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(opl3_t * opl3, unsigned short cmd, unsigned char val)
{
unsigned long flags;
unsigned long port;
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(opl3_t * opl3, unsigned short cmd, unsigned char val)
{
unsigned long flags;
unsigned long port;
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_free(opl3_t *opl3)
{
+ snd_assert(opl3 != NULL, return -ENXIO);
+ if (opl3->private_free)
+ opl3->private_free(opl3);
if (opl3->res_l_port) {
release_resource(opl3->res_l_port);
kfree_nocheck(opl3->res_l_port);
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(snd_card_t *card,
+ unsigned short hardware,
+ opl3_t **ropl3)
{
- opl3_t *opl3;
- int err;
static snd_device_ops_t ops = {
.dev_free = snd_opl3_dev_free,
};
+ opl3_t *opl3;
+ int err;
*ropl3 = NULL;
-
opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
if (opl3 == NULL)
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);
+ init_MUTEX(&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;
+}
+
+int snd_opl3_init(opl3_t *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;
+}
+
+int snd_opl3_create(snd_card_t * card,
+ unsigned long l_port,
+ unsigned long r_port,
+ unsigned short hardware,
+ int integrated,
+ opl3_t ** ropl3)
+{
+ opl3_t *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_opl3_free(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_opl3_free(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:
case OPL3_HW_OPL3_FM801:
opl3->command = &snd_opl3_command;
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) {
}
}
- 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;
}
EXPORT_SYMBOL(snd_opl3_interrupt);
+EXPORT_SYMBOL(snd_opl3_new);
+EXPORT_SYMBOL(snd_opl3_init);
EXPORT_SYMBOL(snd_opl3_create);
EXPORT_SYMBOL(snd_opl3_timer_new);
EXPORT_SYMBOL(snd_opl3_hwdep_new);