⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sonicvibes.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	snd_iprintf(buffer, "Ext. Rx to synth : %s\n", tmp & 0x02 ? "on" : "off");	snd_iprintf(buffer, "MIDI to ext. Tx  : %s\n", tmp & 0x04 ? "on" : "off");}static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic){	struct snd_info_entry *entry;	if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry))		snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read);}/* */#ifdef SUPPORT_JOYSTICKstatic struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata =SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic){	struct gameport *gp;	sonic->gameport = gp = gameport_allocate_port();	if (!gp) {		printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n");		return -ENOMEM;	}	gameport_set_name(gp, "SonicVibes Gameport");	gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci));	gameport_set_dev_parent(gp, &sonic->pci->dev);	gp->io = sonic->game_port;	gameport_register_port(gp);	snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));	return 0;}static void snd_sonicvibes_free_gameport(struct sonicvibes *sonic){	if (sonic->gameport) {		gameport_unregister_port(sonic->gameport);		sonic->gameport = NULL;	}}#elsestatic inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { return -ENOSYS; }static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }#endifstatic int snd_sonicvibes_free(struct sonicvibes *sonic){	snd_sonicvibes_free_gameport(sonic);	pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);	pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);	if (sonic->irq >= 0)		free_irq(sonic->irq, sonic);	release_and_free_resource(sonic->res_dmaa);	release_and_free_resource(sonic->res_dmac);	pci_release_regions(sonic->pci);	pci_disable_device(sonic->pci);	kfree(sonic);	return 0;}static int snd_sonicvibes_dev_free(struct snd_device *device){	struct sonicvibes *sonic = device->device_data;	return snd_sonicvibes_free(sonic);}static int __devinit snd_sonicvibes_create(struct snd_card *card,					struct pci_dev *pci,					int reverb,					int mge,					struct sonicvibes ** rsonic){	struct sonicvibes *sonic;	unsigned int dmaa, dmac;	int err;	static struct snd_device_ops ops = {		.dev_free =	snd_sonicvibes_dev_free,	};	*rsonic = NULL;	/* enable PCI device */	if ((err = pci_enable_device(pci)) < 0)		return err;	/* check, if we can restrict PCI DMA transfers to 24 bits */        if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||	    pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {		snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");		pci_disable_device(pci);                return -ENXIO;        }	sonic = kzalloc(sizeof(*sonic), GFP_KERNEL);	if (sonic == NULL) {		pci_disable_device(pci);		return -ENOMEM;	}	spin_lock_init(&sonic->reg_lock);	sonic->card = card;	sonic->pci = pci;	sonic->irq = -1;	if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) {		kfree(sonic);		pci_disable_device(pci);		return err;	}	sonic->sb_port = pci_resource_start(pci, 0);	sonic->enh_port = pci_resource_start(pci, 1);	sonic->synth_port = pci_resource_start(pci, 2);	sonic->midi_port = pci_resource_start(pci, 3);	sonic->game_port = pci_resource_start(pci, 4);	if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_SHARED,			"S3 SonicVibes", sonic)) {		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);		snd_sonicvibes_free(sonic);		return -EBUSY;	}	sonic->irq = pci->irq;	pci_read_config_dword(pci, 0x40, &dmaa);	pci_read_config_dword(pci, 0x48, &dmac);	dmaio &= ~0x0f;	dmaa &= ~0x0f;	dmac &= ~0x0f;	if (!dmaa) {		dmaa = dmaio;		dmaio += 0x10;		snd_printk(KERN_INFO "BIOS did not allocate DDMA channel A i/o, allocated at 0x%x\n", dmaa);	}	if (!dmac) {		dmac = dmaio;		dmaio += 0x10;		snd_printk(KERN_INFO "BIOS did not allocate DDMA channel C i/o, allocated at 0x%x\n", dmac);	}	pci_write_config_dword(pci, 0x40, dmaa);	pci_write_config_dword(pci, 0x48, dmac);	if ((sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A")) == NULL) {		snd_sonicvibes_free(sonic);		snd_printk(KERN_ERR "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1);		return -EBUSY;	}	if ((sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C")) == NULL) {		snd_sonicvibes_free(sonic);		snd_printk(KERN_ERR "unable to grab DDMA-C port at 0x%x-0x%x\n", dmac, dmac + 0x10 - 1);		return -EBUSY;	}	pci_read_config_dword(pci, 0x40, &sonic->dmaa_port);	pci_read_config_dword(pci, 0x48, &sonic->dmac_port);	sonic->dmaa_port &= ~0x0f;	sonic->dmac_port &= ~0x0f;	pci_write_config_dword(pci, 0x40, sonic->dmaa_port | 9);	/* enable + enhanced */	pci_write_config_dword(pci, 0x48, sonic->dmac_port | 9);	/* enable */	/* ok.. initialize S3 SonicVibes chip */	outb(SV_RESET, SV_REG(sonic, CONTROL));		/* reset chip */	udelay(100);	outb(0, SV_REG(sonic, CONTROL));	/* release reset */	udelay(100);	outb(SV_ENHANCED | SV_INTA | (reverb ? SV_REVERB : 0), SV_REG(sonic, CONTROL));	inb(SV_REG(sonic, STATUS));	/* clear IRQs */#if 1	snd_sonicvibes_out(sonic, SV_IREG_DRIVE_CTRL, 0);	/* drive current 16mA */#else	snd_sonicvibes_out(sonic, SV_IREG_DRIVE_CTRL, 0x40);	/* drive current 8mA */#endif	snd_sonicvibes_out(sonic, SV_IREG_PC_ENABLE, sonic->enable = 0);	/* disable playback & capture */	outb(sonic->irqmask = ~(SV_DMAA_MASK | SV_DMAC_MASK | SV_UD_MASK), SV_REG(sonic, IRQMASK));	inb(SV_REG(sonic, STATUS));	/* clear IRQs */	snd_sonicvibes_out(sonic, SV_IREG_ADC_CLOCK, 0);	/* use PLL as clock source */	snd_sonicvibes_out(sonic, SV_IREG_ANALOG_POWER, 0);	/* power up analog parts */	snd_sonicvibes_out(sonic, SV_IREG_DIGITAL_POWER, 0);	/* power up digital parts */	snd_sonicvibes_setpll(sonic, SV_IREG_ADC_PLL, 8000);	snd_sonicvibes_out(sonic, SV_IREG_SRS_SPACE, sonic->srs_space = 0x80);	/* SRS space off */	snd_sonicvibes_out(sonic, SV_IREG_SRS_CENTER, sonic->srs_center = 0x00);/* SRS center off */	snd_sonicvibes_out(sonic, SV_IREG_MPU401, sonic->mpu_switch = 0x05);	/* MPU-401 switch */	snd_sonicvibes_out(sonic, SV_IREG_WAVE_SOURCE, sonic->wave_source = 0x00);	/* onboard ROM */	snd_sonicvibes_out(sonic, SV_IREG_PCM_RATE_LOW, (8000 * 65536 / SV_FULLRATE) & 0xff);	snd_sonicvibes_out(sonic, SV_IREG_PCM_RATE_HIGH, ((8000 * 65536 / SV_FULLRATE) >> 8) & 0xff);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_ADC, mge ? 0xd0 : 0xc0);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_ADC, 0xc0);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_AUX1, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_AUX1, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_CD, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_CD, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_LINE, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_LINE, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_MIC, 0x8f);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_SYNTH, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_SYNTH, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_AUX2, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_AUX2, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_ANALOG, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_ANALOG, 0x9f);	snd_sonicvibes_out(sonic, SV_IREG_LEFT_PCM, 0xbf);	snd_sonicvibes_out(sonic, SV_IREG_RIGHT_PCM, 0xbf);	snd_sonicvibes_out(sonic, SV_IREG_ADC_OUTPUT_CTRL, 0xfc);#if 0	snd_sonicvibes_debug(sonic);#endif	sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) {		snd_sonicvibes_free(sonic);		return err;	}	snd_sonicvibes_proc_init(sonic);	snd_card_set_dev(card, &pci->dev);	*rsonic = sonic;	return 0;}/* *  MIDI section */static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),SONICVIBES_SINGLE("SonicVibes External Rx to Synth", 0, SV_IREG_MPU401, 1, 1, 0),SONICVIBES_SINGLE("SonicVibes External Tx", 0, SV_IREG_MPU401, 2, 1, 0)};static int snd_sonicvibes_midi_input_open(struct snd_mpu401 * mpu){	struct sonicvibes *sonic = mpu->private_data;	outb(sonic->irqmask &= ~SV_MIDI_MASK, SV_REG(sonic, IRQMASK));	return 0;}static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu){	struct sonicvibes *sonic = mpu->private_data;	outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));}static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,					 struct snd_rawmidi *rmidi){	struct snd_mpu401 * mpu = rmidi->private_data;	struct snd_card *card = sonic->card;	struct snd_rawmidi_str *dir;	unsigned int idx;	int err;	mpu->private_data = sonic;	mpu->open_input = snd_sonicvibes_midi_input_open;	mpu->close_input = snd_sonicvibes_midi_input_close;	dir = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++)		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0)			return err;	return 0;}static int __devinit snd_sonic_probe(struct pci_dev *pci,				     const struct pci_device_id *pci_id){	static int dev;	struct snd_card *card;	struct sonicvibes *sonic;	struct snd_rawmidi *midi_uart;	struct snd_opl3 *opl3;	int idx, err;	if (dev >= SNDRV_CARDS)		return -ENODEV;	if (!enable[dev]) {		dev++;		return -ENOENT;	} 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);	if (card == NULL)		return -ENOMEM;	for (idx = 0; idx < 5; idx++) {		if (pci_resource_start(pci, idx) == 0 ||		    !(pci_resource_flags(pci, idx) & IORESOURCE_IO)) {			snd_card_free(card);			return -ENODEV;		}	}	if ((err = snd_sonicvibes_create(card, pci,					 reverb[dev] ? 1 : 0,					 mge[dev] ? 1 : 0,					 &sonic)) < 0) {		snd_card_free(card);		return err;	}	strcpy(card->driver, "SonicVibes");	strcpy(card->shortname, "S3 SonicVibes");	sprintf(card->longname, "%s rev %i at 0x%llx, irq %i",		card->shortname,		sonic->revision,		(unsigned long long)pci_resource_start(pci, 1),		sonic->irq);	if ((err = snd_sonicvibes_pcm(sonic, 0, NULL)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_sonicvibes_mixer(sonic)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,				       sonic->midi_port, MPU401_INFO_INTEGRATED,				       sonic->irq, 0,				       &midi_uart)) < 0) {		snd_card_free(card);		return err;	}	snd_sonicvibes_midi(sonic, midi_uart);	if ((err = snd_opl3_create(card, sonic->synth_port,				   sonic->synth_port + 2,				   OPL3_HW_OPL3_SV, 1, &opl3)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {		snd_card_free(card);		return err;	}	snd_sonicvibes_create_gameport(sonic);	if ((err = snd_card_register(card)) < 0) {		snd_card_free(card);		return err;	}		pci_set_drvdata(pci, card);	dev++;	return 0;}static void __devexit snd_sonic_remove(struct pci_dev *pci){	snd_card_free(pci_get_drvdata(pci));	pci_set_drvdata(pci, NULL);}static struct pci_driver driver = {	.name = "S3 SonicVibes",	.id_table = snd_sonic_ids,	.probe = snd_sonic_probe,	.remove = __devexit_p(snd_sonic_remove),};static int __init alsa_card_sonicvibes_init(void){	return pci_register_driver(&driver);}static void __exit alsa_card_sonicvibes_exit(void){	pci_unregister_driver(&driver);}module_init(alsa_card_sonicvibes_init)module_exit(alsa_card_sonicvibes_exit)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -