X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fdrivers%2Fopl3%2Fopl3_lib.c;h=87fe376f38f0c0744a6111195346f5f990daca76;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=e3fa31d4d73f241e96e679a1de8c091ffc7e8012;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index e3fa31d4d..87fe376f3 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -35,11 +35,9 @@ MODULE_AUTHOR("Jaroslav Kysela , Hannu Savolainen 1993-1996, Rob MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)"); MODULE_LICENSE("GPL"); -#define chip_t opl3_t - extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; -void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val) +static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) { unsigned long flags; unsigned long port; @@ -62,7 +60,7 @@ void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val) spin_unlock_irqrestore(&opl3->reg_lock, flags); } -void snd_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val) +static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val) { unsigned long flags; unsigned long port; @@ -87,29 +85,7 @@ void snd_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val) spin_unlock_irqrestore(&opl3->reg_lock, flags); } -void snd_opl3_cs4281_command(opl3_t * opl3, unsigned short cmd, unsigned char val) -{ - unsigned long flags; - unsigned long port; - - /* - * CS4281 requires a special access to I/O registers - */ - - port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port; - - spin_lock_irqsave(&opl3->reg_lock, flags); - - writel((unsigned int)cmd, port << 2); - udelay(10); - - writel((unsigned int)val, (port + 1) << 2); - udelay(30); - - spin_unlock_irqrestore(&opl3->reg_lock, flags); -} - -static int snd_opl3_detect(opl3_t * opl3) +static int snd_opl3_detect(struct snd_opl3 * opl3) { /* * This function returns 1 if the FM chip is present at the given I/O port @@ -177,12 +153,12 @@ static int snd_opl3_detect(opl3_t * opl3) * Timer 1 - 80us */ -static int snd_opl3_timer1_start(snd_timer_t * timer) +static int snd_opl3_timer1_start(struct snd_timer * timer) { unsigned long flags; unsigned char tmp; unsigned int ticks; - opl3_t *opl3; + struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); spin_lock_irqsave(&opl3->timer_lock, flags); @@ -195,11 +171,11 @@ static int snd_opl3_timer1_start(snd_timer_t * timer) return 0; } -static int snd_opl3_timer1_stop(snd_timer_t * timer) +static int snd_opl3_timer1_stop(struct snd_timer * timer) { unsigned long flags; unsigned char tmp; - opl3_t *opl3; + struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); spin_lock_irqsave(&opl3->timer_lock, flags); @@ -214,12 +190,12 @@ static int snd_opl3_timer1_stop(snd_timer_t * timer) * Timer 2 - 320us */ -static int snd_opl3_timer2_start(snd_timer_t * timer) +static int snd_opl3_timer2_start(struct snd_timer * timer) { unsigned long flags; unsigned char tmp; unsigned int ticks; - opl3_t *opl3; + struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); spin_lock_irqsave(&opl3->timer_lock, flags); @@ -232,11 +208,11 @@ static int snd_opl3_timer2_start(snd_timer_t * timer) return 0; } -static int snd_opl3_timer2_stop(snd_timer_t * timer) +static int snd_opl3_timer2_stop(struct snd_timer * timer) { unsigned long flags; unsigned char tmp; - opl3_t *opl3; + struct snd_opl3 *opl3; opl3 = snd_timer_chip(timer); spin_lock_irqsave(&opl3->timer_lock, flags); @@ -251,7 +227,7 @@ static int snd_opl3_timer2_stop(snd_timer_t * timer) */ -static struct _snd_timer_hardware snd_opl3_timer1 = +static struct snd_timer_hardware snd_opl3_timer1 = { .flags = SNDRV_TIMER_HW_STOP, .resolution = 80000, @@ -260,7 +236,7 @@ static struct _snd_timer_hardware snd_opl3_timer1 = .stop = snd_opl3_timer1_stop, }; -static struct _snd_timer_hardware snd_opl3_timer2 = +static struct snd_timer_hardware snd_opl3_timer2 = { .flags = SNDRV_TIMER_HW_STOP, .resolution = 320000, @@ -269,10 +245,10 @@ static struct _snd_timer_hardware snd_opl3_timer2 = .stop = snd_opl3_timer2_stop, }; -static int snd_opl3_timer1_init(opl3_t * opl3, int timer_no) +static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no) { - snd_timer_t *timer = NULL; - snd_timer_id_t tid; + struct snd_timer *timer = NULL; + struct snd_timer_id tid; int err; tid.dev_class = SNDRV_TIMER_CLASS_CARD; @@ -289,10 +265,10 @@ static int snd_opl3_timer1_init(opl3_t * opl3, int timer_no) return err; } -static int snd_opl3_timer2_init(opl3_t * opl3, int timer_no) +static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no) { - snd_timer_t *timer = NULL; - snd_timer_id_t tid; + struct snd_timer *timer = NULL; + struct snd_timer_id tid; int err; tid.dev_class = SNDRV_TIMER_CLASS_CARD; @@ -313,16 +289,16 @@ static int snd_opl3_timer2_init(opl3_t * opl3, int timer_no) */ -void snd_opl3_interrupt(snd_hwdep_t * hw) +void snd_opl3_interrupt(struct snd_hwdep * hw) { unsigned char status; - opl3_t *opl3; - snd_timer_t *timer; + struct snd_opl3 *opl3; + struct snd_timer *timer; if (hw == NULL) return; - opl3 = snd_magic_cast(opl3_t, hw->private_data, return); + opl3 = hw->private_data; status = inb(opl3->l_port); #if 0 snd_printk("AdLib IRQ status = 0x%x\n", status); @@ -340,75 +316,118 @@ void snd_opl3_interrupt(snd_hwdep_t * hw) } } +EXPORT_SYMBOL(snd_opl3_interrupt); + /* */ -static int snd_opl3_free(opl3_t *opl3) +static int snd_opl3_free(struct snd_opl3 *opl3) { - if (opl3->res_l_port) { - release_resource(opl3->res_l_port); - kfree_nocheck(opl3->res_l_port); - } - if (opl3->res_r_port) { - release_resource(opl3->res_r_port); - kfree_nocheck(opl3->res_r_port); - } - snd_magic_kfree(opl3); + snd_assert(opl3 != NULL, return -ENXIO); + if (opl3->private_free) + opl3->private_free(opl3); + release_and_free_resource(opl3->res_l_port); + release_and_free_resource(opl3->res_r_port); + kfree(opl3); return 0; } -static int snd_opl3_dev_free(snd_device_t *device) +static int snd_opl3_dev_free(struct snd_device *device) { - opl3_t *opl3 = snd_magic_cast(opl3_t, device->device_data, return -ENXIO); + struct snd_opl3 *opl3 = device->device_data; return snd_opl3_free(opl3); } -int snd_opl3_create(snd_card_t * card, - unsigned long l_port, - unsigned long r_port, - unsigned short hardware, - int integrated, - opl3_t ** ropl3) +int snd_opl3_new(struct snd_card *card, + unsigned short hardware, + struct snd_opl3 **ropl3) { - opl3_t *opl3; - int err; - static snd_device_ops_t ops = { + static struct snd_device_ops ops = { .dev_free = snd_opl3_dev_free, }; + struct snd_opl3 *opl3; + int err; *ropl3 = NULL; - - opl3 = snd_magic_kcalloc(opl3_t, 0, GFP_KERNEL); - if (opl3 == NULL) + opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL); + if (opl3 == NULL) { + snd_printk(KERN_ERR "opl3: cannot allocate\n"); return -ENOMEM; + } - if (integrated) - goto __step1; /* ports are already reserved */ + opl3->card = card; + opl3->hardware = hardware; + spin_lock_init(&opl3->reg_lock); + spin_lock_init(&opl3->timer_lock); + mutex_init(&opl3->access_mutex); - if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) { - snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port); + if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) { snd_opl3_free(opl3); - return -EBUSY; + return err; } - if (r_port != 0 && - (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) { - snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); - snd_opl3_free(opl3); - return -EBUSY; + + *ropl3 = opl3; + return 0; +} + +EXPORT_SYMBOL(snd_opl3_new); + +int snd_opl3_init(struct snd_opl3 *opl3) +{ + if (! opl3->command) { + printk(KERN_ERR "snd_opl3_init: command not defined!\n"); + return -EINVAL; } - __step1: + opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); + /* Melodic mode */ + opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); - opl3->card = card; - opl3->hardware = hardware; + switch (opl3->hardware & OPL3_HW_MASK) { + case OPL3_HW_OPL2: + opl3->max_voices = MAX_OPL2_VOICES; + break; + case OPL3_HW_OPL3: + case OPL3_HW_OPL4: + opl3->max_voices = MAX_OPL3_VOICES; + /* Enter OPL3 mode */ + opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE); + } + return 0; +} + +EXPORT_SYMBOL(snd_opl3_init); + +int snd_opl3_create(struct snd_card *card, + unsigned long l_port, + unsigned long r_port, + unsigned short hardware, + int integrated, + struct snd_opl3 ** ropl3) +{ + struct snd_opl3 *opl3; + int err; + + *ropl3 = NULL; + if ((err = snd_opl3_new(card, hardware, &opl3)) < 0) + return err; + if (! integrated) { + if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) { + snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port); + snd_device_free(card, opl3); + return -EBUSY; + } + if (r_port != 0 && + (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) { + snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); + snd_device_free(card, opl3); + return -EBUSY; + } + } opl3->l_port = l_port; opl3->r_port = r_port; - spin_lock_init(&opl3->reg_lock); - spin_lock_init(&opl3->timer_lock); - init_MUTEX(&opl3->access_mutex); - switch (opl3->hardware) { /* some hardware doesn't support timers */ case OPL3_HW_OPL3_SV: @@ -416,35 +435,12 @@ int snd_opl3_create(snd_card_t * card, case OPL3_HW_OPL3_FM801: opl3->command = &snd_opl3_command; break; - case OPL3_HW_OPL3_PC98: - opl3->command = &snd_opl3_command; - - /* Initialize? */ - opl3->command(opl3, OPL3_RIGHT | 0x05, 0x05); - opl3->command(opl3, OPL3_RIGHT | 0x08, 0x04); - opl3->command(opl3, OPL3_RIGHT | 0x08, 0x00); - opl3->command(opl3, OPL3_LEFT | 0xf7, 0x00); - opl3->command(opl3, OPL3_LEFT | 0x04, 0x60); - opl3->command(opl3, OPL3_LEFT | 0x04, 0x80); - inb(opl3->l_port); - - opl3->command(opl3, OPL3_LEFT | 0x02, 0xff); - opl3->command(opl3, OPL3_LEFT | 0x04, 0x21); - inb(opl3->l_port); - - opl3->command(opl3, OPL3_LEFT | 0x04, 0x60); - opl3->command(opl3, OPL3_LEFT | 0x04, 0x80); - - break; - case OPL3_HW_OPL3_CS4281: - opl3->command = &snd_opl3_cs4281_command; - break; default: opl3->command = &snd_opl2_command; if ((err = snd_opl3_detect(opl3)) < 0) { snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n", opl3->l_port, opl3->r_port); - snd_opl3_free(opl3); + snd_device_free(card, opl3); return err; } /* detect routine returns correct hardware type */ @@ -455,29 +451,15 @@ int snd_opl3_create(snd_card_t * card, } } - opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); - opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */ - - switch (opl3->hardware & OPL3_HW_MASK) { - case OPL3_HW_OPL2: - opl3->max_voices = MAX_OPL2_VOICES; - break; - case OPL3_HW_OPL3: - case OPL3_HW_OPL4: - opl3->max_voices = MAX_OPL3_VOICES; - snd_assert(opl3->r_port != 0, snd_opl3_free(opl3); return -ENODEV); - opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE); /* Enter OPL3 mode */ - } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl3, &ops)) < 0) { - snd_opl3_free(opl3); - return err; - } + snd_opl3_init(opl3); *ropl3 = opl3; return 0; } -int snd_opl3_timer_new(opl3_t * opl3, int timer1_dev, int timer2_dev) +EXPORT_SYMBOL(snd_opl3_create); + +int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) { int err; @@ -494,12 +476,14 @@ int snd_opl3_timer_new(opl3_t * opl3, int timer1_dev, int timer2_dev) return 0; } -int snd_opl3_hwdep_new(opl3_t * opl3, +EXPORT_SYMBOL(snd_opl3_timer_new); + +int snd_opl3_hwdep_new(struct snd_opl3 * opl3, int device, int seq_device, - snd_hwdep_t ** rhwdep) + struct snd_hwdep ** rhwdep) { - snd_hwdep_t *hw; - snd_card_t *card = opl3->card; + struct snd_hwdep *hw; + struct snd_card *card = opl3->card; int err; if (rhwdep) @@ -542,9 +526,9 @@ int snd_opl3_hwdep_new(opl3_t * opl3, opl3->seq_dev_num = seq_device; #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3, - sizeof(opl3_t*), &opl3->seq_dev) >= 0) { + sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) { strcpy(opl3->seq_dev->name, hw->name); - *(opl3_t**)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3; + *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3; } #endif if (rhwdep) @@ -552,15 +536,8 @@ int snd_opl3_hwdep_new(opl3_t * opl3, return 0; } -EXPORT_SYMBOL(snd_opl3_interrupt); -EXPORT_SYMBOL(snd_opl3_create); -EXPORT_SYMBOL(snd_opl3_timer_new); EXPORT_SYMBOL(snd_opl3_hwdep_new); -/* opl3_synth.c */ -EXPORT_SYMBOL(snd_opl3_regmap); -EXPORT_SYMBOL(snd_opl3_reset); - /* * INIT part */