--- linux-2.6.16.1/sound/pci/hda/patch_sigmatel.c 2006-03-28 07:49:02.000000000 +0100 +++ linux-2.6.16.1-imac-sky2-rtc/sound/pci/hda/patch_sigmatel.c 2006-05-22 19:09:51.000000000 +0100 @@ -41,6 +41,7 @@ #define STAC_REF 0 #define STAC_D945GTP3 1 #define STAC_D945GTP5 2 +#define STAC_MINIMAC 3 struct sigmatel_spec { struct snd_kcontrol_new *mixers[4]; @@ -51,6 +52,7 @@ unsigned int line_switch: 1; unsigned int mic_switch: 1; unsigned int alt_switch: 1; + unsigned int gpio_mute: 1; /* playback */ struct hda_multi_out multiout; @@ -288,10 +290,28 @@ 0x02a19320, 0x40000100, }; +/* These come from the windows inf files from bootcamp*/ +#if 0 +/*This has mic/line in*/ +static unsigned int minimac_pin_configs[10] = { + 0x0121E230, 0x90A70120, 0x9017E110, 0x400000FE, + 0x400000FD, 0x0181E021, 0x1145E040, 0x400000FA, + 0x400000FC, 0x400000FB, +}; +#else +/*This has only line in*/ +static unsigned int minimac_pin_configs[10] = { + 0x0121E220, 0x400000FF, 0x9017E110, 0x400000FE, + 0x400000FD, 0x0181E040, 0x1145E030, 0x11C5E040, + 0x400000FC, 0x400000FB, +}; +#endif + static unsigned int *stac922x_brd_tbl[] = { ref922x_pin_configs, d945gtp3_pin_configs, d945gtp5_pin_configs, + minimac_pin_configs, }; static struct hda_board_config stac922x_cfg_tbl[] = { @@ -314,6 +334,15 @@ { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x0417, .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ +#if 0 + { .pci_subvendor = 0x8384, + .pci_subdevice = 0x7680, + .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ +#else + { .pci_subvendor = 0x8384, + .pci_subdevice = 0x7680, + .config = STAC_MINIMAC }, /* Intel D975XBK - 5 Stack */ +#endif {} /* terminator */ }; @@ -824,6 +853,19 @@ } } + if (imux->num_items == 1) { + /* + * Set the current input for the muxes. + * The STAC9221 has two input muxes with identical source + * NID lists. Hopefully this won't get confused. + */ + for (i = 0; i < spec->num_muxes; i++) { + snd_hda_codec_write(codec, spec->mux_nids[i], 0, + AC_VERB_SET_CONNECT_SEL, + imux->items[0].index); + } + } + return 0; } @@ -918,6 +960,46 @@ return 1; } +/* + * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a + * funky external mute control using GPIO pins. + */ + +static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) +{ + unsigned int gpiostate, gpiomask, gpiodir; + + gpiostate = snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_GET_GPIO_DATA, 0); + + if (!muted) { + gpiostate |= (1 << pin); + } else { + gpiostate &= ~(1 << pin); + } + + gpiomask = snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_GET_GPIO_MASK, 0); + gpiomask |= (1 << pin); + + gpiodir = snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_GET_GPIO_DIRECTION, 0); + gpiodir |= (1 << pin); + + /* AppleHDA seems to do this -- WTF is this verb?? */ + snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); + + snd_hda_codec_write(codec, codec->afg, 0, + AC_VERB_SET_GPIO_MASK, gpiomask); + snd_hda_codec_write(codec, codec->afg, 0, + AC_VERB_SET_GPIO_DIRECTION, gpiodir); + + udelay(1000); + + snd_hda_codec_write(codec, codec->afg, 0, + AC_VERB_SET_GPIO_DATA, gpiostate); +} + static int stac92xx_init(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -1005,6 +1087,11 @@ if (spec->dig_in_nid) snd_hda_resume_spdif_in(codec); + if (spec->gpio_mute) { + stac922x_gpio_mute(codec, 0, 0); + stac922x_gpio_mute(codec, 1, 0); + } + return 0; } #endif @@ -1029,6 +1116,7 @@ if (spec == NULL) return -ENOMEM; + codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); if (spec->board_config < 0) @@ -1072,6 +1160,7 @@ codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); + if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n"); else { @@ -1080,6 +1169,18 @@ spec->pin_configs = stac922x_brd_tbl[spec->board_config]; stac92xx_set_config_regs(codec); } + { + u16 subsystem_vendor, subsystem_device; + pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); + pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device); + + /* Need a better way of detecting an Intel Macintosh */ + if ((subsystem_vendor == 0x8384) && + (subsystem_device == 0x7680)) { + spec->gpio_mute = 1; + } + } + spec->adc_nids = stac922x_adc_nids; spec->mux_nids = stac922x_mux_nids; @@ -1098,6 +1199,9 @@ codec->patch_ops = stac92xx_patch_ops; + stac922x_gpio_mute(codec, 0, 0); + stac922x_gpio_mute(codec, 1, 0); + return 0; }