Example #1
0
void
Mixer::Init()
{
	ac97_attach(&fAC97Dev, _ReadAC97, _WriteAC97, this,
			fDevice->PCIInfo().u.h0.subsystem_vendor_id,
			fDevice->PCIInfo().u.h0.subsystem_id);

	_ReadSupportedFormats();
}
Example #2
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, 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
}
Example #3
0
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");
}
Example #4
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
}
Example #5
0
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);
}
Example #6
0
File: neo.c Project: bluhm/sys
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");
}
Example #8
0
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);
}
Example #9
0
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");
}
Example #10
0
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);
}
Example #11
0
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;
	}
}
Example #12
0
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);
}
Example #13
0
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;
}