| changeset 5086: | 6ee58da0b892 |
| parent: | 200fc3a7ef62 |
| child: | c0f8873b6fbf |
| author: | tiwai |
| date: | Tue May 29 19:01:37 2007 +0200 (4 years ago) |
| permissions: | -rw-r--r-- |
| description: | hda-codec - Fix STAC922x capture boost level STAC922x provides the capture boost level up to 4, but actually it works only up to 2. Since the range of the mixer is automatically defined from amp-capability bits, we need to override the value beforehand. snd_hda_override_amp_caps() is introduced for this purpose. The function patch_stac922x() calls this for NID 0x12 (Mux Capture Volume). This should fix another recording problem on Intel Macs. Patch-level: ASAP |
1/*2 * Universal Interface for Intel High Definition Audio Codec3 *4 * HD audio interface patch for SigmaTel STAC92xx5 *6 * Copyright (c) 2005 Embedded Alley Solutions, Inc.7 * Matt Porter <mporter@embeddedalley.com>8 *9 * Based on patch_cmedia.c and patch_realtek.c10 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>11 *12 * This driver is free software; you can redistribute it and/or modify13 * it under the terms of the GNU General Public License as published by14 * the Free Software Foundation; either version 2 of the License, or15 * (at your option) any later version.16 *17 * This driver is distributed in the hope that it will be useful,18 * but WITHOUT ANY WARRANTY; without even the implied warranty of19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the20 * GNU General Public License for more details.21 *22 * You should have received a copy of the GNU General Public License23 * along with this program; if not, write to the Free Software24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA25 */2627#include <sound/driver.h>28#include <linux/init.h>29#include <linux/delay.h>30#include <linux/slab.h>31#include <linux/pci.h>32#include <sound/core.h>33#include <sound/asoundef.h>34#include "hda_codec.h"35#include "hda_local.h"3637#define NUM_CONTROL_ALLOC 3238#define STAC_HP_EVENT 0x373940enum {41 STAC_REF,42 STAC_9200_MODELS43};4445enum {46 STAC_9205_REF,47 STAC_9205_MODELS48};4950enum {51 STAC_925x_REF,52 STAC_M2_2,53 STAC_MA6,54 STAC_PA6,55 STAC_925x_MODELS56};5758enum {59 STAC_D945_REF,60 STAC_D945GTP3,61 STAC_D945GTP5,62 STAC_INTEL_MAC_V1,63 STAC_INTEL_MAC_V2,64 STAC_INTEL_MAC_V3,65 STAC_INTEL_MAC_V4,66 STAC_INTEL_MAC_V5,67 /* for backward compitability */68 STAC_MACMINI,69 STAC_MACBOOK,70 STAC_MACBOOK_PRO_V1,71 STAC_MACBOOK_PRO_V2,72 STAC_IMAC_INTEL,73 STAC_IMAC_INTEL_20,74 STAC_922X_MODELS75};7677enum {78 STAC_D965_REF,79 STAC_D965_3ST,80 STAC_D965_5ST,81 STAC_927X_MODELS82};8384struct sigmatel_spec {85 struct snd_kcontrol_new *mixers[4];86 unsigned int num_mixers;8788 int board_config;89 unsigned int surr_switch: 1;90 unsigned int line_switch: 1;91 unsigned int mic_switch: 1;92 unsigned int alt_switch: 1;93 unsigned int hp_detect: 1;94 unsigned int gpio_mute: 1;9596 /* playback */97 struct hda_multi_out multiout;98 hda_nid_t dac_nids[5];99100 /* capture */101 hda_nid_t *adc_nids;102 unsigned int num_adcs;103 hda_nid_t *mux_nids;104 unsigned int num_muxes;105 hda_nid_t *dmic_nids;106 unsigned int num_dmics;107 hda_nid_t dmux_nid;108 hda_nid_t dig_in_nid;109110 /* pin widgets */111 hda_nid_t *pin_nids;112 unsigned int num_pins;113 unsigned int *pin_configs;114 unsigned int *bios_pin_configs;115116 /* codec specific stuff */117 struct hda_verb *init;118 struct snd_kcontrol_new *mixer;119120 /* capture source */121 struct hda_input_mux *dinput_mux;122 unsigned int cur_dmux;123 struct hda_input_mux *input_mux;124 unsigned int cur_mux[3];125126 /* i/o switches */127 unsigned int io_switch[2];128129 struct hda_pcm pcm_rec[2]; /* PCM information */130131 /* dynamic controls and input_mux */132 struct auto_pin_cfg autocfg;133 unsigned int num_kctl_alloc, num_kctl_used;134 struct snd_kcontrol_new *kctl_alloc;135 struct hda_input_mux private_dimux;136 struct hda_input_mux private_imux;137};138139static hda_nid_t stac9200_adc_nids[1] = {140 0x03,141};142143static hda_nid_t stac9200_mux_nids[1] = {144 0x0c,145};146147static hda_nid_t stac9200_dac_nids[1] = {148 0x02,149};150151static hda_nid_t stac925x_adc_nids[1] = {152 0x03,153};154155static hda_nid_t stac925x_mux_nids[1] = {156 0x0f,157};158159static hda_nid_t stac925x_dac_nids[1] = {160 0x02,161};162163static hda_nid_t stac925x_dmic_nids[1] = {164 0x15,165};166167static hda_nid_t stac922x_adc_nids[2] = {168 0x06, 0x07,169};170171static hda_nid_t stac922x_mux_nids[2] = {172 0x12, 0x13,173};174175static hda_nid_t stac927x_adc_nids[3] = {176 0x07, 0x08, 0x09177};178179static hda_nid_t stac927x_mux_nids[3] = {180 0x15, 0x16, 0x17181};182183static hda_nid_t stac9205_adc_nids[2] = {184 0x12, 0x13185};186187static hda_nid_t stac9205_mux_nids[2] = {188 0x19, 0x1a189};190191static hda_nid_t stac9205_dmic_nids[2] = {192 0x17, 0x18,193};194195static hda_nid_t stac9200_pin_nids[8] = {196 0x08, 0x09, 0x0d, 0x0e,197 0x0f, 0x10, 0x11, 0x12,198};199200static hda_nid_t stac925x_pin_nids[8] = {201 0x07, 0x08, 0x0a, 0x0b,202 0x0c, 0x0d, 0x10, 0x11,203};204205static hda_nid_t stac922x_pin_nids[10] = {206 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,207 0x0f, 0x10, 0x11, 0x15, 0x1b,208};209210static hda_nid_t stac927x_pin_nids[14] = {211 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,212 0x0f, 0x10, 0x11, 0x12, 0x13,213 0x14, 0x21, 0x22, 0x23,214};215216static hda_nid_t stac9205_pin_nids[12] = {217 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,218 0x0f, 0x14, 0x16, 0x17, 0x18,219 0x21, 0x22,220221};222223static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol,224 struct snd_ctl_elem_info *uinfo)225{226 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);227 struct sigmatel_spec *spec = codec->spec;228 return snd_hda_input_mux_info(spec->dinput_mux, uinfo);229}230231static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol,232 struct snd_ctl_elem_value *ucontrol)233{234 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);235 struct sigmatel_spec *spec = codec->spec;236237 ucontrol->value.enumerated.item[0] = spec->cur_dmux;238 return 0;239}240241static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol,242 struct snd_ctl_elem_value *ucontrol)243{244 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);245 struct sigmatel_spec *spec = codec->spec;246247 return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol,248 spec->dmux_nid, &spec->cur_dmux);249}250251static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)252{253 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);254 struct sigmatel_spec *spec = codec->spec;255 return snd_hda_input_mux_info(spec->input_mux, uinfo);256}257258static int stac92xx_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)259{260 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);261 struct sigmatel_spec *spec = codec->spec;262 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);263264 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];265 return 0;266}267268static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)269{270 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);271 struct sigmatel_spec *spec = codec->spec;272 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);273274 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,275 spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);276}277278static struct hda_verb stac9200_core_init[] = {279 /* set dac0mux for dac converter */280 { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},281 {}282};283284static struct hda_verb stac925x_core_init[] = {285 /* set dac0mux for dac converter */286 { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},287 {}288};289290static struct hda_verb stac922x_core_init[] = {291 /* set master volume and direct control */292 { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},293 {}294};295296static struct hda_verb d965_core_init[] = {297 /* set master volume and direct control */298 { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},299 /* unmute node 0x1b */300 { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},301 /* select node 0x03 as DAC */302 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01},303 {}304};305306static struct hda_verb stac927x_core_init[] = {307 /* set master volume and direct control */308 { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},309 {}310};311312static struct hda_verb stac9205_core_init[] = {313 /* set master volume and direct control */314 { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},315 {}316};317318static struct snd_kcontrol_new stac9200_mixer[] = {319 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),320 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),321 {322 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,323 .name = "Input Source",324 .count = 1,325 .info = stac92xx_mux_enum_info,326 .get = stac92xx_mux_enum_get,327 .put = stac92xx_mux_enum_put,328 },329 HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),330 HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),331 HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT),332 { } /* end */333};334335static struct snd_kcontrol_new stac925x_mixer[] = {336 HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),337 HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),338 {339 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,340 .name = "Input Source",341 .count = 1,342 .info = stac92xx_mux_enum_info,343 .get = stac92xx_mux_enum_get,344 .put = stac92xx_mux_enum_put,345 },346 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),347 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT),348 HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT),349 { } /* end */350};351352/* This needs to be generated dynamically based on sequence */353static struct snd_kcontrol_new stac922x_mixer[] = {354 {355 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,356 .name = "Input Source",357 .count = 1,358 .info = stac92xx_mux_enum_info,359 .get = stac92xx_mux_enum_get,360 .put = stac92xx_mux_enum_put,361 },362 HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),363 HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),364 HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),365 { } /* end */366};367368/* This needs to be generated dynamically based on sequence */369static struct snd_kcontrol_new stac9227_mixer[] = {370 {371 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,372 .name = "Input Source",373 .count = 1,374 .info = stac92xx_mux_enum_info,375 .get = stac92xx_mux_enum_get,376 .put = stac92xx_mux_enum_put,377 },378 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),379 HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT),380 { } /* end */381};382383static struct snd_kcontrol_new stac927x_mixer[] = {384 {385 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,386 .name = "Input Source",387 .count = 1,388 .info = stac92xx_mux_enum_info,389 .get = stac92xx_mux_enum_get,390 .put = stac92xx_mux_enum_put,391 },392 HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT),393 HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT),394 HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT),395 { } /* end */396};397398static struct snd_kcontrol_new stac9205_mixer[] = {399 {400 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,401 .name = "Digital Input Source",402 .count = 1,403 .info = stac92xx_dmux_enum_info,404 .get = stac92xx_dmux_enum_get,405 .put = stac92xx_dmux_enum_put,406 },407 {408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,409 .name = "Input Source",410 .count = 1,411 .info = stac92xx_mux_enum_info,412 .get = stac92xx_mux_enum_get,413 .put = stac92xx_mux_enum_put,414 },415 HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT),416 HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT),417 HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT),418 { } /* end */419};420421static int stac92xx_build_controls(struct hda_codec *codec)422{423 struct sigmatel_spec *spec = codec->spec;424 int err;425 int i;426427 err = snd_hda_add_new_ctls(codec, spec->mixer);428 if (err < 0)429 return err;430431 for (i = 0; i < spec->num_mixers; i++) {432 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);433 if (err < 0)434 return err;435 }436437 if (spec->multiout.dig_out_nid) {438 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);439 if (err < 0)440 return err;441 }442 if (spec->dig_in_nid) {443 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);444 if (err < 0)445 return err;446 }447 return 0;448}449450static unsigned int ref9200_pin_configs[8] = {451 0x01c47010, 0x01447010, 0x0221401f, 0x01114010,452 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,453};454455static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {456 [STAC_REF] = ref9200_pin_configs,457};458459static const char *stac9200_models[STAC_9200_MODELS] = {460 [STAC_REF] = "ref",461};462463static struct snd_pci_quirk stac9200_cfg_tbl[] = {464 /* SigmaTel reference board */465 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,466 "DFI LanParty", STAC_REF),467 /* Dell laptops have BIOS problem */468 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5,469 "Dell Inspiron 630m", STAC_REF),470 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2,471 "Dell Latitude D620", STAC_REF),472 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb,473 "Dell Latitude 120L", STAC_REF),474 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc,475 "Dell Latitude D820", STAC_REF),476 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cd,477 "Dell Inspiron E1705/9400", STAC_REF),478 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ce,479 "Dell XPS M1710", STAC_REF),480 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cf,481 "Dell Precision M90", STAC_REF),482 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6,483 "unknown Dell", STAC_REF),484 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8,485 "Dell Inspiron 640m", STAC_REF),486 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5,487 "Dell Inspiron 1501", STAC_REF),488489 /* Panasonic */490 SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),491492 {} /* terminator */493};494495static unsigned int ref925x_pin_configs[8] = {496 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,497 0x90a70320, 0x02214210, 0x400003f1, 0x9033032e,498};499500static unsigned int stac925x_MA6_pin_configs[8] = {501 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,502 0x90a70320, 0x90100211, 0x400003f1, 0x9033032e,503};504505static unsigned int stac925x_PA6_pin_configs[8] = {506 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,507 0x50a103f0, 0x90100211, 0x400003f1, 0x9033032e,508};509510static unsigned int stac925xM2_2_pin_configs[8] = {511 0x40c003f3, 0x424503f2, 0x04180011, 0x02a19020,512 0x50a103f0, 0x90100212, 0x400003f1, 0x9033032e,513};514515static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {516 [STAC_REF] = ref925x_pin_configs,517 [STAC_M2_2] = stac925xM2_2_pin_configs,518 [STAC_MA6] = stac925x_MA6_pin_configs,519 [STAC_PA6] = stac925x_PA6_pin_configs,520};521522static const char *stac925x_models[STAC_925x_MODELS] = {523 [STAC_REF] = "ref",524 [STAC_M2_2] = "m2-2",525 [STAC_MA6] = "m6",526 [STAC_PA6] = "pa6",527};528529static struct snd_pci_quirk stac925x_cfg_tbl[] = {530 /* SigmaTel reference board */531 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),532 SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF),533 SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_REF),534 SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_REF),535 SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_MA6),536 SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_PA6),537 SND_PCI_QUIRK(0x1002, 0x437b, "Gateway MX6453", STAC_M2_2),538 {} /* terminator */539};540541static unsigned int ref922x_pin_configs[10] = {542 0x01014010, 0x01016011, 0x01012012, 0x0221401f,543 0x01813122, 0x01011014, 0x01441030, 0x01c41030,544 0x40000100, 0x40000100,545};546547static unsigned int d945gtp3_pin_configs[10] = {548 0x0221401f, 0x01a19022, 0x01813021, 0x01014010,549 0x40000100, 0x40000100, 0x40000100, 0x40000100,550 0x02a19120, 0x40000100,551};552553static unsigned int d945gtp5_pin_configs[10] = {554 0x0221401f, 0x01011012, 0x01813024, 0x01014010,555 0x01a19021, 0x01016011, 0x01452130, 0x40000100,556 0x02a19320, 0x40000100,557};558559static unsigned int intel_mac_v1_pin_configs[10] = {560 0x0121e21f, 0x400000ff, 0x9017e110, 0x400000fd,561 0x400000fe, 0x0181e020, 0x1145e030, 0x11c5e240,562 0x400000fc, 0x400000fb,563};564565static unsigned int intel_mac_v2_pin_configs[10] = {566 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,567 0x400000fe, 0x0181e020, 0x1145e230, 0x500000fa,568 0x400000fc, 0x400000fb,569};570571static unsigned int intel_mac_v3_pin_configs[10] = {572 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd,573 0x400000fe, 0x0181e020, 0x1145e230, 0x11c5e240,574 0x400000fc, 0x400000fb,575};576577static unsigned int intel_mac_v4_pin_configs[10] = {578 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,579 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,580 0x400000fc, 0x400000fb,581};582583static unsigned int intel_mac_v5_pin_configs[10] = {584 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f,585 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240,586 0x400000fc, 0x400000fb,587};588589static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {590 [STAC_D945_REF] = ref922x_pin_configs,591 [STAC_D945GTP3] = d945gtp3_pin_configs,592 [STAC_D945GTP5] = d945gtp5_pin_configs,593 [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs,594 [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs,595 [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs,596 [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs,597 [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs,598 /* for backward compitability */599 [STAC_MACMINI] = intel_mac_v3_pin_configs,600 [STAC_MACBOOK] = intel_mac_v5_pin_configs,601 [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs,602 [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs,603 [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs,604 [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs,605};606607static const char *stac922x_models[STAC_922X_MODELS] = {608 [STAC_D945_REF] = "ref",609 [STAC_D945GTP5] = "5stack",610 [STAC_D945GTP3] = "3stack",611 [STAC_INTEL_MAC_V1] = "intel-mac-v1",612 [STAC_INTEL_MAC_V2] = "intel-mac-v2",613 [STAC_INTEL_MAC_V3] = "intel-mac-v3",614 [STAC_INTEL_MAC_V4] = "intel-mac-v4",615 [STAC_INTEL_MAC_V5] = "intel-mac-v5",616 /* for backward compitability */617 [STAC_MACMINI] = "macmini",618 [STAC_MACBOOK] = "macbook",619 [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1",620 [STAC_MACBOOK_PRO_V2] = "macbook-pro",621 [STAC_IMAC_INTEL] = "imac-intel",622 [STAC_IMAC_INTEL_20] = "imac-intel-20",623};624625static struct snd_pci_quirk stac922x_cfg_tbl[] = {626 /* SigmaTel reference board */627 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,628 "DFI LanParty", STAC_D945_REF),629 /* Intel 945G based systems */630 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101,631 "Intel D945G", STAC_D945GTP3),632 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202,633 "Intel D945G", STAC_D945GTP3),634 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606,635 "Intel D945G", STAC_D945GTP3),636 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601,637 "Intel D945G", STAC_D945GTP3),638 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111,639 "Intel D945G", STAC_D945GTP3),640 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115,641 "Intel D945G", STAC_D945GTP3),642 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116,643 "Intel D945G", STAC_D945GTP3),644 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117,645 "Intel D945G", STAC_D945GTP3),646 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118,647 "Intel D945G", STAC_D945GTP3),648 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119,649 "Intel D945G", STAC_D945GTP3),650 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826,651 "Intel D945G", STAC_D945GTP3),652 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049,653 "Intel D945G", STAC_D945GTP3),654 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055,655 "Intel D945G", STAC_D945GTP3),656 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048,657 "Intel D945G", STAC_D945GTP3),658 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110,659 "Intel D945G", STAC_D945GTP3),660 /* Intel D945G 5-stack systems */661 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404,662 "Intel D945G", STAC_D945GTP5),663 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303,664 "Intel D945G", STAC_D945GTP5),665 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013,666 "Intel D945G", STAC_D945GTP5),667 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417,668 "Intel D945G", STAC_D945GTP5),669 /* Intel 945P based systems */670 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b,671 "Intel D945P", STAC_D945GTP3),672 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112,673 "Intel D945P", STAC_D945GTP3),674 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d,675 "Intel D945P", STAC_D945GTP3),676 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909,677 "Intel D945P", STAC_D945GTP3),678 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505,679 "Intel D945P", STAC_D945GTP3),680 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707,681 "Intel D945P", STAC_D945GTP5),682 /* other systems */683 /* Apple Mac Mini (early 2006) */684 SND_PCI_QUIRK(0x8384, 0x7680,685 "Mac Mini", STAC_INTEL_MAC_V3),686 {} /* terminator */687};688689static unsigned int ref927x_pin_configs[14] = {690 0x02214020, 0x02a19080, 0x0181304e, 0x01014010,691 0x01a19040, 0x01011012, 0x01016011, 0x0101201f,692 0x183301f0, 0x18a001f0, 0x18a001f0, 0x01442070,693 0x01c42190, 0x40000100,694};695696static unsigned int d965_3st_pin_configs[14] = {697 0x0221401f, 0x02a19120, 0x40000100, 0x01014011,698 0x01a19021, 0x01813024, 0x40000100, 0x40000100,699 0x40000100, 0x40000100, 0x40000100, 0x40000100,700 0x40000100, 0x40000100701};702703static unsigned int d965_5st_pin_configs[14] = {704 0x02214020, 0x02a19080, 0x0181304e, 0x01014010,705 0x01a19040, 0x01011012, 0x01016011, 0x40000100,706 0x40000100, 0x40000100, 0x40000100, 0x01442070,707 0x40000100, 0x40000100708};709710static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {711 [STAC_D965_REF] = ref927x_pin_configs,712 [STAC_D965_3ST] = d965_3st_pin_configs,713 [STAC_D965_5ST] = d965_5st_pin_configs,714};715716static const char *stac927x_models[STAC_927X_MODELS] = {717 [STAC_D965_REF] = "ref",718 [STAC_D965_3ST] = "3stack",719 [STAC_D965_5ST] = "5stack",720};721722static struct snd_pci_quirk stac927x_cfg_tbl[] = {723 /* SigmaTel reference board */724 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,725 "DFI LanParty", STAC_D965_REF),726 /* Intel 946 based systems */727 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST),728 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST),729 /* 965 based 3 stack systems */730 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST),731 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST),732 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST),733 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST),734 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST),735 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST),736 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST),737 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST),738 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST),739 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST),740 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST),741 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST),742 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST),743 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST),744 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST),745 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST),746 /* 965 based 5 stack systems */747 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST),748 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST),749 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST),750 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST),751 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST),752 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST),753 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST),754 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST),755 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST),756 {} /* terminator */757};758759static unsigned int ref9205_pin_configs[12] = {760 0x40000100, 0x40000100, 0x01016011, 0x01014010,761 0x01813122, 0x01a19021, 0x40000100, 0x40000100,762 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030763};764765static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {766 ref9205_pin_configs,767};768769static const char *stac9205_models[STAC_9205_MODELS] = {770 [STAC_9205_REF] = "ref",771};772773static struct snd_pci_quirk stac9205_cfg_tbl[] = {774 /* SigmaTel reference board */775 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,776 "DFI LanParty", STAC_9205_REF),777 {} /* terminator */778};779780static int stac92xx_save_bios_config_regs(struct hda_codec *codec)781{782 int i;783 struct sigmatel_spec *spec = codec->spec;784785 if (! spec->bios_pin_configs) {786 spec->bios_pin_configs = kcalloc(spec->num_pins,787 sizeof(*spec->bios_pin_configs), GFP_KERNEL);788 if (! spec->bios_pin_configs)789 return -ENOMEM;790 }791792 for (i = 0; i < spec->num_pins; i++) {793 hda_nid_t nid = spec->pin_nids[i];794 unsigned int pin_cfg;795796 pin_cfg = snd_hda_codec_read(codec, nid, 0,797 AC_VERB_GET_CONFIG_DEFAULT, 0x00);798 snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n",799 nid, pin_cfg);800 spec->bios_pin_configs[i] = pin_cfg;801 }802803 return 0;804}805806static void stac92xx_set_config_regs(struct hda_codec *codec)807{808 int i;809 struct sigmatel_spec *spec = codec->spec;810 unsigned int pin_cfg;811812 if (! spec->pin_nids || ! spec->pin_configs)813 return;814815 for (i = 0; i < spec->num_pins; i++) {816 snd_hda_codec_write(codec, spec->pin_nids[i], 0,817 AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,818 spec->pin_configs[i] & 0x000000ff);819 snd_hda_codec_write(codec, spec->pin_nids[i], 0,820 AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,821 (spec->pin_configs[i] & 0x0000ff00) >> 8);822 snd_hda_codec_write(codec, spec->pin_nids[i], 0,823 AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,824 (spec->pin_configs[i] & 0x00ff0000) >> 16);825 snd_hda_codec_write(codec, spec->pin_nids[i], 0,826 AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,827 spec->pin_configs[i] >> 24);828 pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,829 AC_VERB_GET_CONFIG_DEFAULT,830 0x00);831 snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);832 }833}834835/*836 * Analog playback callbacks837 */838static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,839 struct hda_codec *codec,840 struct snd_pcm_substream *substream)841{842 struct sigmatel_spec *spec = codec->spec;843 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);844}845846static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,847 struct hda_codec *codec,848 unsigned int stream_tag,849 unsigned int format,850 struct snd_pcm_substream *substream)851{852 struct sigmatel_spec *spec = codec->spec;853 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, format, substream);854}855856static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,857 struct hda_codec *codec,858 struct snd_pcm_substream *substream)859{860 struct sigmatel_spec *spec = codec->spec;861 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);862}863864/*865 * Digital playback callbacks866 */867static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,868 struct hda_codec *codec,869 struct snd_pcm_substream *substream)870{871 struct sigmatel_spec *spec = codec->spec;872 return snd_hda_multi_out_dig_open(codec, &spec->multiout);873}874875static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,876 struct hda_codec *codec,877 struct snd_pcm_substream *substream)878{879 struct sigmatel_spec *spec = codec->spec;880 return snd_hda_multi_out_dig_close(codec, &spec->multiout);881}882883static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,884 struct hda_codec *codec,885 unsigned int stream_tag,886 unsigned int format,887 struct snd_pcm_substream *substream)888{889 struct sigmatel_spec *spec = codec->spec;890 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,891 stream_tag, format, substream);892}893894895/*896 * Analog capture callbacks897 */898static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,899 struct hda_codec *codec,900 unsigned int stream_tag,901 unsigned int format,902 struct snd_pcm_substream *substream)903{904 struct sigmatel_spec *spec = codec->spec;905906 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],907 stream_tag, 0, format);908 return 0;909}910911static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,912 struct hda_codec *codec,913 struct snd_pcm_substream *substream)914{915 struct sigmatel_spec *spec = codec->spec;916917 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);918 return 0;919}920921static struct hda_pcm_stream stac92xx_pcm_digital_playback = {922 .substreams = 1,923 .channels_min = 2,924 .channels_max = 2,925 /* NID is set in stac92xx_build_pcms */926 .ops = {927 .open = stac92xx_dig_playback_pcm_open,928 .close = stac92xx_dig_playback_pcm_close,929 .prepare = stac92xx_dig_playback_pcm_prepare930 },931};932933static struct hda_pcm_stream stac92xx_pcm_digital_capture = {934 .substreams = 1,935 .channels_min = 2,936 .channels_max = 2,937 /* NID is set in stac92xx_build_pcms */938};939940static struct hda_pcm_stream stac92xx_pcm_analog_playback = {941 .substreams = 1,942 .channels_min = 2,943 .channels_max = 8,944 .nid = 0x02, /* NID to query formats and rates */945 .ops = {946 .open = stac92xx_playback_pcm_open,947 .prepare = stac92xx_playback_pcm_prepare,948 .cleanup = stac92xx_playback_pcm_cleanup949 },950};951952static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = {953 .substreams = 1,954 .channels_min = 2,955 .channels_max = 2,956 .nid = 0x06, /* NID to query formats and rates */957 .ops = {958 .open = stac92xx_playback_pcm_open,959 .prepare = stac92xx_playback_pcm_prepare,960 .cleanup = stac92xx_playback_pcm_cleanup961 },962};963964static struct hda_pcm_stream stac92xx_pcm_analog_capture = {965 .substreams = 2,966 .channels_min = 2,967 .channels_max = 2,968 /* NID is set in stac92xx_build_pcms */969 .ops = {970 .prepare = stac92xx_capture_pcm_prepare,971 .cleanup = stac92xx_capture_pcm_cleanup972 },973};974975static int stac92xx_build_pcms(struct hda_codec *codec)976{977 struct sigmatel_spec *spec = codec->spec;978 struct hda_pcm *info = spec->pcm_rec;979980 codec->num_pcms = 1;981 codec->pcm_info = info;982983 info->name = "STAC92xx Analog";984 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;985 info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;986 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];987988 if (spec->alt_switch) {989 codec->num_pcms++;990 info++;991 info->name = "STAC92xx Analog Alt";992 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_alt_playback;993 }994995 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {996 codec->num_pcms++;997 info++;998 info->name = "STAC92xx Digital";999 if (spec->multiout.dig_out_nid) {1000 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;1001 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;1002 }1003 if (spec->dig_in_nid) {1004 info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture;1005 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;1006 }1007 }10081009 return 0;1010}10111012static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)1013{1014 unsigned int pincap = snd_hda_param_read(codec, nid,1015 AC_PAR_PIN_CAP);1016 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;1017 if (pincap & AC_PINCAP_VREF_100)1018 return AC_PINCTL_VREF_100;1019 if (pincap & AC_PINCAP_VREF_80)1020 return AC_PINCTL_VREF_80;1021 if (pincap & AC_PINCAP_VREF_50)1022 return AC_PINCTL_VREF_50;1023 if (pincap & AC_PINCAP_VREF_GRD)1024 return AC_PINCTL_VREF_GRD;1025 return 0;1026}10271028static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)10291030{1031 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);1032}10331034static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)1035{1036 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;1037 uinfo->count = 1;1038 uinfo->value.integer.min = 0;1039 uinfo->value.integer.max = 1;1040 return 0;1041}10421043static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)1044{1045 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);1046 struct sigmatel_spec *spec = codec->spec;1047 int io_idx = kcontrol-> private_value & 0xff;10481049 ucontrol->value.integer.value[0] = spec->io_switch[io_idx];1050 return 0;1051}10521053static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)1054{1055 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);1056 struct sigmatel_spec *spec = codec->spec;1057 hda_nid_t nid = kcontrol->private_value >> 8;1058 int io_idx = kcontrol-> private_value & 0xff;1059 unsigned short val = ucontrol->value.integer.value[0];10601061 spec->io_switch[io_idx] = val;10621063 if (val)1064 stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);1065 else {1066 unsigned int pinctl = AC_PINCTL_IN_EN;1067 if (io_idx) /* set VREF for mic */1068 pinctl |= stac92xx_get_vref(codec, nid);1069 stac92xx_auto_set_pinctl(codec, nid, pinctl);1070 }1071 return 1;1072}10731074#define STAC_CODEC_IO_SWITCH(xname, xpval) \1075 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \1076 .name = xname, \1077 .index = 0, \1078 .info = stac92xx_io_switch_info, \1079 .get = stac92xx_io_switch_get, \1080 .put = stac92xx_io_switch_put, \1081 .private_value = xpval, \1082 }108310841085enum {1086 STAC_CTL_WIDGET_VOL,1087 STAC_CTL_WIDGET_MUTE,1088 STAC_CTL_WIDGET_IO_SWITCH,1089};10901091static struct snd_kcontrol_new stac92xx_control_templates[] = {1092 HDA_CODEC_VOLUME(NULL, 0, 0, 0),1093 HDA_CODEC_MUTE(NULL, 0, 0, 0),1094 STAC_CODEC_IO_SWITCH(NULL, 0),1095};10961097/* add dynamic controls */1098static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char *name, unsigned long val)1099{1100 struct snd_kcontrol_new *knew;11011102 if (spec->num_kctl_used >= spec->num_kctl_alloc) {1103 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;11041105 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */1106 if (! knew)1107 return -ENOMEM;1108 if (spec->kctl_alloc) {1109 memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);1110 kfree(spec->kctl_alloc);1111 }1112 spec->kctl_alloc = knew;1113 spec->num_kctl_alloc = num;1114 }11151116 knew = &spec->kctl_alloc[spec->num_kctl_used];1117 *knew = stac92xx_control_templates[type];1118 knew->name = kstrdup(name, GFP_KERNEL);1119 if (! knew->name)1120 return -ENOMEM;1121 knew->private_value = val;1122 spec->num_kctl_used++;1123 return 0;1124}11251126/* flag inputs as additional dynamic lineouts */1127static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg)1128{1129 struct sigmatel_spec *spec = codec->spec;1130 unsigned int wcaps, wtype;1131 int i, num_dacs = 0;11321133 /* use the wcaps cache to count all DACs available for line-outs */1134 for (i = 0; i < codec->num_nodes; i++) {1135 wcaps = codec->wcaps[i];1136 wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;1137 if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL))1138 num_dacs++;1139 }11401141 snd_printdd("%s: total dac count=%d\n", __func__, num_dacs);11421143 switch (cfg->line_outs) {1144 case 3:1145 /* add line-in as side */1146 if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) {1147 cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE];1148 spec->line_switch = 1;1149 cfg->line_outs++;1150 }1151 break;1152 case 2:1153 /* add line-in as clfe and mic as side */1154 if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) {1155 cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE];1156 spec->line_switch = 1;1157 cfg->line_outs++;1158 }1159 if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) {1160 cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC];1161 spec->mic_switch = 1;1162 cfg->line_outs++;1163 }1164 break;1165 case 1:1166 /* add line-in as surr and mic as clfe */1167 if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) {1168 cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE];1169 spec->line_switch = 1;1170 cfg->line_outs++;1171 }1172 if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) {1173 cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC];1174 spec->mic_switch = 1;1175 cfg->line_outs++;1176 }1177 break;1178 }11791180 return 0;1181}118211831184static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)1185{1186 int i;11871188 for (i = 0; i < spec->multiout.num_dacs; i++) {1189 if (spec->multiout.dac_nids[i] == nid)1190 return 1;1191 }11921193 return 0;1194}11951196/*1197 * Fill in the dac_nids table from the parsed pin configuration1198 * This function only works when every pin in line_out_pins[]1199 * contains atleast one DAC in its connection list. Some 92xx1200 * codecs are not connected directly to a DAC, such as the 92001201 * and 9202/925x. For those, dac_nids[] must be hard-coded.1202 */1203static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,1204 const struct auto_pin_cfg *cfg)1205{1206 struct sigmatel_spec *spec = codec->spec;1207 int i, j, conn_len = 0;1208 hda_nid_t nid, conn[HDA_MAX_CONNECTIONS];1209 unsigned int wcaps, wtype;12101211 for (i = 0; i < cfg->line_outs; i++) {1212 nid = cfg->line_out_pins[i];1213 conn_len = snd_hda_get_connections(codec, nid, conn,1214 HDA_MAX_CONNECTIONS);1215 for (j = 0; j < conn_len; j++) {1216 wcaps = snd_hda_param_read(codec, conn[j],1217 AC_PAR_AUDIO_WIDGET_CAP);1218 wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;12191220 if (wtype != AC_WID_AUD_OUT ||1221 (wcaps & AC_WCAP_DIGITAL))1222 continue;1223 /* conn[j] is a DAC routed to this line-out */1224 if (!is_in_dac_nids(spec, conn[j]))1225 break;1226 }12271228 if (j == conn_len) {1229 /* error out, no available DAC found */1230 snd_printk(KERN_ERR1231 "%s: No available DAC for pin 0x%x\n",1232 __func__, nid);1233 return -ENODEV;1234 }12351236 spec->multiout.dac_nids[i] = conn[j];1237 spec->multiout.num_dacs++;1238 if (conn_len > 1) {1239 /* select this DAC in the pin's input mux */1240 snd_hda_codec_write(codec, nid, 0,1241 AC_VERB_SET_CONNECT_SEL, j);12421243 }1244 }12451246 snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",1247 spec->multiout.num_dacs,1248 spec->multiout.dac_nids[0],1249 spec->multiout.dac_nids[1],1250 spec->multiout.dac_nids[2],1251 spec->multiout.dac_nids[3],1252 spec->multiout.dac_nids[4]);1253 return 0;1254}12551256/* create volume control/switch for the given prefx type */1257static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs)1258{1259 char name[32];1260 int err;12611262 sprintf(name, "%s Playback Volume", pfx);1263 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,1264 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));1265 if (err < 0)1266 return err;1267 sprintf(name, "%s Playback Switch", pfx);1268 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name,1269 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));1270 if (err < 0)1271 return err;1272 return 0;1273}12741275/* add playback controls from the parsed DAC table */1276static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,1277 const struct auto_pin_cfg *cfg)1278{1279 static const char *chname[4] = {1280 "Front", "Surround", NULL /*CLFE*/, "Side"1281 };1282 hda_nid_t nid;1283 int i, err;12841285 for (i = 0; i < cfg->line_outs; i++) {1286 if (!spec->multiout.dac_nids[i])1287 continue;12881289 nid = spec->multiout.dac_nids[i];12901291 if (i == 2) {1292 /* Center/LFE */1293 err = create_controls(spec, "Center", nid, 1);1294 if (err < 0)1295 return err;1296 err = create_controls(spec, "LFE", nid, 2);1297 if (err < 0)1298 return err;1299 } else {1300 err = create_controls(spec, chname[i], nid, 3);1301 if (err < 0)1302 return err;1303 }1304 }13051306 if (spec->line_switch)1307 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, "Line In as Output Switch", cfg->input_pins[AUTO_PIN_LINE] << 8)) < 0)1308 return err;13091310 if (spec->mic_switch)1311 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, "Mic as Output Switch", (cfg->input_pins[AUTO_PIN_MIC] << 8) | 1)) < 0)1312 return err;13131314 return 0;1315}13161317static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)1318{1319 if (is_in_dac_nids(spec, nid))1320 return 1;1321 if (spec->multiout.hp_nid == nid)1322 return 1;1323 return 0;1324}13251326static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)1327{1328 if (!spec->multiout.hp_nid)1329 spec->multiout.hp_nid = nid;1330 else if (spec->multiout.num_dacs > 4) {1331 printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);1332 return 1;1333 } else {1334 spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;1335 spec->multiout.num_dacs++;1336 }1337 return 0;1338}13391340/* add playback controls for Speaker and HP outputs */1341static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,1342 struct auto_pin_cfg *cfg)1343{1344 struct sigmatel_spec *spec = codec->spec;1345 hda_nid_t nid;1346 int i, old_num_dacs, err;13471348 old_num_dacs = spec->multiout.num_dacs;1349 for (i = 0; i < cfg->hp_outs; i++) {1350 unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);1351 if (wid_caps & AC_WCAP_UNSOL_CAP)1352 spec->hp_detect = 1;1353 nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,1354 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;1355 if (check_in_dac_nids(spec, nid))1356 nid = 0;1357 if (! nid)1358 continue;1359 add_spec_dacs(spec, nid);1360 }1361 for (i = 0; i < cfg->speaker_outs; i++) {1362 nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0,1363 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;1364 if (check_in_dac_nids(spec, nid))1365 nid = 0;1366 if (! nid)1367 continue;1368 add_spec_dacs(spec, nid);1369 }13701371 for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) {1372 static const char *pfxs[] = {1373 "Speaker", "External Speaker", "Speaker2",1374 };1375 err = create_controls(spec, pfxs[i - old_num_dacs],1376 spec->multiout.dac_nids[i], 3);1377 if (err < 0)1378 return err;1379 }1380 if (spec->multiout.hp_nid) {1381 const char *pfx;1382 if (old_num_dacs == spec->multiout.num_dacs)1383 pfx = "Master";1384 else1385 pfx = "Headphone";1386 err = create_controls(spec, pfx, spec->multiout.hp_nid, 3);1387 if (err < 0)1388 return err;1389 }13901391 return 0;1392}13931394/* labels for dmic mux inputs */1395static const char *stac92xx_dmic_labels[5] = {1396 "Analog Inputs", "Digital Mic 1", "Digital Mic 2",1397 "Digital Mic 3", "Digital Mic 4"1398};13991400/* create playback/capture controls for input pins on dmic capable codecs */1401static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,1402 const struct auto_pin_cfg *cfg)1403{1404 struct sigmatel_spec *spec = codec->spec;1405 struct hda_input_mux *dimux = &spec->private_dimux;1406 hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];1407 int i, j;14081409 dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0];1410 dimux->items[dimux->num_items].index = 0;1411 dimux->num_items++;14121413 for (i = 0; i < spec->num_dmics; i++) {1414 int index;1415 int num_cons;1416 unsigned int def_conf;14171418 def_conf = snd_hda_codec_read(codec,1419 spec->dmic_nids[i],1420 0,1421 AC_VERB_GET_CONFIG_DEFAULT,1422 0);1423 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)1424 continue;14251426 num_cons = snd_hda_get_connections(codec,1427 spec->dmux_nid,1428 con_lst,1429 HDA_MAX_NUM_INPUTS);1430 for (j = 0; j < num_cons; j++)1431 if (con_lst[j] == spec->dmic_nids[i]) {1432 index = j;1433 goto found;1434 }1435 continue;1436found:1437 dimux->items[dimux->num_items].label =1438 stac92xx_dmic_labels[dimux->num_items];1439 dimux->items[dimux->num_items].index = index;1440 dimux->num_items++;1441 }14421443 return 0;1444}14451446/* create playback/capture controls for input pins */1447static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg)1448{1449 struct sigmatel_spec *spec = codec->spec;1450 struct hda_input_mux *imux = &spec->private_imux;1451 hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];1452 int i, j, k;14531454 for (i = 0; i < AUTO_PIN_LAST; i++) {1455 int index;14561457 if (!cfg->input_pins[i])1458 continue;1459 index = -1;1460 for (j = 0; j < spec->num_muxes; j++) {1461 int num_cons;1462 num_cons = snd_hda_get_connections(codec,1463 spec->mux_nids[j],1464 con_lst,1465 HDA_MAX_NUM_INPUTS);1466 for (k = 0; k < num_cons; k++)1467 if (con_lst[k] == cfg->input_pins[i]) {1468 index = k;1469 goto found;1470 }1471 }1472 continue;1473 found:1474 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];1475 imux->items[imux->num_items].index = index;1476 imux->num_items++;1477 }14781479 if (imux->num_items) {1480 /*1481 * Set the current input for the muxes.1482 * The STAC9221 has two input muxes with identical source1483 * NID lists. Hopefully this won't get confused.1484 */1485 for (i = 0; i < spec->num_muxes; i++) {1486 snd_hda_codec_write(codec, spec->mux_nids[i], 0,1487 AC_VERB_SET_CONNECT_SEL,1488 imux->items[0].index);1489 }1490 }14911492 return 0;1493}14941495static void stac92xx_auto_init_multi_out(struct hda_codec *codec)1496{1497 struct sigmatel_spec *spec = codec->spec;1498 int i;14991500 for (i = 0; i < spec->autocfg.line_outs; i++) {1501 hda_nid_t nid = spec->autocfg.line_out_pins[i];1502 stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);1503 }1504}15051506static void stac92xx_auto_init_hp_out(struct hda_codec *codec)1507{1508 struct sigmatel_spec *spec = codec->spec;1509 int i;15101511 for (i = 0; i < spec->autocfg.hp_outs; i++) {1512 hda_nid_t pin;1513 pin = spec->autocfg.hp_pins[i];1514 if (pin) /* connect to front */1515 stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);1516 }1517 for (i = 0; i < spec->autocfg.speaker_outs; i++) {1518 hda_nid_t pin;1519 pin = spec->autocfg.speaker_pins[i];1520 if (pin) /* connect to front */1521 stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN);1522 }1523}15241525static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)1526{1527 struct sigmatel_spec *spec = codec->spec;1528 int err;15291530 if ((err = snd_hda_parse_pin_def_config(codec,1531 &spec->autocfg,1532 spec->dmic_nids)) < 0)1533 return err;1534 if (! spec->autocfg.line_outs)1535 return 0; /* can't find valid pin config */15361537 if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0)1538 return err;1539 if (spec->multiout.num_dacs == 0)1540 if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)1541 return err;15421543 if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||1544 (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 ||1545 (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)1546 return err;15471548 if (spec->num_dmics > 0)1549 if ((err = stac92xx_auto_create_dmic_input_ctls(codec,1550 &spec->autocfg)) < 0)1551 return err;15521553 spec->multiout.max_channels = spec->multiout.num_dacs * 2;1554 if (spec->multiout.max_channels > 2)1555 spec->surr_switch = 1;15561557 if (spec->autocfg.dig_out_pin)1558 spec->multiout.dig_out_nid = dig_out;1559 if (spec->autocfg.dig_in_pin)1560 spec->dig_in_nid = dig_in;15611562 if (spec->kctl_alloc)1563 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;15641565 spec->input_mux = &spec->private_imux;1566 spec->dinput_mux = &spec->private_dimux;15671568 return 1;1569}15701571/* add playback controls for HP output */1572static int stac9200_auto_create_hp_ctls(struct hda_codec *codec,1573 struct auto_pin_cfg *cfg)1574{1575 struct sigmatel_spec *spec = codec->spec;1576 hda_nid_t pin = cfg->hp_pins[0];1577 unsigned int wid_caps;15781579 if (! pin)1580 return 0;15811582 wid_caps = get_wcaps(codec, pin);1583 if (wid_caps & AC_WCAP_UNSOL_CAP)1584 spec->hp_detect = 1;15851586 return 0;1587}15881589/* add playback controls for LFE output */1590static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,1591 struct auto_pin_cfg *cfg)1592{1593 struct sigmatel_spec *spec = codec->spec;1594 int err;1595 hda_nid_t lfe_pin = 0x0;1596 int i;15971598 /*1599 * search speaker outs and line outs for a mono speaker pin1600 * with an amp. If one is found, add LFE controls1601 * for it.1602 */1603 for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) {1604 hda_nid_t pin = spec->autocfg.speaker_pins[i];1605 unsigned long wcaps = get_wcaps(codec, pin);1606 wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);1607 if (wcaps == AC_WCAP_OUT_AMP)1608 /* found a mono speaker with an amp, must be lfe */1609 lfe_pin = pin;1610 }16111612 /* if speaker_outs is 0, then speakers may be in line_outs */1613 if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) {1614 for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) {1615 hda_nid_t pin = spec->autocfg.line_out_pins[i];1616 unsigned long cfg;1617 cfg = snd_hda_codec_read(codec, pin, 0,1618 AC_VERB_GET_CONFIG_DEFAULT,1619 0x00);1620 if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) {1621 unsigned long wcaps = get_wcaps(codec, pin);1622 wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP);1623 if (wcaps == AC_WCAP_OUT_AMP)1624 /* found a mono speaker with an amp,1625 must be lfe */1626 lfe_pin = pin;1627 }1628 }1629 }16301631 if (lfe_pin) {1632 err = create_controls(spec, "LFE", lfe_pin, 1);1633 if (err < 0)1634 return err;1635 }16361637 return 0;1638}16391640static int stac9200_parse_auto_config(struct hda_codec *codec)1641{1642 struct sigmatel_spec *spec = codec->spec;1643 int err;16441645 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)1646 return err;16471648 if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)1649 return err;16501651 if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0)1652 return err;16531654 if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0)1655 return err;16561657 if (spec->autocfg.dig_out_pin)1658 spec->multiout.dig_out_nid = 0x05;1659 if (spec->autocfg.dig_in_pin)1660 spec->dig_in_nid = 0x04;16611662 if (spec->kctl_alloc)1663 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;16641665 spec->input_mux = &spec->private_imux;1666 spec->dinput_mux = &spec->private_dimux;16671668 return 1;1669}16701671/*1672 * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a1673 * funky external mute control using GPIO pins.1674 */16751676static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted)1677{1678 unsigned int gpiostate, gpiomask, gpiodir;16791680 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,1681 AC_VERB_GET_GPIO_DATA, 0);16821683 if (!muted)1684 gpiostate |= (1 << pin);1685 else1686 gpiostate &= ~(1 << pin);16871688 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,1689 AC_VERB_GET_GPIO_MASK, 0);1690 gpiomask |= (1 << pin);16911692 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,1693 AC_VERB_GET_GPIO_DIRECTION, 0);1694 gpiodir |= (1 << pin);16951696 /* AppleHDA seems to do this -- WTF is this verb?? */1697 snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0);16981699 snd_hda_codec_write(codec, codec->afg, 0,1700 AC_VERB_SET_GPIO_MASK, gpiomask);1701 snd_hda_codec_write(codec, codec->afg, 0,1702 AC_VERB_SET_GPIO_DIRECTION, gpiodir);17031704 msleep(1);17051706 snd_hda_codec_write(codec, codec->afg, 0,1707 AC_VERB_SET_GPIO_DATA, gpiostate);1708}17091710static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,1711 unsigned int event)1712{1713 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)1714 snd_hda_codec_write(codec, nid, 0,1715 AC_VERB_SET_UNSOLICITED_ENABLE,1716 (AC_USRSP_EN | event));1717}17181719static int stac92xx_init(struct hda_codec *codec)1720{1721 struct sigmatel_spec *spec = codec->spec;1722 struct auto_pin_cfg *cfg = &spec->autocfg;1723 int i;17241725 snd_hda_sequence_write(codec, spec->init);17261727 /* set up pins */1728 if (spec->hp_detect) {1729 /* Enable unsolicited responses on the HP widget */1730 for (i = 0; i < cfg->hp_outs; i++)1731 enable_pin_detect(codec, cfg->hp_pins[i],1732 STAC_HP_EVENT);1733 /* force to enable the first line-out; the others are set up1734 * in unsol_event1735 */1736 stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],1737 AC_PINCTL_OUT_EN);1738 stac92xx_auto_init_hp_out(codec);1739 /* fake event to set up pins */1740 codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);1741 } else {1742 stac92xx_auto_init_multi_out(codec);1743 stac92xx_auto_init_hp_out(codec);1744 }1745 for (i = 0; i < AUTO_PIN_LAST; i++) {1746 hda_nid_t nid = cfg->input_pins[i];1747 if (nid) {1748 unsigned int pinctl = AC_PINCTL_IN_EN;1749 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC)1750 pinctl |= stac92xx_get_vref(codec, nid);1751 stac92xx_auto_set_pinctl(codec, nid, pinctl);1752 }1753 }1754 if (spec->num_dmics > 0)1755 for (i = 0; i < spec->num_dmics; i++)1756 stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],1757 AC_PINCTL_IN_EN);17581759 if (cfg->dig_out_pin)1760 stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,1761 AC_PINCTL_OUT_EN);1762 if (cfg->dig_in_pin)1763 stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,1764 AC_PINCTL_IN_EN);17651766 if (spec->gpio_mute) {1767 stac922x_gpio_mute(codec, 0, 0);1768 stac922x_gpio_mute(codec, 1, 0);1769 }17701771 return 0;1772}17731774static void stac92xx_free(struct hda_codec *codec)1775{1776 struct sigmatel_spec *spec = codec->spec;1777 int i;17781779 if (! spec)1780 return;17811782 if (spec->kctl_alloc) {1783 for (i = 0; i < spec->num_kctl_used; i++)1784 kfree(spec->kctl_alloc[i].name);1785 kfree(spec->kctl_alloc);1786 }17871788 if (spec->bios_pin_configs)1789 kfree(spec->bios_pin_configs);17901791 kfree(spec);1792}17931794static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,1795 unsigned int flag)1796{1797 unsigned int pin_ctl = snd_hda_codec_read(codec, nid,1798 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);17991800 if (pin_ctl & AC_PINCTL_IN_EN) {1801 /*1802 * we need to check the current set-up direction of1803 * shared input pins since they can be switched via1804 * "xxx as Output" mixer switch1805 */1806 struct sigmatel_spec *spec = codec->spec;1807 struct auto_pin_cfg *cfg = &spec->autocfg;1808 if ((nid == cfg->input_pins[AUTO_PIN_LINE] &&1809 spec->line_switch) ||1810 (nid == cfg->input_pins[AUTO_PIN_MIC] &&1811 spec->mic_switch))1812 return;1813 }18141815 /* if setting pin direction bits, clear the current1816 direction bits first */1817 if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))1818 pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);18191820 snd_hda_codec_write(codec, nid, 0,1821 AC_VERB_SET_PIN_WIDGET_CONTROL,1822 pin_ctl | flag);1823}18241825static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,1826 unsigned int flag)1827{1828 unsigned int pin_ctl = snd_hda_codec_read(codec, nid,1829 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);1830 snd_hda_codec_write(codec, nid, 0,1831 AC_VERB_SET_PIN_WIDGET_CONTROL,1832 pin_ctl & ~flag);1833}18341835static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)1836{1837 if (!nid)1838 return 0;1839 if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00)1840 & (1 << 31))1841 return 1;1842 return 0;1843}18441845static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)1846{1847 struct sigmatel_spec *spec = codec->spec;1848 struct auto_pin_cfg *cfg = &spec->autocfg;1849 int i, presence;18501851 presence = 0;1852 for (i = 0; i < cfg->hp_outs; i++) {1853 presence = get_pin_presence(codec, cfg->hp_pins[i]);1854 if (presence)1855 break;1856 }18571858 if (presence) {1859 /* disable lineouts, enable hp */1860 for (i = 0; i < cfg->line_outs; i++)1861 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],1862 AC_PINCTL_OUT_EN);1863 for (i = 0; i < cfg->speaker_outs; i++)1864 stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],1865 AC_PINCTL_OUT_EN);1866 } else {1867 /* enable lineouts, disable hp */1868 for (i = 0; i < cfg->line_outs; i++)1869 stac92xx_set_pinctl(codec, cfg->line_out_pins[i],1870 AC_PINCTL_OUT_EN);1871 for (i = 0; i < cfg->speaker_outs; i++)1872 stac92xx_set_pinctl(codec, cfg->speaker_pins[i],1873 AC_PINCTL_OUT_EN);1874 }1875}18761877static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)1878{1879 switch (res >> 26) {1880 case STAC_HP_EVENT:1881 stac92xx_hp_detect(codec, res);1882 break;1883 }1884}18851886#ifdef CONFIG_PM1887static int stac92xx_resume(struct hda_codec *codec)1888{1889 struct sigmatel_spec *spec = codec->spec;1890 int i;18911892 stac92xx_init(codec);1893 stac92xx_set_config_regs(codec);1894 snd_hda_resume_ctls(codec, spec->mixer);1895 for (i = 0; i < spec->num_mixers; i++)1896 snd_hda_resume_ctls(codec, spec->mixers[i]);1897 if (spec->multiout.dig_out_nid)1898 snd_hda_resume_spdif_out(codec);1899 if (spec->dig_in_nid)1900 snd_hda_resume_spdif_in(codec);19011902 return 0;1903}1904#endif19051906static struct hda_codec_ops stac92xx_patch_ops = {1907 .build_controls = stac92xx_build_controls,1908 .build_pcms = stac92xx_build_pcms,1909 .init = stac92xx_init,1910 .free = stac92xx_free,1911 .unsol_event = stac92xx_unsol_event,1912#ifdef CONFIG_PM1913 .resume = stac92xx_resume,1914#endif1915};19161917static int patch_stac9200(struct hda_codec *codec)1918{1919 struct sigmatel_spec *spec;1920 int err;19211922 spec = kzalloc(sizeof(*spec), GFP_KERNEL);1923 if (spec == NULL)1924 return -ENOMEM;19251926 codec->spec = spec;1927 spec->num_pins = 8;1928 spec->pin_nids = stac9200_pin_nids;1929 spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,1930 stac9200_models,1931 stac9200_cfg_tbl);1932 if (spec->board_config < 0) {1933 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");1934 err = stac92xx_save_bios_config_regs(codec);1935 if (err < 0) {1936 stac92xx_free(codec);1937 return err;1938 }1939 spec->pin_configs = spec->bios_pin_configs;1940 } else {1941 spec->pin_configs = stac9200_brd_tbl[spec->board_config];1942 stac92xx_set_config_regs(codec);1943 }19441945 spec->multiout.max_channels = 2;1946 spec->multiout.num_dacs = 1;1947 spec->multiout.dac_nids = stac9200_dac_nids;1948 spec->adc_nids = stac9200_adc_nids;1949 spec->mux_nids = stac9200_mux_nids;1950 spec->num_muxes = 1;1951 spec->num_dmics = 0;19521953 spec->init = stac9200_core_init;1954 spec->mixer = stac9200_mixer;19551956 err = stac9200_parse_auto_config(codec);1957 if (err < 0) {1958 stac92xx_free(codec);1959 return err;1960 }19611962 codec->patch_ops = stac92xx_patch_ops;19631964 return 0;1965}19661967static int patch_stac925x(struct hda_codec *codec)1968{1969 struct sigmatel_spec *spec;1970 int err;19711972 spec = kzalloc(sizeof(*spec), GFP_KERNEL);1973 if (spec == NULL)1974 return -ENOMEM;19751976 codec->spec = spec;1977 spec->num_pins = 8;1978 spec->pin_nids = stac925x_pin_nids;1979 spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,1980 stac925x_models,1981 stac925x_cfg_tbl);1982 again:1983 if (spec->board_config < 0) {1984 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"1985 "using BIOS defaults\n");1986 err = stac92xx_save_bios_config_regs(codec);1987 if (err < 0) {1988 stac92xx_free(codec);1989 return err;1990 }1991 spec->pin_configs = spec->bios_pin_configs;1992 } else if (stac925x_brd_tbl[spec->board_config] != NULL){1993 spec->pin_configs = stac925x_brd_tbl[spec->board_config];1994 stac92xx_set_config_regs(codec);1995 }19961997 spec->multiout.max_channels = 2;1998 spec->multiout.num_dacs = 1;1999 spec->multiout.dac_nids = stac925x_dac_nids;2000 spec->adc_nids = stac925x_adc_nids;2001 spec->mux_nids = stac925x_mux_nids;2002 spec->num_muxes = 1;2003 switch (codec->vendor_id) {2004 case 0x83847632: /* STAC9202 */2005 case 0x83847633: /* STAC9202D */2006 case 0x83847636: /* STAC9251 */2007 case 0x83847637: /* STAC9251D */2008 spec->num_dmics = 1;2009 spec->dmic_nids = stac925x_dmic_nids;2010 break;2011 default:2012 spec->num_dmics = 0;2013 break;2014 }20152016 spec->init = stac925x_core_init;2017 spec->mixer = stac925x_mixer;20182019 err = stac92xx_parse_auto_config(codec, 0x8, 0x7);2020 if (!err) {2021 if (spec->board_config < 0) {2022 printk(KERN_WARNING "hda_codec: No auto-config is "2023 "available, default to model=ref\n");2024 spec->board_config = STAC_925x_REF;2025 goto again;2026 }2027 err = -EINVAL;2028 }2029 if (err < 0) {2030 stac92xx_free(codec);2031 return err;2032 }20332034 codec->patch_ops = stac92xx_patch_ops;20352036 return 0;2037}20382039static int patch_stac922x(struct hda_codec *codec)2040{2041 struct sigmatel_spec *spec;2042 int err;20432044 spec = kzalloc(sizeof(*spec), GFP_KERNEL);2045 if (spec == NULL)2046 return -ENOMEM;20472048 codec->spec = spec;2049 spec->num_pins = 10;2050 spec->pin_nids = stac922x_pin_nids;2051 spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,2052 stac922x_models,2053 stac922x_cfg_tbl);2054 if (spec->board_config == STAC_INTEL_MAC_V3) {2055 spec->gpio_mute = 1;2056 /* Intel Macs have all same PCI SSID, so we need to check2057 * codec SSID to distinguish the exact models2058 */2059 printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id);2060 switch (codec->subsystem_id) {20612062 case 0x106b0800:2063 spec->board_config = STAC_INTEL_MAC_V1;2064 break;2065 case 0x106b0600:2066 case 0x106b0700:2067 spec->board_config = STAC_INTEL_MAC_V2;2068 break;2069 case 0x106b0e00:2070 case 0x106b0f00:2071 case 0x106b1600:2072 case 0x106b1700:2073 case 0x106b0200:2074 case 0x106b1e00:2075 spec->board_config = STAC_INTEL_MAC_V3;2076 break;2077 case 0x106b1a00:2078 case 0x00000100:2079 spec->board_config = STAC_INTEL_MAC_V4;2080 break;2081 case 0x106b0a00:2082 case 0x106b2200:2083 spec->board_config = STAC_INTEL_MAC_V5;2084 break;2085 }2086 }20872088 again:2089 if (spec->board_config < 0) {2090 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "2091 "using BIOS defaults\n");2092 err = stac92xx_save_bios_config_regs(codec);2093 if (err < 0) {2094 stac92xx_free(codec);2095 return err;2096 }2097 spec->pin_configs = spec->bios_pin_configs;2098 } else if (stac922x_brd_tbl[spec->board_config] != NULL) {2099 spec->pin_configs = stac922x_brd_tbl[spec->board_config];2100 stac92xx_set_config_regs(codec);2101 }21022103 spec->adc_nids = stac922x_adc_nids;2104 spec->mux_nids = stac922x_mux_nids;2105 spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids);2106 spec->num_dmics = 0;21072108 spec->init = stac922x_core_init;2109 spec->mixer = stac922x_mixer;21102111 spec->multiout.dac_nids = spec->dac_nids;21122113 err = stac92xx_parse_auto_config(codec, 0x08, 0x09);2114 if (!err) {2115 if (spec->board_config < 0) {2116 printk(KERN_WARNING "hda_codec: No auto-config is "2117 "available, default to model=ref\n");2118 spec->board_config = STAC_D945_REF;2119 goto again;2120 }2121 err = -EINVAL;2122 }2123 if (err < 0) {2124 stac92xx_free(codec);2125 return err;2126 }21272128 codec->patch_ops = stac92xx_patch_ops;21292130 /* Fix Mux capture level; max to 2 */2131 snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,2132 (0 << AC_AMPCAP_OFFSET_SHIFT) |2133 (2 << AC_AMPCAP_NUM_STEPS_SHIFT) |2134 (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |2135 (0 << AC_AMPCAP_MUTE_SHIFT));21362137 return 0;2138}21392140static int patch_stac927x(struct hda_codec *codec)2141{2142 struct sigmatel_spec *spec;2143 int err;21442145 spec = kzalloc(sizeof(*spec), GFP_KERNEL);2146 if (spec == NULL)2147 return -ENOMEM;21482149 codec->spec = spec;2150 spec->num_pins = 14;2151 spec->pin_nids = stac927x_pin_nids;2152 spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,2153 stac927x_models,2154 stac927x_cfg_tbl);2155 again:2156 if (spec->board_config < 0) {2157 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n");2158 err = stac92xx_save_bios_config_regs(codec);2159 if (err < 0) {2160 stac92xx_free(codec);2161 return err;2162 }2163 spec->pin_configs = spec->bios_pin_configs;2164 } else if (stac927x_brd_tbl[spec->board_config] != NULL) {2165 spec->pin_configs = stac927x_brd_tbl[spec->board_config];2166 stac92xx_set_config_regs(codec);2167 }21682169 switch (spec->board_config) {2170 case STAC_D965_3ST:2171 spec->adc_nids = stac927x_adc_nids;2172 spec->mux_nids = stac927x_mux_nids;2173 spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);2174 spec->num_dmics = 0;2175 spec->init = d965_core_init;2176 spec->mixer = stac9227_mixer;2177 break;2178 case STAC_D965_5ST:2179 spec->adc_nids = stac927x_adc_nids;2180 spec->mux_nids = stac927x_mux_nids;2181 spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);2182 spec->num_dmics = 0;2183 spec->init = d965_core_init;2184 spec->mixer = stac9227_mixer;2185 break;2186 default:2187 spec->adc_nids = stac927x_adc_nids;2188 spec->mux_nids = stac927x_mux_nids;2189 spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);2190 spec->num_dmics = 0;2191 spec->init = stac927x_core_init;2192 spec->mixer = stac927x_mixer;2193 }21942195 spec->multiout.dac_nids = spec->dac_nids;21962197 err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);2198 if (!err) {2199 if (spec->board_config < 0) {2200 printk(KERN_WARNING "hda_codec: No auto-config is "2201 "available, default to model=ref\n");2202 spec->board_config = STAC_D965_REF;2203 goto again;2204 }2205 err = -EINVAL;2206 }2207 if (err < 0) {2208 stac92xx_free(codec);2209 return err;2210 }22112212 codec->patch_ops = stac92xx_patch_ops;22132214 return 0;2215}22162217static int patch_stac9205(struct hda_codec *codec)2218{2219 struct sigmatel_spec *spec;2220 int err;22212222 spec = kzalloc(sizeof(*spec), GFP_KERNEL);2223 if (spec == NULL)2224 return -ENOMEM;22252226 codec->spec = spec;2227 spec->num_pins = 14;2228 spec->pin_nids = stac9205_pin_nids;2229 spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,2230 stac9205_models,2231 stac9205_cfg_tbl);2232 again:2233 if (spec->board_config < 0) {2234 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");2235 err = stac92xx_save_bios_config_regs(codec);2236 if (err < 0) {2237 stac92xx_free(codec);2238 return err;2239 }2240 spec->pin_configs = spec->bios_pin_configs;2241 } else {2242 spec->pin_configs = stac9205_brd_tbl[spec->board_config];2243 stac92xx_set_config_regs(codec);2244 }22452246 spec->adc_nids = stac9205_adc_nids;2247 spec->mux_nids = stac9205_mux_nids;2248 spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids);2249 spec->dmic_nids = stac9205_dmic_nids;2250 spec->num_dmics = ARRAY_SIZE(stac9205_dmic_nids);2251 spec->dmux_nid = 0x1d;22522253 spec->init = stac9205_core_init;2254 spec->mixer = stac9205_mixer;22552256 spec->multiout.dac_nids = spec->dac_nids;22572258 /* Configure GPIO0 as EAPD output */2259 snd_hda_codec_write(codec, codec->afg, 0,2260 AC_VERB_SET_GPIO_DIRECTION, 0x00000001);2261 /* Configure GPIO0 as CMOS */2262 snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);2263 /* Assert GPIO0 high */2264 snd_hda_codec_write(codec, codec->afg, 0,2265 AC_VERB_SET_GPIO_DATA, 0x00000001);2266 /* Enable GPIO0 */2267 snd_hda_codec_write(codec, codec->afg, 0,2268 AC_VERB_SET_GPIO_MASK, 0x00000001);22692270 err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);2271 if (!err) {2272 if (spec->board_config < 0) {2273 printk(KERN_WARNING "hda_codec: No auto-config is "2274 "available, default to model=ref\n");2275 spec->board_config = STAC_9205_REF;2276 goto again;2277 }2278 err = -EINVAL;2279 }2280 if (err < 0) {2281 stac92xx_free(codec);2282 return err;2283 }22842285 codec->patch_ops = stac92xx_patch_ops;22862287 return 0;2288}22892290/*2291 * STAC9872 hack2292 */22932294/* static config for Sony VAIO FE550G and Sony VAIO AR */2295static hda_nid_t vaio_dacs[] = { 0x2 };2296#define VAIO_HP_DAC 0x52297static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ };2298static hda_nid_t vaio_mux_nids[] = { 0x15 };22992300static struct hda_input_mux vaio_mux = {2301 .num_items = 2,2302 .items = {2303 /* { "HP", 0x0 }, */2304 { "Line", 0x1 },2305 { "Mic", 0x2 },2306 { "PCM", 0x3 },2307 }2308};23092310static struct hda_verb vaio_init[] = {2311 {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */2312 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */2313 {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */2314 {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */2315 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */2316 {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */2317 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */2318 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */2319 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */2320 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */2321 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */2322 {}2323};23242325static struct hda_verb vaio_ar_init[] = {2326 {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */2327 {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */2328 {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */2329 {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */2330/* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */2331 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */2332 {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */2333 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */2334 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */2335/* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */2336 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */2337 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */2338 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */2339 {}2340};23412342/* bind volumes of both NID 0x02 and 0x05 */2343static int vaio_master_vol_put(struct snd_kcontrol *kcontrol,2344 struct snd_ctl_elem_value *ucontrol)2345{2346 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);2347 long *valp = ucontrol->value.integer.value;2348 int change;23492350 change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,2351 0x7f, valp[0] & 0x7f);2352 change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,2353 0x7f, valp[1] & 0x7f);2354 snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,2355 0x7f, valp[0] & 0x7f);2356 snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,2357 0x7f, valp[1] & 0x7f);2358 return change;2359}23602361/* bind volumes of both NID 0x02 and 0x05 */2362static int vaio_master_sw_put(struct snd_kcontrol *kcontrol,2363 struct snd_ctl_elem_value *ucontrol)2364{2365 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);2366 long *valp = ucontrol->value.integer.value;2367 int change;23682369 change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,2370 0x80, (valp[0] ? 0 : 0x80));2371 change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,2372 0x80, (valp[1] ? 0 : 0x80));2373 snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,2374 0x80, (valp[0] ? 0 : 0x80));2375 snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,2376 0x80, (valp[1] ? 0 : 0x80));2377 return change;2378}23792380static struct snd_kcontrol_new vaio_mixer[] = {2381 {2382 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2383 .name = "Master Playback Volume",2384 .info = snd_hda_mixer_amp_volume_info,2385 .get = snd_hda_mixer_amp_volume_get,2386 .put = vaio_master_vol_put,2387 .tlv = { .c = snd_hda_mixer_amp_tlv },2388 .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),2389 },2390 {2391 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2392 .name = "Master Playback Switch",2393 .info = snd_hda_mixer_amp_switch_info,2394 .get = snd_hda_mixer_amp_switch_get,2395 .put = vaio_master_sw_put,2396 .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),2397 },2398 /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */2399 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),2400 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),2401 {2402 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2403 .name = "Capture Source",2404 .count = 1,2405 .info = stac92xx_mux_enum_info,2406 .get = stac92xx_mux_enum_get,2407 .put = stac92xx_mux_enum_put,2408 },2409 {}2410};24112412static struct snd_kcontrol_new vaio_ar_mixer[] = {2413 {2414 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2415 .name = "Master Playback Volume",2416 .info = snd_hda_mixer_amp_volume_info,2417 .get = snd_hda_mixer_amp_volume_get,2418 .put = vaio_master_vol_put,2419 .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),2420 },2421 {2422 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2423 .name = "Master Playback Switch",2424 .info = snd_hda_mixer_amp_switch_info,2425 .get = snd_hda_mixer_amp_switch_get,2426 .put = vaio_master_sw_put,2427 .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),2428 },2429 /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */2430 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),2431 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),2432 /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT),2433 HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/2434 {2435 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,2436 .name = "Capture Source",2437 .count = 1,2438 .info = stac92xx_mux_enum_info,2439 .get = stac92xx_mux_enum_get,2440 .put = stac92xx_mux_enum_put,2441 },2442 {}2443};24442445static struct hda_codec_ops stac9872_patch_ops = {2446 .build_controls = stac92xx_build_controls,2447 .build_pcms = stac92xx_build_pcms,2448 .init = stac92xx_init,2449 .free = stac92xx_free,2450#ifdef CONFIG_PM2451 .resume = stac92xx_resume,2452#endif2453};24542455enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */2456 CXD9872RD_VAIO,2457 /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */2458 STAC9872AK_VAIO,2459 /* Unknown. id=0x83847661 and subsys=0x104D1200. */2460 STAC9872K_VAIO,2461 /* AR Series. id=0x83847664 and subsys=104D1300 */2462 CXD9872AKD_VAIO,2463 STAC_9872_MODELS,2464};24652466static const char *stac9872_models[STAC_9872_MODELS] = {2467 [CXD9872RD_VAIO] = "vaio",2468 [CXD9872AKD_VAIO] = "vaio-ar",2469};24702471static struct snd_pci_quirk stac9872_cfg_tbl[] = {2472 SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO),2473 SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO),2474 SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO),2475 SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO),2476 {}2477};24782479static int patch_stac9872(struct hda_codec *codec)2480{2481 struct sigmatel_spec *spec;2482 int board_config;24832484 board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,2485 stac9872_models,2486 stac9872_cfg_tbl);2487 if (board_config < 0)2488 /* unknown config, let generic-parser do its job... */2489 return snd_hda_parse_generic_codec(codec);24902491 spec = kzalloc(sizeof(*spec), GFP_KERNEL);2492 if (spec == NULL)2493 return -ENOMEM;24942495 codec->spec = spec;2496 switch (board_config) {2497 case CXD9872RD_VAIO:2498 case STAC9872AK_VAIO:2499 case STAC9872K_VAIO:2500 spec->mixer = vaio_mixer;2501 spec->init = vaio_init;2502 spec->multiout.max_channels = 2;2503 spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);2504 spec->multiout.dac_nids = vaio_dacs;2505 spec->multiout.hp_nid = VAIO_HP_DAC;2506 spec->num_adcs = ARRAY_SIZE(vaio_adcs);2507 spec->adc_nids = vaio_adcs;2508 spec->input_mux = &vaio_mux;2509 spec->mux_nids = vaio_mux_nids;2510 break;25112512 case CXD9872AKD_VAIO:2513 spec->mixer = vaio_ar_mixer;2514 spec->init = vaio_ar_init;2515 spec->multiout.max_channels = 2;2516 spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs);2517 spec->multiout.dac_nids = vaio_dacs;2518 spec->multiout.hp_nid = VAIO_HP_DAC;2519 spec->num_adcs = ARRAY_SIZE(vaio_adcs);2520 spec->adc_nids = vaio_adcs;2521 spec->input_mux = &vaio_mux;2522 spec->mux_nids = vaio_mux_nids;2523 break;2524 }25252526 codec->patch_ops = stac9872_patch_ops;2527 return 0;2528}252925302531/*2532 * patch entries2533 */2534struct hda_codec_preset snd_hda_preset_sigmatel[] = {2535 { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },2536 { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },2537 { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },2538 { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x },2539 { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },2540 { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },2541 { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },2542 { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x },2543 { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x },2544 { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x },2545 { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x },2546 { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x },2547 { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x },2548 { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x },2549 { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x },2550 { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x },2551 { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x },2552 { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x },2553 { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x },2554 { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x },2555 { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x },2556 { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x },2557 { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x },2558 { .id = 0x83847632, .name = "STAC9202", .patch = patch_stac925x },2559 { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x },2560 { .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x },2561 { .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x },2562 { .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x },2563 { .id = 0x83847637, .name = "STAC9250D", .patch = patch_stac925x },2564 /* The following does not take into account .id=0x83847661 when subsys =2565 * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are2566 * currently not fully supported.2567 */2568 { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 },2569 { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 },2570 { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 },2571 { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 },2572 { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 },2573 { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 },2574 { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 },2575 { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 },2576 { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 },2577 { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 },2578 { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 },2579 {} /* terminator */2580};