void eap1371_set_dac_rate(struct eap_softc *sc, int rate, int which) { int dac = which == 1 ? ESRC_DAC1 : ESRC_DAC2; int freq, r; int s; /* Whatever, it works, so I'll leave it :) */ if (rate > 48000) rate = 48000; if (rate < 4000) rate = 4000; freq = ((rate << 15) + 1500) / 3000; s = splaudio(); eap1371_src_wait(sc); r = EREAD4(sc, E1371_SRC) & (E1371_SRC_DISABLE | E1371_SRC_DISP2 | E1371_SRC_DISP1 | E1371_SRC_DISREC); r |= (which == 1) ? E1371_SRC_DISP1 : E1371_SRC_DISP2; EWRITE4(sc, E1371_SRC, r); r = eap1371_src_read(sc, dac + ESRC_IREGS) & 0x00ff; eap1371_src_write(sc, dac + ESRC_IREGS, r | ((freq >> 5) & 0xfc00)); eap1371_src_write(sc, dac + ESRC_VFF, freq & 0x7fff); r = EREAD4(sc, E1371_SRC) & (E1371_SRC_DISABLE | E1371_SRC_DISP2 | E1371_SRC_DISP1 | E1371_SRC_DISREC); r &= ~(which == 1 ? E1371_SRC_DISP1 : E1371_SRC_DISP2); EWRITE4(sc, E1371_SRC, r); splx(s); }
void eap1371_set_adc_rate(struct eap_softc *sc, int rate) { int freq, n, truncm; int out; int s; /* Whatever, it works, so I'll leave it :) */ if (rate > 48000) rate = 48000; if (rate < 4000) rate = 4000; n = rate / 3000; if ((1 << n) & SRC_MAGIC) n--; truncm = ((21 * n) - 1) | 1; freq = ((48000 << 15) / rate) * n; if (rate >= 24000) { if (truncm > 239) truncm = 239; out = ESRC_SET_TRUNC((239 - truncm) / 2); } else { if (truncm > 119) truncm = 119; out = ESRC_SMF | ESRC_SET_TRUNC((119 - truncm) / 2); } out |= ESRC_SET_N(n); s = splaudio(); eap1371_src_write(sc, ESRC_ADC+ESRC_TRUNC_N, out); out = eap1371_src_read(sc, ESRC_ADC+ESRC_IREGS) & 0xff; eap1371_src_write(sc, ESRC_ADC+ESRC_IREGS, out | ESRC_SET_VFI(freq >> 15)); eap1371_src_write(sc, ESRC_ADC+ESRC_VFF, freq & 0x7fff); eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(n)); eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(n)); splx(s); }
void eap_attach(struct device *parent, struct device *self, void *aux) { struct eap_softc *sc = (struct eap_softc *)self; struct pci_attach_args *pa = (struct pci_attach_args *)aux; pci_chipset_tag_t pc = pa->pa_pc; struct audio_hw_if *eap_hw_if; char const *intrstr; pci_intr_handle_t ih; mixer_ctrl_t ctl; int i; int revision, ct5880; /* Flag if we're "creative" */ sc->sc_1371 = !(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI); revision = PCI_REVISION(pa->pa_class); if (sc->sc_1371) { if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ && ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI97 && (revision == EAP_ES1373_8 || revision == EAP_CT5880_A)) || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_CT5880)) ct5880 = 1; else ct5880 = 0; } /* Map I/O register */ if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, &sc->iot, &sc->ioh, NULL, NULL, 0)) { return; } sc->sc_dmatag = pa->pa_dmat; /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, eap_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); if (!sc->sc_1371) { /* Enable interrupts and looping mode. */ /* enable the parts we need */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); /* reset codec */ /* normal operation */ /* select codec clocks */ eap1370_write_codec(sc, AK_RESET, AK_PD); eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST); eap1370_write_codec(sc, AK_CS, 0x0); eap_hw_if = &eap1370_hw_if; /* Enable all relevant mixer switches. */ ctl.dev = EAP_OUTPUT_SELECT; ctl.type = AUDIO_MIXER_SET; ctl.un.mask = 1 << EAP_VOICE_VOL | 1 << EAP_FM_VOL | 1 << EAP_CD_VOL | 1 << EAP_LINE_VOL | 1 << EAP_AUX_VOL | 1 << EAP_MIC_VOL; eap_hw_if->set_port(sc, &ctl); ctl.type = AUDIO_MIXER_VALUE; ctl.un.value.num_channels = 1; for (ctl.dev = EAP_MASTER_VOL; ctl.dev < EAP_MIC_VOL; ctl.dev++) { ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = VOL_0DB; eap_hw_if->set_port(sc, &ctl); } ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = 0; eap_hw_if->set_port(sc, &ctl); ctl.dev = EAP_MIC_PREAMP; ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; eap_hw_if->set_port(sc, &ctl); ctl.dev = EAP_RECORD_SOURCE; ctl.type = AUDIO_MIXER_SET; ctl.un.mask = 1 << EAP_MIC_VOL; eap_hw_if->set_port(sc, &ctl); } else { /* clean slate */ EWRITE4(sc, EAP_SIC, 0); EWRITE4(sc, EAP_ICSC, 0); EWRITE4(sc, E1371_LEGACY, 0); if (ct5880) { EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET); /* Let codec wake up */ delay(20000); } /* Reset from es1371's perspective */ EWRITE4(sc, EAP_ICSC, E1371_SYNC_RES); delay(20); EWRITE4(sc, EAP_ICSC, 0); /* * Must properly reprogram sample rate converter, * or it locks up. Set some defaults for the life of the * machine, and set up a sb default sample rate. */ EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE); for (i = 0; i < 0x80; i++) eap1371_src_write(sc, i, 0); eap1371_src_write(sc, ESRC_DAC1+ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC2+ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC1+ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_DAC2+ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1)); eap1371_set_adc_rate(sc, 22050); eap1371_set_dac_rate(sc, 22050, 1); eap1371_set_dac_rate(sc, 22050, 2); EWRITE4(sc, E1371_SRC, 0); /* Reset codec */ /* Interrupt enable */ sc->host_if.arg = sc; sc->host_if.attach = eap1371_attach_codec; sc->host_if.read = eap1371_read_codec; sc->host_if.write = eap1371_write_codec; sc->host_if.reset = eap1371_reset_codec; sc->host_if.flags = eap_flags_codec; sc->flags = AC97_HOST_DONT_READ; if (ac97_attach(&sc->host_if) == 0) { /* Interrupt enable */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); } else return; eap_hw_if = &eap1371_hw_if; /* Just enable the DAC and master volumes by default */ ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; /* off */ ctl.dev = eap1371_get_portnum_by_name(sc, AudioCoutputs, AudioNmaster, AudioNmute); eap1371_mixer_set_port(sc, &ctl); ctl.dev = eap1371_get_portnum_by_name(sc, AudioCinputs, AudioNdac, AudioNmute); eap1371_mixer_set_port(sc, &ctl); ctl.dev = eap1371_get_portnum_by_name(sc, AudioCrecord, AudioNvolume, AudioNmute); eap1371_mixer_set_port(sc, &ctl); ctl.dev = eap1371_get_portnum_by_name(sc, AudioCrecord, AudioNsource, NULL); ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; eap1371_mixer_set_port(sc, &ctl); } audio_attach_mi(eap_hw_if, sc, &sc->sc_dev); #if NMIDI > 0 sc->sc_mididev = midi_attach_mi(&eap_midi_hw_if, sc, &sc->sc_dev); #endif }
int eap_resume(struct eap_softc *sc) { mixer_ctrl_t ctl; int i; if (!sc->sc_1371) { /* Enable interrupts and looping mode. */ /* enable the parts we need */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); /* reset codec */ /* normal operation */ /* select codec clocks */ eap1370_write_codec(sc, AK_RESET, AK_PD); eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST); eap1370_write_codec(sc, AK_CS, 0x0); bzero(&ctl, sizeof(ctl)); ctl.dev = EAP_RECORD_SOURCE; ctl.type = AUDIO_MIXER_SET; ctl.un.mask = sc->sc_record_source; eap1370_hw_if.set_port(sc, &ctl); ctl.dev = EAP_INPUT_SOURCE; ctl.type = AUDIO_MIXER_SET; ctl.un.mask = sc->sc_input_source; eap1370_hw_if.set_port(sc, &ctl); eap1370_set_mixer(sc, AK_MGAIN, sc->sc_mic_preamp); for (i = EAP_MASTER_VOL; i < EAP_MIC_VOL; i++) eap1370_write_codec(sc, i, sc->sc_port[i]); } else { /* clean slate */ EWRITE4(sc, EAP_SIC, 0); EWRITE4(sc, EAP_ICSC, 0); EWRITE4(sc, E1371_LEGACY, 0); if (sc->sc_ct5880) { EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET); /* Let codec wake up */ delay(20000); } ac97_resume(&sc->host_if, sc->codec_if); EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE); for (i = 0; i < 0x80; i++) eap1371_src_write(sc, i, 0); eap1371_src_write(sc, ESRC_ADC + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_ADC + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_ADC + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1)); EWRITE4(sc, E1371_SRC, 0); /* Interrupt enable */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); } return (0); }
void eap_attach(struct device *parent, struct device *self, void *aux) { struct eap_softc *sc = (struct eap_softc *)self; struct pci_attach_args *pa = (struct pci_attach_args *)aux; pci_chipset_tag_t pc = pa->pa_pc; struct audio_hw_if *eap_hw_if; char const *intrstr; pci_intr_handle_t ih; mixer_ctrl_t ctl; int i; int revision; /* Flag if we're "creative" */ sc->sc_1371 = !(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ && PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI); revision = PCI_REVISION(pa->pa_class); if (sc->sc_1371) { if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ && ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI97 && (revision == EAP_ES1373_8 || revision == EAP_CT5880_A)) || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_CT5880)) sc->sc_ct5880 = 1; } /* Map I/O register */ if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, &sc->iot, &sc->ioh, NULL, NULL, 0)) { return; } sc->sc_dmatag = pa->pa_dmat; /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, eap_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); if (!sc->sc_1371) { /* Enable interrupts and looping mode. */ /* enable the parts we need */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); /* reset codec */ /* normal operation */ /* select codec clocks */ eap1370_write_codec(sc, AK_RESET, AK_PD); eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST); eap1370_write_codec(sc, AK_CS, 0x0); eap_hw_if = &eap1370_hw_if; /* Enable all relevant mixer switches. */ ctl.dev = EAP_INPUT_SOURCE; ctl.type = AUDIO_MIXER_SET; ctl.un.mask = 1 << EAP_VOICE_VOL | 1 << EAP_FM_VOL | 1 << EAP_CD_VOL | 1 << EAP_LINE_VOL | 1 << EAP_AUX_VOL | 1 << EAP_MIC_VOL; eap_hw_if->set_port(sc, &ctl); ctl.type = AUDIO_MIXER_VALUE; ctl.un.value.num_channels = 1; for (ctl.dev = EAP_MASTER_VOL; ctl.dev < EAP_MIC_VOL; ctl.dev++) { ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = VOL_0DB; eap_hw_if->set_port(sc, &ctl); } ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = 0; eap_hw_if->set_port(sc, &ctl); ctl.dev = EAP_MIC_PREAMP; ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; eap_hw_if->set_port(sc, &ctl); ctl.dev = EAP_RECORD_SOURCE; ctl.type = AUDIO_MIXER_SET; ctl.un.mask = 1 << EAP_MIC_VOL; eap_hw_if->set_port(sc, &ctl); } else { /* clean slate */ EWRITE4(sc, EAP_SIC, 0); EWRITE4(sc, EAP_ICSC, 0); EWRITE4(sc, E1371_LEGACY, 0); if (sc->sc_ct5880) { EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET); /* Let codec wake up */ delay(20000); } /* Reset from es1371's perspective */ EWRITE4(sc, EAP_ICSC, E1371_SYNC_RES); delay(20); EWRITE4(sc, EAP_ICSC, 0); /* * Must properly reprogram sample rate converter, * or it locks up. * * We don't know how to program it (no documentation), * and the linux/oss magic receipe doesn't work (breaks * full-duplex, by selecting different play and record * rates). On the other hand, the sample rate converter * can't be disabled (disabling it would disable DMA), * so we use these magic defaults that make it "resample" * 48kHz to 48kHz without breaking full-duplex. */ EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE); for (i = 0; i < 0x80; i++) eap1371_src_write(sc, i, 0); eap1371_src_write(sc, ESRC_ADC + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_ADC + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_ADC + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1)); EWRITE4(sc, E1371_SRC, 0); /* Reset codec */ /* Interrupt enable */ sc->host_if.arg = sc; sc->host_if.attach = eap1371_attach_codec; sc->host_if.read = eap1371_read_codec; sc->host_if.write = eap1371_write_codec; sc->host_if.reset = eap1371_reset_codec; sc->host_if.flags = eap_flags_codec; sc->flags = AC97_HOST_DONT_READ; if (ac97_attach(&sc->host_if) == 0) { /* Interrupt enable */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); } else return; eap_hw_if = &eap1371_hw_if; } audio_attach_mi(eap_hw_if, sc, &sc->sc_dev); #if NMIDI > 0 sc->sc_mididev = midi_attach_mi(&eap_midi_hw_if, sc, &sc->sc_dev); #endif }
void eap_resume(struct eap_softc *sc) { int i; if (!sc->sc_1371) { /* Enable interrupts and looping mode. */ /* enable the parts we need */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); /* reset codec */ /* normal operation */ /* select codec clocks */ eap1370_write_codec(sc, AK_RESET, AK_PD); eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST); eap1370_write_codec(sc, AK_CS, 0x0); } else { /* clean slate */ EWRITE4(sc, EAP_SIC, 0); EWRITE4(sc, EAP_ICSC, 0); EWRITE4(sc, E1371_LEGACY, 0); if (sc->sc_ct5880) { EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET); /* Let codec wake up */ delay(20000); } ac97_resume(&sc->host_if, sc->codec_if); EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE); for (i = 0; i < 0x80; i++) eap1371_src_write(sc, i, 0); eap1371_src_write(sc, ESRC_ADC + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_ADC + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_ADC + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_DAC1 + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_IREGS, ESRC_SET_VFI(16)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_TRUNC_N, ESRC_SET_N(16)); eap1371_src_write(sc, ESRC_DAC2 + ESRC_VFF, 0); eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1)); eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1)); EWRITE4(sc, E1371_SRC, 0); /* Interrupt enable */ EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); } }