Beispiel #1
0
void
cs4280_attachhook(void *xsc)
{
	struct cs4280_softc *sc = xsc;
	mixer_ctrl_t ctl;

	/* Initialization */
	if (cs4280_init2(sc, 1) != 0)
		return;

	printf("%s: firmware loaded\n", sc->sc_dev.dv_xname);

	/* Turn mute off of DAC, CD and master volumes by default */
	ctl.type = AUDIO_MIXER_ENUM;
	ctl.un.ord = 0;	 /* off */

	ctl.dev = cs4280_get_portnum_by_name(sc, AudioCoutputs,
					     AudioNmaster, AudioNmute);
	cs4280_mixer_set_port(sc, &ctl);

	ctl.dev = cs4280_get_portnum_by_name(sc, AudioCinputs,
					     AudioNdac, AudioNmute);
	cs4280_mixer_set_port(sc, &ctl);

	ctl.dev = cs4280_get_portnum_by_name(sc, AudioCinputs,
					     AudioNcd, AudioNmute);
	cs4280_mixer_set_port(sc, &ctl);
	
	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
}
Beispiel #2
0
void
sbattach(struct sbdsp_softc *sc)
{
	struct audio_attach_args arg;
#if NMIDI > 0
	struct midi_hw_if *mhw = &sb_midi_hw_if;
#endif

	sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->sc_irq,
	    IST_EDGE, IPL_AUDIO | IPL_MPSAFE,
	    sbdsp_intr, sc, sc->sc_dev.dv_xname);

	sbdsp_attach(sc);

#if NMIDI > 0
	sc->sc_hasmpu = 0;
	if (ISSB16CLASS(sc) && sc->sc_mpu_sc.iobase != 0) {
		sc->sc_mpu_sc.iot = sc->sc_iot;
		if (mpu_find(&sc->sc_mpu_sc)) {
			sc->sc_hasmpu = 1;
			mhw = &sb_mpu401_hw_if;
		}
	}
	midi_attach_mi(mhw, sc, &sc->sc_dev);
#endif

	audio_attach_mi(&sb_hw_if, sc, &sc->sc_dev);

	arg.type = AUDIODEV_TYPE_OPL;
	arg.hwif = 0;
	arg.hdl = 0;
	(void)config_found(&sc->sc_dev, &arg, audioprint);
}
Beispiel #3
0
Datei: umidi.c Projekt: bluhm/sys
static usbd_status
attach_mididev(struct umidi_softc *sc, struct umidi_mididev *mididev)
{
	if (mididev->sc)
		return USBD_IN_USE;

	mididev->sc = sc;

	mididev->mdev = midi_attach_mi(&umidi_hw_if, mididev, &sc->sc_dev);

	return USBD_NORMAL_COMPLETION;
}
Beispiel #4
0
void
cms_attach(device_t parent, device_t self, void *aux)
{
	struct cms_softc *sc = device_private(self);
	struct isa_attach_args *ia = aux;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	midisyn *ms;

	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_AUDIO);

	aprint_normal("\n");

	DPRINTF(("cms_attach():\n"));

	iot = ia->ia_iot;

	if (bus_space_map(iot, ia->ia_io[0].ir_addr, CMS_IOSIZE, 0, &ioh)) {
		aprint_error_dev(self, "can't map i/o space\n");
		return;
	}

	sc->sc_iot = iot;
	sc->sc_ioh = ioh;

	/* now let's reset the chips */
	cms_reset(sc);

	/* init the synthesiser */
	ms = &sc->sc_midisyn;
	ms->mets = &midi_cms_hw;
	strcpy(ms->name, "Creative Music System");
	ms->nvoice = CMS_NVOICES;
	ms->data = sc;
	ms->lock = &sc->sc_lock;
	midisyn_init(ms);

	/* and attach the midi device with the synthesiser */
	midi_attach_mi(&midisyn_hw_if, ms, self);
}
Beispiel #5
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
}
Beispiel #6
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
}
Beispiel #7
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");
}