vserver 1.9.5.x5
[linux-2.6.git] / sound / drivers / opl3 / opl3_lib.c
index e2315af..c313e52 100644 (file)
@@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
 
 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;
@@ -60,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(opl3_t * opl3, unsigned short cmd, unsigned char val)
 {
        unsigned long flags;
        unsigned long port;
@@ -85,28 +85,6 @@ 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)
 {
        /*
@@ -344,6 +322,9 @@ void snd_opl3_interrupt(snd_hwdep_t * hw)
 
 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);
@@ -362,51 +343,89 @@ static int snd_opl3_dev_free(snd_device_t *device)
        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:
@@ -414,9 +433,6 @@ int snd_opl3_create(snd_card_t * card,
        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) {
@@ -433,23 +449,7 @@ 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;
@@ -531,6 +531,8 @@ int snd_opl3_hwdep_new(opl3_t * opl3,
 }
 
 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);