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

📄 interwave.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
}static void __devinit snd_interwave_init(int dev, snd_gus_card_t * gus){	unsigned long flags;	/* ok.. some InterWave specific initialization */	spin_lock_irqsave(&gus->reg_lock, flags);	snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0x00);	snd_gf1_write8(gus, SNDRV_GF1_GB_COMPATIBILITY, 0x1f);	snd_gf1_write8(gus, SNDRV_GF1_GB_DECODE_CONTROL, 0x49);	snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, 0x11);	snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A, 0x00);	snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B, 0x30);	snd_gf1_write8(gus, SNDRV_GF1_GB_EMULATION_IRQ, 0x00);	spin_unlock_irqrestore(&gus->reg_lock, flags);	gus->equal_irq = 1;	gus->codec_flag = 1;	gus->interwave = 1;	gus->max_flag = 1;	gus->joystick_dac = joystick_dac[dev];}static snd_kcontrol_new_t snd_interwave_controls[] = {CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1),CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)};static int __devinit snd_interwave_mixer(cs4231_t *chip){	snd_card_t *card = chip->card;	snd_ctl_elem_id_t id1, id2;	unsigned int idx;	int err;	memset(&id1, 0, sizeof(id1));	memset(&id2, 0, sizeof(id2));	id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;#if 0	/* remove mono microphone controls */	strcpy(id1.name, "Mic Playback Switch");	if ((err = snd_ctl_remove_id(card, &id1)) < 0)		return err;	strcpy(id1.name, "Mic Playback Volume");	if ((err = snd_ctl_remove_id(card, &id1)) < 0)		return err;#endif	/* add new master and mic controls */	for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++)		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0)			return err;	snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);	snd_cs4231_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f);	snd_cs4231_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f);	snd_cs4231_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f);	/* reassign AUXA to SYNTHESIZER */	strcpy(id1.name, "Aux Playback Switch");	strcpy(id2.name, "Synth Playback Switch");	if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)		return err;	strcpy(id1.name, "Aux Playback Volume");	strcpy(id2.name, "Synth Playback Volume");	if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)		return err;	/* reassign AUXB to CD */	strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;	strcpy(id2.name, "CD Playback Switch");	if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)		return err;	strcpy(id1.name, "Aux Playback Volume");	strcpy(id2.name, "CD Playback Volume");	if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)		return err;	return 0;}#ifdef CONFIG_PNPstatic int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard,				       struct pnp_card_link *card,				       const struct pnp_card_device_id *id){	struct pnp_dev *pdev;	struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);	int err;	iwcard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);	if (iwcard->dev == NULL) {		kfree(cfg);		return -EBUSY;	}#ifdef SNDRV_STB	iwcard->devtc = pnp_request_card_device(card, id->devs[1].id, NULL);	if (iwcard->devtc == NULL) {		kfree(cfg);		return -EBUSY;	}#endif	/* Synth & Codec initialization */	pdev = iwcard->dev;	pnp_init_resource_table(cfg);	if (port[dev] != SNDRV_AUTO_PORT) {		pnp_resource_change(&cfg->port_resource[0], port[dev], 16);		pnp_resource_change(&cfg->port_resource[1], port[dev] + 0x100, 12);		pnp_resource_change(&cfg->port_resource[2], port[dev] + 0x10c, 4);	}	if (dma1[dev] != SNDRV_AUTO_DMA)		pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1);	if (dma2[dev] != SNDRV_AUTO_DMA)		pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1);	if (dma2[dev] < 0)		pnp_resource_change(&cfg->dma_resource[1], 4, 1);	if (irq[dev] != SNDRV_AUTO_IRQ)		pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);        if (pnp_manual_config_dev(pdev, cfg, 0) < 0)		snd_printk(KERN_ERR "InterWave - Synth - the requested resources are invalid, using auto config\n");	err = pnp_activate_dev(pdev);	if (err < 0) {		kfree(cfg);		snd_printk(KERN_ERR "InterWave PnP configure failure (out of resources?)\n");		return err;	}	if (pnp_port_start(pdev, 0) + 0x100 != pnp_port_start(pdev, 1) ||	    pnp_port_start(pdev, 0) + 0x10c != pnp_port_start(pdev, 2)) {		kfree(cfg);		snd_printk(KERN_ERR "PnP configure failure (wrong ports)\n");		return -ENOENT;	}	port[dev] = pnp_port_start(pdev, 0);	dma1[dev] = pnp_dma(pdev, 0);	if (dma2[dev] >= 0)		dma2[dev] = pnp_dma(pdev, 1);	irq[dev] = pnp_irq(pdev, 0);	snd_printdd("isapnp IW: sb port=0x%lx, gf1 port=0x%lx, codec port=0x%lx\n",				pnp_port_start(pdev, 0),				pnp_port_start(pdev, 1),				pnp_port_start(pdev, 2));	snd_printdd("isapnp IW: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]);#ifdef SNDRV_STB	/* Tone Control initialization */	pdev = iwcard->devtc;	pnp_init_resource_table(cfg);	if (port_tc[dev] != SNDRV_AUTO_PORT)		pnp_resource_change(&cfg->port_resource[0], port_tc[dev], 1);        if (pnp_manual_config_dev(pdev, cfg, 0) < 0)		snd_printk(KERN_ERR "InterWave - ToneControl - the requested resources are invalid, using auto config\n");	err = pnp_activate_dev(pdev);	if (err < 0) {		kfree(cfg);		snd_printk(KERN_ERR "InterWave ToneControl PnP configure failure (out of resources?)\n");		return err;	}	port_tc[dev] = pnp_port_start(pdev, 0);	snd_printdd("isapnp IW: tone control port=0x%lx\n", port_tc[dev]);#endif	kfree(cfg);	return 0;}#endif /* CONFIG_PNP */static void snd_interwave_free(snd_card_t *card){	struct snd_interwave *iwcard = (struct snd_interwave *)card->private_data;	if (iwcard == NULL)		return;#ifdef SNDRV_STB	release_and_free_resource(iwcard->i2c_res);#endif	if (iwcard->irq >= 0)		free_irq(iwcard->irq, (void *)iwcard);}static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,				         const struct pnp_card_device_id *pid){	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};	static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};	int xirq, xdma1, xdma2;	snd_card_t *card;	struct snd_interwave *iwcard;	cs4231_t *cs4231;	snd_gus_card_t *gus;#ifdef SNDRV_STB	snd_i2c_bus_t *i2c_bus;#endif	snd_pcm_t *pcm;	char *str;	int err;	card = snd_card_new(index[dev], id[dev], THIS_MODULE,			    sizeof(struct snd_interwave));	if (card == NULL)		return -ENOMEM;	iwcard = (struct snd_interwave *)card->private_data;	iwcard->card = card;	iwcard->irq = -1;	card->private_free = snd_interwave_free;#ifdef CONFIG_PNP	if (isapnp[dev]) {		if ((err = snd_interwave_pnp(dev, iwcard, pcard, pid)) < 0)			goto _err;		snd_card_set_dev(card, &pcard->card->dev);	}#endif	xirq = irq[dev];	if (xirq == SNDRV_AUTO_IRQ) {		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");			err = -EBUSY;			goto _err;		}	}	xdma1 = dma1[dev];	if (xdma1 == SNDRV_AUTO_DMA) {		if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {			snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");			err = -EBUSY;			goto _err;		}	}	xdma2 = dma2[dev];	if (xdma2 == SNDRV_AUTO_DMA) {		if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {			snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");			err = -EBUSY;			goto _err;		}	}	if ((err = snd_gus_create(card,				  port[dev],				  -xirq, xdma1, xdma2,				  0, 32,				  pcm_channels[dev], effect[dev], &gus)) < 0)		goto _err;	if ((err = snd_interwave_detect(iwcard, gus, dev#ifdef SNDRV_STB            , &i2c_bus#endif	    )) < 0)		goto _err;	iwcard->gus_status_reg = gus->gf1.reg_irqstat;	iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;	snd_interwave_init(dev, gus);	snd_interwave_detect_memory(gus);	if ((err = snd_gus_initialize(gus)) < 0)		goto _err;	if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) {		snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);		err = -EBUSY;		goto _err;	}	iwcard->irq = xirq;	if ((err = snd_cs4231_create(card,				     gus->gf1.port + 0x10c, -1, xirq,				     xdma2 < 0 ? xdma1 : xdma2, xdma1,				     CS4231_HW_INTERWAVE,				     CS4231_HWSHARE_IRQ |				     CS4231_HWSHARE_DMA1 |				     CS4231_HWSHARE_DMA2,				     &cs4231)) < 0)		goto _err;	if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0)		goto _err;	sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');	strcat(pcm->name, " (codec)");	if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0)		goto _err;	if ((err = snd_cs4231_mixer(cs4231)) < 0)		goto _err;	if (pcm_channels[dev] > 0) {		if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)			goto _err;	}	if ((err = snd_interwave_mixer(cs4231)) < 0)		goto _err;#ifdef SNDRV_STB	{		snd_ctl_elem_id_t id1, id2;		memset(&id1, 0, sizeof(id1));		memset(&id2, 0, sizeof(id2));		id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;		strcpy(id1.name, "Master Playback Switch");		strcpy(id2.name, id1.name);		id2.index = 1;		if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)			goto _err;		strcpy(id1.name, "Master Playback Volume");		strcpy(id2.name, id1.name);		if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)			goto _err;		if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0)			goto _err;	}#endif	gus->uart_enable = midi[dev];	if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)		goto _err;#ifndef SNDRV_STB	str = "AMD InterWave";	if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8)		str = "Dynasonic 3-D";#else	str = "InterWave STB";#endif	strcpy(card->driver, str);	strcpy(card->shortname, str);	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %d",		str,		gus->gf1.port,		xirq,		xdma1);	if (xdma2 >= 0)		sprintf(card->longname + strlen(card->longname), "&%d", xdma2);	if ((err = snd_card_set_generic_dev(card)) < 0)		goto _err;	if ((err = snd_card_register(card)) < 0)		goto _err;		iwcard->cs4231 = cs4231;	iwcard->gus = gus;	if (pcard)		pnp_set_card_drvdata(pcard, card);	else		snd_interwave_legacy[dev++] = card;	return 0; _err:	snd_card_free(card);	return err;}static int __devinit snd_interwave_probe_legacy_port(unsigned long xport){	static int dev;	int res;	for ( ; dev < SNDRV_CARDS; dev++) {		if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)                        continue;#ifdef CONFIG_PNP		if (isapnp[dev])			continue;#endif		port[dev] = xport;		res = snd_interwave_probe(dev, NULL, NULL);		if (res < 0)			port[dev] = SNDRV_AUTO_PORT;		return res;	}	return -ENODEV;}#ifdef CONFIG_PNPstatic int __devinit snd_interwave_pnp_detect(struct pnp_card_link *card,					   const struct pnp_card_device_id *id){	static int dev;	int res;	for ( ; dev < SNDRV_CARDS; dev++) {		if (!enable[dev] || !isapnp[dev])			continue;		res = snd_interwave_probe(dev, card, id);		if (res < 0)			return res;		dev++;		return 0;        }        return -ENODEV;}static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard){	snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);	snd_card_disconnect(card);	snd_card_free_in_thread(card);}static struct pnp_card_driver interwave_pnpc_driver = {	.flags = PNP_DRIVER_RES_DISABLE,	.name = "interwave",	.id_table = snd_interwave_pnpids,	.probe = snd_interwave_pnp_detect,	.remove = __devexit_p(snd_interwave_pnp_remove),};#endif /* CONFIG_PNP */static int __init alsa_card_interwave_init(void){	int cards = 0, i;	static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260, -1};	int dev;	for (dev = 0; dev < SNDRV_CARDS; dev++) {		if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)			continue;#ifdef CONFIG_PNP		if (isapnp[dev])			continue;#endif		if (!snd_interwave_probe(dev, NULL, NULL)) {			cards++;			continue;		}#ifdef MODULE		printk(KERN_ERR "InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]);#endif	}	/* legacy auto configured cards */	i = snd_legacy_auto_probe(possible_ports, snd_interwave_probe_legacy_port);	if (i > 0)		cards += i;#ifdef CONFIG_PNP	/* ISA PnP cards */	i = pnp_register_card_driver(&interwave_pnpc_driver);	if (i > 0)		cards += i;#endif	if (!cards) {#ifdef CONFIG_PNP		pnp_unregister_card_driver(&interwave_pnpc_driver);#endif#ifdef MODULE		printk(KERN_ERR "InterWave soundcard not found or device busy\n");#endif		return -ENODEV;	}	return 0;}static void __exit alsa_card_interwave_exit(void){	int dev;#ifdef CONFIG_PNP	/* PnP cards first */	pnp_unregister_card_driver(&interwave_pnpc_driver);#endif	for (dev = 0; dev < SNDRV_CARDS; dev++)		snd_card_free(snd_interwave_legacy[dev]);}module_init(alsa_card_interwave_init)module_exit(alsa_card_interwave_exit)

⌨️ 快捷键说明

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