📄 intel8x0.c
字号:
.name = "HP nc8000", .type = AC97_TUNE_HP_MUTE_LED }, { .subvendor = 0x103c, .subdevice = 0x0890, .name = "HP nc6000", .type = AC97_TUNE_MUTE_LED }, { .subvendor = 0x103c, .subdevice = 0x0934, .name = "HP nx8220", .type = AC97_TUNE_MUTE_LED }, { .subvendor = 0x103c, .subdevice = 0x129d, .name = "HP xw8000", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x103c, .subdevice = 0x0938, .name = "HP nc4200", .type = AC97_TUNE_HP_MUTE_LED }, { .subvendor = 0x103c, .subdevice = 0x099c, .name = "HP nx6110/nc6120", .type = AC97_TUNE_HP_MUTE_LED }, { .subvendor = 0x103c, .subdevice = 0x0944, .name = "HP nc6220", .type = AC97_TUNE_HP_MUTE_LED }, { .subvendor = 0x103c, .subdevice = 0x0934, .name = "HP nc8220", .type = AC97_TUNE_HP_MUTE_LED }, { .subvendor = 0x103c, .subdevice = 0x12f1, .name = "HP xw8200", /* AD1981B*/ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x103c, .subdevice = 0x12f2, .name = "HP xw6200", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x103c, .subdevice = 0x3008, .name = "HP xw4200", /* AD1981B*/ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x104d, .subdevice = 0x8197, .name = "Sony S1XP", .type = AC97_TUNE_INV_EAPD }, { .subvendor = 0x1043, .subdevice = 0x80f3, .name = "ASUS ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { .subvendor = 0x10cf, .subdevice = 0x11c3, .name = "Fujitsu-Siemens E4010", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10cf, .subdevice = 0x1225, .name = "Fujitsu-Siemens T3010", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10cf, .subdevice = 0x1253, .name = "Fujitsu S6210", /* STAC9750/51 */ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10cf, .subdevice = 0x127e, .name = "Fujitsu Lifebook C1211D", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10cf, .subdevice = 0x12ec, .name = "Fujitsu-Siemens 4010", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10cf, .subdevice = 0x12f2, .name = "Fujitsu-Siemens Celsius H320", .type = AC97_TUNE_SWAP_HP }, { .subvendor = 0x10f1, .subdevice = 0x2665, .name = "Fujitsu-Siemens Celsius", /* AD1981? */ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10f1, .subdevice = 0x2885, .name = "AMD64 Mobo", /* ALC650 */ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10f1, .subdevice = 0x2895, .name = "Tyan Thunder K8WE", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x10f7, .subdevice = 0x834c, .name = "Panasonic CF-R4", .type = AC97_TUNE_HP_ONLY, }, { .subvendor = 0x110a, .subdevice = 0x0056, .name = "Fujitsu-Siemens Scenic", /* AD1981? */ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x11d4, .subdevice = 0x5375, .name = "ADI AD1985 (discrete)", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x1462, .subdevice = 0x5470, .name = "MSI P4 ATX 645 Ultra", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x1734, .subdevice = 0x0088, .name = "Fujitsu-Siemens D1522", /* AD1981 */ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x8086, .subdevice = 0x2000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { .subvendor = 0x8086, .subdevice = 0x4000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { .subvendor = 0x8086, .subdevice = 0x4856, .name = "Intel D845WN (82801BA)", .type = AC97_TUNE_SWAP_HP }, { .subvendor = 0x8086, .subdevice = 0x4d44, .name = "Intel D850EMV2", /* AD1885 */ .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x8086, .subdevice = 0x4d56, .name = "Intel ICH/AD1885", .type = AC97_TUNE_HP_ONLY }, { .subvendor = 0x8086, .subdevice = 0x6000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING }, { .subvendor = 0x8086, .subdevice = 0xe000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_AD_SHARING },#if 0 /* FIXME: this seems wrong on most boards */ { .subvendor = 0x8086, .subdevice = 0xa000, .mask = 0xfff0, .name = "Intel ICH5/AD1985", .type = AC97_TUNE_HP_ONLY },#endif { } /* terminator */};static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, const char *quirk_override){ struct snd_ac97_bus *pbus; struct snd_ac97_template ac97; int err; unsigned int i, codecs; unsigned int glob_sta = 0; struct snd_ac97_bus_ops *ops; static struct snd_ac97_bus_ops standard_bus_ops = { .write = snd_intel8x0_codec_write, .read = snd_intel8x0_codec_read, }; static struct snd_ac97_bus_ops ali_bus_ops = { .write = snd_intel8x0_ali_codec_write, .read = snd_intel8x0_ali_codec_read, }; chip->spdif_idx = -1; /* use PCMOUT (or disabled) */ if (!spdif_aclink) { switch (chip->device_type) { case DEVICE_NFORCE: chip->spdif_idx = NVD_SPBAR; break; case DEVICE_ALI: chip->spdif_idx = ALID_AC97SPDIFOUT; break; case DEVICE_INTEL_ICH4: chip->spdif_idx = ICHD_SPBAR; break; }; } chip->in_ac97_init = 1; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; ac97.private_free = snd_intel8x0_mixer_free_ac97; ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE; if (chip->xbox) ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR; if (chip->device_type != DEVICE_ALI) { glob_sta = igetdword(chip, ICHREG(GLOB_STA)); ops = &standard_bus_ops; chip->in_sdin_init = 1; codecs = 0; for (i = 0; i < chip->max_codecs; i++) { if (! (glob_sta & chip->codec_bit[i])) continue; if (chip->device_type == DEVICE_INTEL_ICH4) { snd_intel8x0_codec_read_test(chip, codecs); chip->ac97_sdin[codecs] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; snd_assert(chip->ac97_sdin[codecs] < 3, chip->ac97_sdin[codecs] = 0); } else chip->ac97_sdin[codecs] = i; codecs++; } chip->in_sdin_init = 0; if (! codecs) codecs = 1; } else { ops = &ali_bus_ops; codecs = 1; /* detect the secondary codec */ for (i = 0; i < 100; i++) { unsigned int reg = igetdword(chip, ICHREG(ALI_RTSR)); if (reg & 0x40) { codecs = 2; break; } iputdword(chip, ICHREG(ALI_RTSR), reg | 0x40); udelay(1); } } if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0) goto __err; pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; if (ac97_clock >= 8000 && ac97_clock <= 48000) pbus->clock = ac97_clock; /* FIXME: my test board doesn't work well with VRA... */ if (chip->device_type == DEVICE_ALI) pbus->no_vra = 1; else pbus->dra = 1; chip->ac97_bus = pbus; chip->ncodecs = codecs; ac97.pci = chip->pci; for (i = 0; i < codecs; i++) { ac97.num = i; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { if (err != -EACCES) snd_printk(KERN_ERR "Unable to initialize codec #%d\n", i); if (i == 0) goto __err; continue; } } /* tune up the primary codec */ snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, quirk_override); /* enable separate SDINs for ICH4 */ if (chip->device_type == DEVICE_INTEL_ICH4) pbus->isdin = 1; /* find the available PCM streams */ i = ARRAY_SIZE(ac97_pcm_defs); if (chip->device_type != DEVICE_INTEL_ICH4) i -= 2; /* do not allocate PCM2IN and MIC2 */ if (chip->spdif_idx < 0) i--; /* do not allocate S/PDIF */ err = snd_ac97_pcm_assign(pbus, i, ac97_pcm_defs); if (err < 0) goto __err; chip->ichd[ICHD_PCMOUT].pcm = &pbus->pcms[0]; chip->ichd[ICHD_PCMIN].pcm = &pbus->pcms[1]; chip->ichd[ICHD_MIC].pcm = &pbus->pcms[2]; if (chip->spdif_idx >= 0) chip->ichd[chip->spdif_idx].pcm = &pbus->pcms[3]; if (chip->device_type == DEVICE_INTEL_ICH4) { chip->ichd[ICHD_PCM2IN].pcm = &pbus->pcms[4]; chip->ichd[ICHD_MIC2].pcm = &pbus->pcms[5]; } /* enable separate SDINs for ICH4 */ if (chip->device_type == DEVICE_INTEL_ICH4) { struct ac97_pcm *pcm = chip->ichd[ICHD_PCM2IN].pcm; u8 tmp = igetbyte(chip, ICHREG(SDM)); tmp &= ~(ICH_DI2L_MASK|ICH_DI1L_MASK); if (pcm) { tmp |= ICH_SE; /* steer enable for multiple SDINs */ tmp |= chip->ac97_sdin[0] << ICH_DI1L_SHIFT; for (i = 1; i < 4; i++) { if (pcm->r[0].codec[i]) { tmp |= chip->ac97_sdin[pcm->r[0].codec[1]->num] << ICH_DI2L_SHIFT; break; } } } else { tmp &= ~ICH_SE; /* steer disable */ } iputbyte(chip, ICHREG(SDM), tmp); } if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) { chip->multi4 = 1; if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) chip->multi6 = 1; } if (pbus->pcms[0].r[1].rslots[0]) { chip->dra = 1; } if (chip->device_type == DEVICE_INTEL_ICH4) { if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20) chip->smp20bit = 1; } if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) { /* 48kHz only */ chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000; } if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) { /* use slot 10/11 for SPDIF */ u32 val; val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK; val |= ICH_PCM_SPDIF_1011; iputdword(chip, ICHREG(GLOB_CNT), val); snd_ac97_update_bits(chip->ac97[0], AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4); } chip->in_ac97_init = 0; return 0; __err: /* clear the cold-reset bit for the next chance */ if (chip->device_type != DEVICE_ALI) iputdword(chip, ICHREG(GLOB_CNT), igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD); return err;}/* * */static void do_ali_reset(struct intel8x0 *chip){ iputdword(chip, ICHREG(ALI_SCR), ICH_ALI_SC_RESET); iputdword(chip, ICHREG(ALI_FIFOCR1), 0x83838383); iputdword(chip, ICHREG(ALI_FIFOCR2), 0x83838383); iputdword(chip, ICHREG(ALI_FIFOCR3), 0x83838383); iputdword(chip, ICHREG(ALI_INTERFACECR), ICH_ALI_IF_PI|ICH_ALI_IF_PO); iputdword(chip, ICHREG(ALI_INTERRUPTCR), 0x00000000); iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);}static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing){ unsigned long end_time; unsigned int cnt, status, nstatus; /* put logic to right state */ /* first clear status bits */ status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; if (chip->device_type == DEVICE_NFORCE) status |= ICH_NVSPINT; cnt = igetdword(chip, ICHREG(GLOB_STA)); iputdword(chip, ICHREG(GLOB_STA), cnt & status); /* ACLink on, 2 channels */ cnt = igetdword(chip, ICHREG(GLOB_CNT)); cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK);#ifdef CONFIG_SND_AC97_POWER_SAVE /* do cold reset - the full ac97 powerdown may leave the controller * in a warm state but actually it cannot communicate with the codec. */ iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_AC97COLD); cnt = igetdword(chip, ICHREG(GLOB_CNT)); udelay(10); iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); msleep(1);#else /* finish cold or do warm reset */ cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; iputdword(chip, ICHREG(GLOB_CNT), cnt); end_time = (jiffies + (HZ / 4)) + 1; do { if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) goto __ok; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); return -EIO; __ok:#endif if (probing) { /* wait for any codec read
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -