void Mixer::Init() { ac97_attach(&fAC97Dev, _ReadAC97, _WriteAC97, this, fDevice->PCIInfo().u.h0.subsystem_vendor_id, fDevice->PCIInfo().u.h0.subsystem_id); _ReadSupportedFormats(); }
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 }
static void cs4280_attach(device_t parent, device_t self, void *aux) { struct cs428x_softc *sc; struct pci_attach_args *pa; pci_chipset_tag_t pc; const struct cs4280_card_t *cs_card; char const *intrstr; const char *vendor, *product; pcireg_t reg; uint32_t mem; int error; char intrbuf[PCI_INTRSTR_LEN]; sc = device_private(self); sc->sc_dev = self; pa = (struct pci_attach_args *)aux; pc = pa->pa_pc; pci_aprint_devinfo(pa, "Audio controller"); cs_card = cs4280_identify_card(pa); if (cs_card != NULL) { vendor = pci_findvendor(cs_card->id); product = pci_findproduct(cs_card->id); if (vendor == NULL) aprint_normal_dev(sc->sc_dev, "vendor 0x%04x product 0x%04x\n", PCI_VENDOR(cs_card->id), PCI_PRODUCT(cs_card->id)); else if (product == NULL) aprint_normal_dev(sc->sc_dev, "%s product 0x%04x\n", vendor, PCI_PRODUCT(cs_card->id)); else aprint_normal_dev(sc->sc_dev, "%s %s\n", vendor, product); sc->sc_flags = cs_card->flags; } else { sc->sc_flags = CS428X_FLAG_NONE; } sc->sc_pc = pa->pa_pc; sc->sc_pt = pa->pa_tag; /* Map I/O register */ if (pci_mapreg_map(pa, PCI_BA0, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t, &sc->ba0h, NULL, NULL)) { aprint_error_dev(sc->sc_dev, "can't map BA0 space\n"); return; } if (pci_mapreg_map(pa, PCI_BA1, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t, &sc->ba1h, NULL, NULL)) { aprint_error_dev(sc->sc_dev, "can't map BA1 space\n"); return; } sc->sc_dmatag = pa->pa_dmat; /* power up chip */ if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, pci_activate_null)) && error != EOPNOTSUPP) { aprint_error_dev(sc->sc_dev, "cannot activate %d\n", error); return; } /* Enable the device (set bus master flag) */ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg | PCI_COMMAND_MASTER_ENABLE); /* LATENCY_TIMER setting */ mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); if ( PCI_LATTIMER(mem) < 32 ) { mem &= 0xffff00ff; mem |= 0x00002000; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem); } /* CLKRUN hack initialization */ cs4280_clkrun_hack_init(sc); /* Map and establish the interrupt. */ if (pci_intr_map(pa, &sc->intrh)) { aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, sc->intrh, intrbuf, sizeof(intrbuf)); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); sc->sc_ih = pci_intr_establish(sc->sc_pc, sc->intrh, IPL_AUDIO, cs4280_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); /* Initialization */ if(cs4280_init(sc, 1) != 0) { mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } sc->type = TYPE_CS4280; sc->halt_input = cs4280_halt_input; sc->halt_output = cs4280_halt_output; /* setup buffer related parameters */ sc->dma_size = CS4280_DCHUNK; sc->dma_align = CS4280_DALIGN; sc->hw_blocksize = CS4280_ICHUNK; /* AC 97 attachment */ sc->host_if.arg = sc; sc->host_if.attach = cs428x_attach_codec; sc->host_if.read = cs4280_read_codec; sc->host_if.write = cs4280_write_codec; #if 0 sc->host_if.reset = cs4280_reset_codec; #else sc->host_if.reset = NULL; #endif sc->host_if.flags = cs4280_flags_codec; if (ac97_attach(&sc->host_if, self, &sc->sc_lock) != 0) { aprint_error_dev(sc->sc_dev, "ac97_attach failed\n"); return; } audio_attach_mi(&cs4280_hw_if, sc, sc->sc_dev); #if NMIDI > 0 midi_attach_mi(&cs4280_midi_hw_if, sc, sc->sc_dev); #endif if (!pmf_device_register(self, cs4280_suspend, cs4280_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
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 }
static void fms_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa; struct fms_softc *sc; struct audio_attach_args aa; const char *intrstr; pci_chipset_tag_t pc; pcitag_t pt; pci_intr_handle_t ih; uint16_t k1; pa = aux; sc = device_private(self); sc->sc_dev = self; intrstr = NULL; pc = pa->pa_pc; pt = pa->pa_tag; aprint_naive(": Audio controller\n"); aprint_normal(": Forte Media FM-801\n"); if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, &sc->sc_ioaddr, &sc->sc_iosize)) { aprint_error_dev(sc->sc_dev, "can't map i/o space\n"); return; } if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x30, 2, &sc->sc_mpu_ioh)) panic("fms_attach: can't get mpu subregion handle"); if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x68, 4, &sc->sc_opl_ioh)) panic("fms_attach: can't get opl subregion handle"); if (pci_intr_map(pa, &ih)) { aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, fms_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } sc->sc_dmat = pa->pa_dmat; aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); /* Disable legacy audio (SBPro compatibility) */ pci_conf_write(pc, pt, 0x40, 0); /* Reset codec and AC'97 */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020); delay(2); /* > 1us according to AC'97 documentation */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000); delay(1); /* > 168.2ns according to AC'97 documentation */ /* Set up volume */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PCM_VOLUME, 0x0808); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_FM_VOLUME, 0x0808); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_I2S_VOLUME, 0x0808); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_RECORD_SOURCE, 0x0000); /* Unmask playback, record and mpu interrupts, mask the rest */ k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK, (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) | FM_INTMASK_VOL); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS, FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU | FM_INTSTATUS_VOL); sc->host_if.arg = sc; sc->host_if.attach = fms_attach_codec; sc->host_if.read = fms_read_codec; sc->host_if.write = fms_write_codec; sc->host_if.reset = fms_reset_codec; if (ac97_attach(&sc->host_if, self, &sc->sc_lock) != 0) { mutex_destroy(&sc->sc_intr_lock); mutex_destroy(&sc->sc_lock); return; } audio_attach_mi(&fms_hw_if, sc, sc->sc_dev); aa.type = AUDIODEV_TYPE_OPL; aa.hwif = NULL; aa.hdl = NULL; config_found(sc->sc_dev, &aa, audioprint); aa.type = AUDIODEV_TYPE_MPU; aa.hwif = NULL; aa.hdl = NULL; sc->sc_mpu_dev = config_found(sc->sc_dev, &aa, audioprint); }
void neo_attach(struct device *parent, struct device *self, void *aux) { struct neo_softc *sc = (struct neo_softc *)self; struct pci_attach_args *pa = (struct pci_attach_args *)aux; pci_chipset_tag_t pc = pa->pa_pc; char const *intrstr; pci_intr_handle_t ih; int error; sc->type = pa->pa_id; /* Map I/O register */ if (pci_mapreg_map(pa, PCI_MAPS, PCI_MAPREG_TYPE_MEM, 0, &sc->bufiot, &sc->bufioh, NULL, NULL, 0)) { printf("\n%s: can't map i/o space\n", sc->dev.dv_xname); return; } if (pci_mapreg_map(pa, PCI_MAPS + 4, PCI_MAPREG_TYPE_MEM, 0, &sc->regiot, &sc->regioh, NULL, NULL, 0)) { printf("\n%s: can't map i/o space\n", sc->dev.dv_xname); return; } /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { printf("\n%s: couldn't map interrupt\n", sc->dev.dv_xname); return; } intrstr = pci_intr_string(pc, ih); sc->ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, neo_intr, sc, sc->dev.dv_xname); if (sc->ih == NULL) { printf("\n%s: couldn't establish interrupt", sc->dev.dv_xname); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s\n", intrstr); if ((error = nm_init(sc)) != 0) return; sc->host_if.arg = sc; sc->host_if.attach = neo_attach_codec; sc->host_if.read = neo_read_codec; sc->host_if.write = neo_write_codec; sc->host_if.reset = neo_reset_codec; sc->host_if.flags = neo_flags_codec; if ((error = ac97_attach(&sc->host_if)) != 0) return; audio_attach_mi(&neo_hw_if, sc, &sc->dev); return; }
static void auacer_attach(struct device *parent, struct device *self, void *aux) { struct auacer_softc *sc; struct pci_attach_args *pa; pci_intr_handle_t ih; bus_size_t aud_size; pcireg_t v; const char *intrstr; int i; sc = (struct auacer_softc *)self; pa = aux; aprint_normal(": Acer Labs M5455 Audio controller\n"); if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->iot, &sc->aud_ioh, NULL, &aud_size)) { aprint_error(": can't map i/o space\n"); return; } sc->sc_pc = pa->pa_pc; sc->sc_pt = pa->pa_tag; sc->dmat = pa->pa_dmat; sc->sc_dmamap_flags = BUS_DMA_COHERENT; /* XXX remove */ /* enable bus mastering */ v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, v | PCI_COMMAND_MASTER_ENABLE); /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(&sc->sc_dev, "can't map interrupt\n"); return; } intrstr = pci_intr_string(pa->pa_pc, ih); sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, auacer_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(&sc->sc_dev, "can't establish interrupt"); if (intrstr != NULL) aprint_normal(" at %s", intrstr); aprint_normal("\n"); return; } aprint_normal_dev(&sc->sc_dev, "interrupting at %s\n", intrstr); strlcpy(sc->sc_audev.name, "M5455 AC97", MAX_AUDIO_DEV_LEN); snprintf(sc->sc_audev.version, MAX_AUDIO_DEV_LEN, "0x%02x", PCI_REVISION(pa->pa_class)); strlcpy(sc->sc_audev.config, device_xname(&sc->sc_dev), MAX_AUDIO_DEV_LEN); /* Set up DMA lists. */ auacer_alloc_cdata(sc); sc->sc_pcmo.dmalist = sc->sc_cdata->ic_dmalist_pcmo; sc->sc_pcmo.ptr = 0; sc->sc_pcmo.port = ALI_BASE_PO; DPRINTF(ALI_DEBUG_DMA, ("auacer_attach: lists %p\n", sc->sc_pcmo.dmalist)); sc->host_if.arg = sc; sc->host_if.attach = auacer_attach_codec; sc->host_if.read = auacer_read_codec; sc->host_if.write = auacer_write_codec; sc->host_if.reset = auacer_reset_codec; if (ac97_attach(&sc->host_if, self) != 0) return; /* setup audio_format */ memcpy(sc->sc_formats, auacer_formats, sizeof(auacer_formats)); if (!AC97_IS_4CH(sc->codec_if)) AUFMT_INVALIDATE(&sc->sc_formats[AUACER_FORMATS_4CH]); if (!AC97_IS_6CH(sc->codec_if)) AUFMT_INVALIDATE(&sc->sc_formats[AUACER_FORMATS_6CH]); if (AC97_IS_FIXED_RATE(sc->codec_if)) { for (i = 0; i < AUACER_NFORMATS; i++) { sc->sc_formats[i].frequency_type = 1; sc->sc_formats[i].frequency[0] = 48000; } } if (0 != auconv_create_encodings(sc->sc_formats, AUACER_NFORMATS, &sc->sc_encodings)) { return; } audio_attach_mi(&auacer_hw_if, sc, &sc->sc_dev); auacer_reset(sc); if (!pmf_device_register(self, NULL, auacer_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
void yds_attachhook(void *xsc) { struct yds_softc *sc = xsc; struct yds_codec_softc *codec; mixer_ctrl_t ctl; int r, i; /* Initialize the device */ if (yds_init(sc, 0) == -1) return; /* * Attach ac97 codec */ for (i = 0; i < 2; i++) { static struct { int data; int addr; } statregs[] = { {AC97_STAT_DATA1, AC97_STAT_ADDR1}, {AC97_STAT_DATA2, AC97_STAT_ADDR2}, }; if (i == 1 && ac97_id2 == -1) break; /* secondary ac97 not available */ codec = &sc->sc_codec[i]; memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev)); codec->sc = sc; codec->id = i == 1 ? ac97_id2 : 0; codec->status_data = statregs[i].data; codec->status_addr = statregs[i].addr; codec->host_if.arg = codec; codec->host_if.attach = yds_attach_codec; codec->host_if.read = yds_read_codec; codec->host_if.write = yds_write_codec; codec->host_if.reset = yds_reset_codec; if ((r = ac97_attach(&codec->host_if)) != 0) { printf("%s: can't attach codec (error 0x%X)\n", sc->sc_dev.dv_xname, r); return; } } /* Just enable the DAC and master volumes by default */ ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; /* off */ ctl.dev = yds_get_portnum_by_name(sc, AudioCoutputs, AudioNmaster, AudioNmute); yds_mixer_set_port(sc, &ctl); ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs, AudioNdac, AudioNmute); yds_mixer_set_port(sc, &ctl); ctl.dev = yds_get_portnum_by_name(sc, AudioCinputs, AudioNcd, AudioNmute); yds_mixer_set_port(sc, &ctl); ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord, AudioNvolume, AudioNmute); yds_mixer_set_port(sc, &ctl); ctl.dev = yds_get_portnum_by_name(sc, AudioCrecord, AudioNsource, NULL); ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; yds_mixer_set_port(sc, &ctl); /* Set a reasonable default volume */ ctl.type = AUDIO_MIXER_VALUE; ctl.un.value.num_channels = 2; ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127; ctl.dev = sc->sc_codec[0].codec_if->vtbl->get_portnum_by_name( sc->sc_codec[0].codec_if, AudioCoutputs, AudioNmaster, NULL); yds_mixer_set_port(sc, &ctl); audio_attach_mi(&yds_hw_if, sc, &sc->sc_dev); /* Watch for power changes */ sc->suspend = DVACT_RESUME; yds_configure_legacy(sc); }
static void yds_attach(device_t parent, device_t self, void *aux) { struct yds_softc *sc; struct pci_attach_args *pa; pci_chipset_tag_t pc; char const *intrstr; pci_intr_handle_t ih; pcireg_t reg; struct yds_codec_softc *codec; int i, r, to; int revision; int ac97_id2; char intrbuf[PCI_INTRSTR_LEN]; sc = device_private(self); sc->sc_dev = self; pa = (struct pci_attach_args *)aux; pc = pa->pa_pc; revision = PCI_REVISION(pa->pa_class); pci_aprint_devinfo(pa, NULL); /* Map register to memory */ if (pci_mapreg_map(pa, YDS_PCI_MBA, PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, NULL)) { aprint_error_dev(self, "can't map memory space\n"); return; } /* Map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_AUDIO); /* XXX IPL_NONE? */ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, yds_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); sc->sc_dmatag = pa->pa_dmat; sc->sc_pc = pc; sc->sc_pcitag = pa->pa_tag; sc->sc_id = pa->pa_id; sc->sc_revision = revision; sc->sc_flags = yds_get_dstype(sc->sc_id); #ifdef AUDIO_DEBUG if (ydsdebug) { char bits[80]; snprintb(bits, sizeof(bits), YDS_CAP_BITS, sc->sc_flags); printf("%s: chip has %s\n", device_xname(self), bits); } #endif /* Disable legacy mode */ reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_LEGACY); pci_conf_write(pc, pa->pa_tag, YDS_PCI_LEGACY, reg & YDS_PCI_LEGACY_LAD); /* Enable the device. */ reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE); pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); /* Mute all volumes */ for (i = 0x80; i < 0xc0; i += 2) YWRITE2(sc, i, 0); /* Initialize the device */ if (yds_init(sc)) { aprint_error_dev(self, "initialize failed\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } /* * Detect primary/secondary AC97 * YMF754 Hardware Specification Rev 1.01 page 24 */ reg = pci_conf_read(pc, pa->pa_tag, YDS_PCI_DSCTRL); pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg & ~YDS_DSCTRL_CRST); delay(400000); /* Needed for 740C. */ /* Primary */ for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0) break; delay(1); } if (to == AC97_TIMEOUT) { aprint_error_dev(self, "no AC97 available\n"); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } /* Secondary */ /* Secondary AC97 is used for 4ch audio. Currently unused. */ ac97_id2 = -1; if ((YREAD2(sc, YDS_ACTIVITY) & YDS_ACTIVITY_DOCKA) == 0) goto detected; #if 0 /* reset secondary... */ YWRITE2(sc, YDS_GPIO_OCTRL, YREAD2(sc, YDS_GPIO_OCTRL) & ~YDS_GPIO_GPO2); YWRITE2(sc, YDS_GPIO_FUNCE, (YREAD2(sc, YDS_GPIO_FUNCE)&(~YDS_GPIO_GPC2))|YDS_GPIO_GPE2); #endif for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY) == 0) break; delay(1); } if (to < AC97_TIMEOUT) { /* detect id */ for (ac97_id2 = 1; ac97_id2 < 4; ac97_id2++) { YWRITE2(sc, AC97_CMD_ADDR, AC97_CMD_READ | AC97_ID(ac97_id2) | 0x28); for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR2) & AC97_BUSY) == 0) goto detected; delay(1); } } if (ac97_id2 == 4) ac97_id2 = -1; detected: ; } pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg | YDS_DSCTRL_CRST); delay (20); pci_conf_write(pc, pa->pa_tag, YDS_PCI_DSCTRL, reg & ~YDS_DSCTRL_CRST); delay (400000); for (to = 0; to < AC97_TIMEOUT; to++) { if ((YREAD2(sc, AC97_STAT_ADDR1) & AC97_BUSY) == 0) break; delay(1); } /* * Attach ac97 codec */ for (i = 0; i < 2; i++) { static struct { int data; int addr; } statregs[] = { {AC97_STAT_DATA1, AC97_STAT_ADDR1}, {AC97_STAT_DATA2, AC97_STAT_ADDR2}, }; if (i == 1 && ac97_id2 == -1) break; /* secondary ac97 not available */ codec = &sc->sc_codec[i]; codec->sc = sc; codec->id = i == 1 ? ac97_id2 : 0; codec->status_data = statregs[i].data; codec->status_addr = statregs[i].addr; codec->host_if.arg = codec; codec->host_if.attach = yds_attach_codec; codec->host_if.read = yds_read_codec; codec->host_if.write = yds_write_codec; codec->host_if.reset = yds_reset_codec; r = ac97_attach(&codec->host_if, self, &sc->sc_lock); if (r != 0) { aprint_error_dev(self, "can't attach codec (error 0x%X)\n", r); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } } if (0 != auconv_create_encodings(yds_formats, YDS_NFORMATS, &sc->sc_encodings)) { mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } audio_attach_mi(&yds_hw_if, sc, self); sc->sc_legacy_iot = pa->pa_iot; config_defer(self, yds_configure_legacy); if (!pmf_device_register(self, yds_suspend, yds_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); }
void auvia_attach(struct device *parent, struct device *self, void *aux) { struct pci_attach_args *pa = aux; struct auvia_softc *sc = (struct auvia_softc *) self; const char *intrstr = NULL; struct mixer_ctrl ctl; pci_chipset_tag_t pc = pa->pa_pc; pcitag_t pt = pa->pa_tag; pci_intr_handle_t ih; bus_size_t iosize; pcireg_t pr; int r, i; sc->sc_play.sc_base = AUVIA_PLAY_BASE; sc->sc_record.sc_base = AUVIA_RECORD_BASE; if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97) { sc->sc_flags |= AUVIA_FLAGS_VT8233; sc->sc_play.sc_base = VIA8233_MP_BASE; sc->sc_record.sc_base = VIA8233_WR_BASE; } if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0)) { printf(": can't map i/o space\n"); return; } sc->sc_dmat = pa->pa_dmat; sc->sc_pc = pc; sc->sc_pt = pt; if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, auvia_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"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); return; } printf(": %s\n", intrstr); /* disable SBPro compat & others */ pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK); pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */ /* XXX what to do about MIDI, FM, joystick? */ pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST | AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD); pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB); pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr); sc->sc_pci_junk = pr; sc->host_if.arg = sc; sc->host_if.attach = auvia_attach_codec; sc->host_if.read = auvia_read_codec; sc->host_if.write = auvia_write_codec; sc->host_if.reset = auvia_reset_codec; sc->host_if.spdif_event = auvia_spdif_event; if ((r = ac97_attach(&sc->host_if)) != 0) { printf("%s: can't attach codec (error 0x%X)\n", sc->sc_dev.dv_xname, r); pci_intr_disestablish(pc, sc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); return; } /* disable mutes */ for (i = 0; i < 4; i++) { static struct { char *class, *device; } d[] = { { AudioCoutputs, AudioNmaster}, { AudioCinputs, AudioNdac}, { AudioCinputs, AudioNcd}, { AudioCrecord, AudioNvolume}, }; ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, d[i].class, d[i].device, AudioNmute); auvia_set_port(sc, &ctl); } /* set a reasonable default volume */ ctl.type = AUDIO_MIXER_VALUE; ctl.un.value.num_channels = 2; ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = \ ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 199; ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, AudioCoutputs, AudioNmaster, NULL); auvia_set_port(sc, &ctl); audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev); sc->codec_if->vtbl->unlock(sc->codec_if); }
void cs4280_attach(struct device *parent, struct device *self, void *aux) { struct cs4280_softc *sc = (struct cs4280_softc *) self; struct pci_attach_args *pa = (struct pci_attach_args *) aux; pci_chipset_tag_t pc = pa->pa_pc; char const *intrstr; pci_intr_handle_t ih; u_int32_t mem; /* Map I/O register */ if (pci_mapreg_map(pa, CSCC_PCI_BA0, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t, &sc->ba0h, NULL, NULL, 0)) { printf(": can't map BA0 space\n"); return; } if (pci_mapreg_map(pa, CSCC_PCI_BA1, PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t, &sc->ba1h, NULL, NULL, 0)) { printf(": can't map BA1 space\n"); return; } sc->sc_dmatag = pa->pa_dmat; /* Get out of power save mode if needed. */ pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* LATENCY_TIMER setting */ mem = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); if ( PCI_LATTIMER(mem) < 32 ) { mem &= 0xffff00ff; mem |= 0x00002000; pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, mem); } /* 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 | IPL_MPSAFE, cs4280_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); /* Initialization */ if (cs4280_init(sc, 1) != 0) return; mountroothook_establish(cs4280_attachhook, sc); /* AC 97 attachement */ sc->host_if.arg = sc; sc->host_if.attach = cs4280_attach_codec; sc->host_if.read = cs4280_read_codec; sc->host_if.write = cs4280_write_codec; sc->host_if.reset = cs4280_reset_codec; if (ac97_attach(&sc->host_if) != 0) { printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname); return; } }
void fms_attach(struct device *parent, struct device *self, void *aux) { struct pci_attach_args *pa = aux; struct fms_softc *sc = (struct fms_softc *) self; struct audio_attach_args aa; pci_chipset_tag_t pc = pa->pa_pc; pcitag_t pt = pa->pa_tag; pci_intr_handle_t ih; bus_size_t iosize; const char *intrstr; u_int16_t k1; int i; if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0)) { printf(": can't map i/o space\n"); return; } if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x30, 2, &sc->sc_mpu_ioh)) { printf(": can't get mpu subregion handle\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); return; } if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x68, 4, &sc->sc_opl_ioh)) { printf(": can't get opl subregion handle\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); return; } if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, fms_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"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); return; } printf(": %s\n", intrstr); sc->sc_dmat = pa->pa_dmat; /* Disable legacy audio (SBPro compatibility) */ pci_conf_write(pc, pt, 0x40, 0); /* Reset codec and AC'97 */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020); delay(2); /* > 1us according to AC'97 documentation */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000); delay(1); /* > 168.2ns according to AC'97 documentation */ /* Set up volume */ bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PCM_VOLUME, 0x0808); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_FM_VOLUME, 0x0808); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_I2S_VOLUME, 0x0808); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_RECORD_SOURCE, 0x0000); /* Unmask playback, record and mpu interrupts, mask the rest */ k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK, (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) | FM_INTMASK_VOL); bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS, FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU | FM_INTSTATUS_VOL); #if NRADIO > 0 fmsradio_attach(sc); #endif /* NRADIO > 0 */ sc->host_if.arg = sc; sc->host_if.attach = fms_attach_codec; sc->host_if.read = fms_read_codec; sc->host_if.write = fms_write_codec; sc->host_if.reset = fms_reset_codec; if (ac97_attach(&sc->host_if) != 0) return; /* Turn mute off */ for (i = 0; i < 3; i++) { static struct { char *class, *device; } d[] = { { AudioCoutputs, AudioNmaster }, { AudioCinputs, AudioNdac }, { AudioCrecord, AudioNvolume } }; struct mixer_ctrl ctl; ctl.type = AUDIO_MIXER_ENUM; ctl.un.ord = 0; ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if, d[i].class, d[i].device, AudioNmute); fms_set_port(sc, &ctl); } audio_attach_mi(&fms_hw_if, sc, &sc->sc_dev); aa.type = AUDIODEV_TYPE_OPL; aa.hwif = NULL; aa.hdl = NULL; config_found(&sc->sc_dev, &aa, audioprint); aa.type = AUDIODEV_TYPE_MPU; aa.hwif = NULL; aa.hdl = NULL; sc->sc_mpu_dev = config_found(&sc->sc_dev, &aa, audioprint); }
static void auvia_attach(device_t parent, device_t self, void *aux) { struct pci_attach_args *pa; struct auvia_softc *sc; const char *intrstr; pci_chipset_tag_t pc; pcitag_t pt; pci_intr_handle_t ih; pcireg_t pr; int r; const char *revnum; /* VT823xx revision number */ char intrbuf[PCI_INTRSTR_LEN]; pa = aux; sc = device_private(self); sc->sc_dev = self; intrstr = NULL; pc = pa->pa_pc; pt = pa->pa_tag; revnum = NULL; aprint_naive(": Audio controller\n"); sc->sc_play.sc_base = AUVIA_PLAY_BASE; sc->sc_record.sc_base = AUVIA_RECORD_BASE; if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97) { sc->sc_flags |= AUVIA_FLAGS_VT8233; sc->sc_play.sc_base = VIA8233_MP_BASE; sc->sc_record.sc_base = VIA8233_WR_BASE; } if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_iosize)) { aprint_error(": can't map i/o space\n"); return; } sc->sc_dmat = pa->pa_dmat; sc->sc_pc = pc; sc->sc_pt = pt; r = PCI_REVISION(pa->pa_class); if (sc->sc_flags & AUVIA_FLAGS_VT8233) { snprintf(sc->sc_revision, sizeof(sc->sc_revision), "0x%02X", r); switch(r) { case VIA_REV_8233PRE: /* same as 8233, but should not be in the market */ revnum = "3-Pre"; break; case VIA_REV_8233C: /* 2 rec, 4 pb, 1 multi-pb */ revnum = "3C"; break; case VIA_REV_8233: /* 2 rec, 4 pb, 1 multi-pb, spdif */ revnum = "3"; break; case VIA_REV_8233A: /* 1 rec, 1 multi-pb, spdif */ revnum = "3A"; break; default: break; } if (r >= VIA_REV_8237) revnum = "7"; else if (r >= VIA_REV_8235) /* 2 rec, 4 pb, 1 multi-pb, spdif */ revnum = "5"; aprint_normal(": VIA Technologies VT823%s AC'97 Audio " "(rev %s)\n", revnum, sc->sc_revision); } else { sc->sc_revision[1] = '\0'; if (r == 0x20) { sc->sc_revision[0] = 'H'; } else if ((r >= 0x10) && (r <= 0x14)) { sc->sc_revision[0] = 'A' + (r - 0x10); } else { snprintf(sc->sc_revision, sizeof(sc->sc_revision), "0x%02X", r); } aprint_normal(": VIA Technologies VT82C686A AC'97 Audio " "(rev %s)\n", sc->sc_revision); } if (pci_intr_map(pa, &ih)) { aprint_error(": couldn't map interrupt\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); return; } intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, auvia_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); /* disable SBPro compat & others */ pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK); pr &= ~AUVIA_PCICONF_ENABLES; /* clear compat function enables */ /* XXX what to do about MIDI, FM, joystick? */ pr |= (AUVIA_PCICONF_ACLINKENAB | AUVIA_PCICONF_ACNOTRST | AUVIA_PCICONF_ACVSR | AUVIA_PCICONF_ACSGD); pr &= ~(AUVIA_PCICONF_ACFM | AUVIA_PCICONF_ACSB); pci_conf_write(pc, pt, AUVIA_PCICONF_JUNK, pr); sc->host_if.arg = sc; sc->host_if.attach = auvia_attach_codec; sc->host_if.read = auvia_read_codec; sc->host_if.write = auvia_write_codec; sc->host_if.reset = auvia_reset_codec; sc->host_if.spdif_event = auvia_spdif_event; if ((r = ac97_attach(&sc->host_if, self, &sc->sc_lock)) != 0) { aprint_error_dev(sc->sc_dev, "can't attach codec (error 0x%X)\n", r); pci_intr_disestablish(pc, sc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); return; } /* setup audio_format */ memcpy(sc->sc_formats, auvia_formats, sizeof(auvia_formats)); mutex_enter(&sc->sc_lock); if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_4CH(sc->codec_if)) { AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_8]); AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_4CH_16]); } if (sc->sc_play.sc_base != VIA8233_MP_BASE || !AC97_IS_6CH(sc->codec_if)) { AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_8]); AUFMT_INVALIDATE(&sc->sc_formats[AUVIA_FORMATS_6CH_16]); } if (AC97_IS_FIXED_RATE(sc->codec_if)) { for (r = 0; r < AUVIA_NFORMATS; r++) { sc->sc_formats[r].frequency_type = 1; sc->sc_formats[r].frequency[0] = 48000; } } mutex_exit(&sc->sc_lock); if (0 != auconv_create_encodings(sc->sc_formats, AUVIA_NFORMATS, &sc->sc_encodings)) { mutex_enter(&sc->sc_lock); sc->codec_if->vtbl->detach(sc->codec_if); mutex_exit(&sc->sc_lock); pci_intr_disestablish(pc, sc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); aprint_error_dev(sc->sc_dev, "can't create encodings\n"); return; } if (0 != auconv_create_encodings(auvia_spdif_formats, AUVIA_SPDIF_NFORMATS, &sc->sc_spdif_encodings)) { mutex_enter(&sc->sc_lock); sc->codec_if->vtbl->detach(sc->codec_if); mutex_exit(&sc->sc_lock); pci_intr_disestablish(pc, sc->sc_ih); bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); mutex_destroy(&sc->sc_lock); mutex_destroy(&sc->sc_intr_lock); aprint_error_dev(sc->sc_dev, "can't create spdif encodings\n"); return; } if (!pmf_device_register(self, NULL, auvia_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); audio_attach_mi(&auvia_hw_if, sc, sc->sc_dev); mutex_enter(&sc->sc_lock); sc->codec_if->vtbl->unlock(sc->codec_if); mutex_exit(&sc->sc_lock); return; }