static int snd_gus_dev_free(struct snd_device *device)
{
	struct snd_gus_card *gus = device->device_data;
	return snd_gus_free(gus);
}
int snd_gus_create(struct snd_card *card,
		   unsigned long port,
		   int irq, int dma1, int dma2,
		   int timer_dev,
		   int voices,
		   int pcm_channels,
		   int effect,
		   struct snd_gus_card **rgus)
{
	struct snd_gus_card *gus;
	int err;
	static struct snd_device_ops ops = {
		.dev_free =	snd_gus_dev_free,
	};

	*rgus = NULL;
	gus = kzalloc(sizeof(*gus), GFP_KERNEL);
	if (gus == NULL)
		return -ENOMEM;
	spin_lock_init(&gus->reg_lock);
	spin_lock_init(&gus->voice_alloc);
	spin_lock_init(&gus->active_voice_lock);
	spin_lock_init(&gus->event_lock);
	spin_lock_init(&gus->dma_lock);
	spin_lock_init(&gus->pcm_volume_level_lock);
	spin_lock_init(&gus->uart_cmd_lock);
	mutex_init(&gus->dma_mutex);
	gus->gf1.irq = -1;
	gus->gf1.dma1 = -1;
	gus->gf1.dma2 = -1;
	gus->card = card;
	gus->gf1.port = port;
	/* fill register variables for speedup */
	gus->gf1.reg_page = GUSP(gus, GF1PAGE);
	gus->gf1.reg_regsel = GUSP(gus, GF1REGSEL);
	gus->gf1.reg_data8 = GUSP(gus, GF1DATAHIGH);
	gus->gf1.reg_data16 = GUSP(gus, GF1DATALOW);
	gus->gf1.reg_irqstat = GUSP(gus, IRQSTAT);
	gus->gf1.reg_dram = GUSP(gus, DRAM);
	gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL);
	gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA);
	/* allocate resources */
	if ((gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)")) == NULL) {
		snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port);
		snd_gus_free(gus);
		return -EBUSY;
	}
	if ((gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)")) == NULL) {
		snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100);
		snd_gus_free(gus);
		return -EBUSY;
	}
	if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) {
		snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq);
		snd_gus_free(gus);
		return -EBUSY;
	}
	gus->gf1.irq = irq;
	if (request_dma(dma1, "GUS - 1")) {
		snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1);
		snd_gus_free(gus);
		return -EBUSY;
	}
	gus->gf1.dma1 = dma1;
	if (dma2 >= 0 && dma1 != dma2) {
		if (request_dma(dma2, "GUS - 2")) {
			snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2);
			snd_gus_free(gus);
			return -EBUSY;
		}
		gus->gf1.dma2 = dma2;
	} else {
		gus->gf1.dma2 = gus->gf1.dma1;
		gus->equal_dma = 1;
	}
	gus->timer_dev = timer_dev;
	if (voices < 14)
		voices = 14;
	if (voices > 32)
		voices = 32;
	if (pcm_channels < 0)
		pcm_channels = 0;
	if (pcm_channels > 8)
		pcm_channels = 8;
	pcm_channels++;
	pcm_channels &= ~1;
	gus->gf1.effect = effect ? 1 : 0;
	gus->gf1.active_voices = voices;
	gus->gf1.pcm_channels = pcm_channels;
	gus->gf1.volume_ramp = 25;
	gus->gf1.smooth_pan = 1;
	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) {
		snd_gus_free(gus);
		return err;
	}
	*rgus = gus;
	return 0;
}
Ejemplo n.º 3
0
static int snd_gus_dev_free(snd_device_t *device)
{
	snd_gus_card_t *gus = device->device_data;
	return snd_gus_free(gus);
}