Merge branch 'topic/memdup_user' into for-linus
[linux-2.6.git] / sound / isa / wavefront / wavefront_fx.c
index 2e03dc5..2bb1cee 100644 (file)
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <sound/driver.h>
 #include <asm/io.h>
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/wait.h>
+#include <linux/firmware.h>
 #include <sound/core.h>
 #include <sound/snd_wavefront.h>
 #include <sound/initval.h>
@@ -34,8 +34,6 @@
 
 #define WAIT_IDLE      0xff
 
-#include "yss225.c"
-
 static int
 wavefront_fx_idle (snd_wavefront_t *dev)
 
@@ -174,11 +172,11 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
        unsigned short *pd;
        int err = 0;
 
-       snd_assert(sdev->card != NULL, return -ENODEV);
-       
        card = sdev->card;
-
-       snd_assert(card->private_data != NULL, return -ENODEV);
+       if (snd_BUG_ON(!card))
+               return -ENODEV;
+       if (snd_BUG_ON(!card->private_data))
+               return -ENODEV;
 
        acard = card->private_data;
        dev = &acard->wavefront;
@@ -204,15 +202,11 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
                                            "> 512 bytes to FX\n");
                                return -EIO;
                        }
-                       page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
-                       if (!page_data)
-                               return -ENOMEM;
-                       if (copy_from_user (page_data,
-                                           (unsigned char __user *) r.data[3],
-                                           r.data[2] * sizeof(short))) {
-                               kfree(page_data);
-                               return -EFAULT;
-                       }
+                       page_data = memdup_user((unsigned char __user *)
+                                               r.data[3],
+                                               r.data[2] * sizeof(short));
+                       if (IS_ERR(page_data))
+                               return PTR_ERR(page_data);
                        pd = page_data;
                }
 
@@ -248,25 +242,42 @@ int __devinit
 snd_wavefront_fx_start (snd_wavefront_t *dev)
 {
        unsigned int i;
+       int err;
+       const struct firmware *firmware = NULL;
 
        if (dev->fx_initialized)
                return 0;
 
-       for (i = 0; i < ARRAY_SIZE(yss225_registers); ++i) {
-               if (yss225_registers[i].addr >= 8 &&
-                   yss225_registers[i].addr < 16) {
-                       outb(yss225_registers[i].data,
-                            yss225_registers[i].addr + dev->base);
-               } else if (yss225_registers[i].addr == WAIT_IDLE) {
-                       if (!wavefront_fx_idle(dev))
-                               return -1;
+       err = request_firmware(&firmware, "yamaha/yss225_registers.bin",
+                              dev->card->dev);
+       if (err < 0) {
+               err = -1;
+               goto out;
+       }
+
+       for (i = 0; i + 1 < firmware->size; i += 2) {
+               if (firmware->data[i] >= 8 && firmware->data[i] < 16) {
+                       outb(firmware->data[i + 1],
+                            dev->base + firmware->data[i]);
+               } else if (firmware->data[i] == WAIT_IDLE) {
+                       if (!wavefront_fx_idle(dev)) {
+                               err = -1;
+                               goto out;
+                       }
                } else {
                        snd_printk(KERN_ERR "invalid address"
                                   " in register data\n");
-                       return -1;
+                       err = -1;
+                       goto out;
                }
        }
 
        dev->fx_initialized = 1;
-       return (0);
+       err = 0;
+
+out:
+       release_firmware(firmware);
+       return err;
 }
+
+MODULE_FIRMWARE("yamaha/yss225_registers.bin");