]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - sound/drivers/opl3/opl3_oss.c
ALSA: snd-powermac: enable mic on iMac G4
[linux-2.6-omap-h63xx.git] / sound / drivers / opl3 / opl3_oss.c
index fccf019a6d85968a5ff8f26953d0f9dba655d654..9a2271dc046a653e7f80077108bd6c19b2c3e6a7 100644 (file)
@@ -100,7 +100,8 @@ static int snd_opl3_oss_create_port(struct snd_opl3 * opl3)
                                                          SNDRV_SEQ_PORT_CAP_WRITE,
                                                          SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
                                                          SNDRV_SEQ_PORT_TYPE_MIDI_GM |
-                                                         SNDRV_SEQ_PORT_TYPE_SYNTH,
+                                                         SNDRV_SEQ_PORT_TYPE_HARDWARE |
+                                                         SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
                                                          voices, voices,
                                                          name);
        if (opl3->oss_chset->port < 0) {
@@ -161,7 +162,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        struct snd_opl3 *opl3 = closure;
        int err;
 
-       snd_assert(arg != NULL, return -ENXIO);
+       if (snd_BUG_ON(!arg))
+               return -ENXIO;
 
        if ((err = snd_opl3_synth_setup(opl3)) < 0)
                return err;
@@ -183,7 +185,8 @@ static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg)
 {
        struct snd_opl3 *opl3;
 
-       snd_assert(arg != NULL, return -ENXIO);
+       if (snd_BUG_ON(!arg))
+               return -ENXIO;
        opl3 = arg->private_data;
 
        snd_opl3_synth_cleanup(opl3);
@@ -194,17 +197,6 @@ static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg)
 
 /* load patch */
 
-/* offsets for SBI params */
-#define AM_VIB         0
-#define KSL_LEVEL      2
-#define ATTACK_DECAY   4
-#define SUSTAIN_RELEASE        6
-#define WAVE_SELECT    8
-
-/* offset for SBI instrument */
-#define CONNECTION     10
-#define OFFSET_4OP     11
-
 /* from sound_config.h */
 #define SBFM_MAXINSTR  256
 
@@ -212,112 +204,43 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
                                       const char __user *buf, int offs, int count)
 {
        struct snd_opl3 *opl3;
-       int err = -EINVAL;
+       struct sbi_instrument sbi;
+       char name[32];
+       int err, type;
 
-       snd_assert(arg != NULL, return -ENXIO);
+       if (snd_BUG_ON(!arg))
+               return -ENXIO;
        opl3 = arg->private_data;
 
-       if ((format == FM_PATCH) || (format == OPL3_PATCH)) {
-               struct sbi_instrument sbi;
+       if (format == FM_PATCH)
+               type = FM_PATCH_OPL2;
+       else if (format == OPL3_PATCH)
+               type = FM_PATCH_OPL3;
+       else
+               return -EINVAL;
 
-               size_t size;
-               struct snd_seq_instr_header *put;
-               struct snd_seq_instr_data *data;
-               struct fm_xinstrument *xinstr;
+       if (count < (int)sizeof(sbi)) {
+               snd_printk("FM Error: Patch record too short\n");
+               return -EINVAL;
+       }
+       if (copy_from_user(&sbi, buf, sizeof(sbi)))
+               return -EFAULT;
 
-               struct snd_seq_event ev;
-               int i;
+       if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) {
+               snd_printk("FM Error: Invalid instrument number %d\n",
+                          sbi.channel);
+               return -EINVAL;
+       }
 
-               mm_segment_t fs;
+       memset(name, 0, sizeof(name));
+       sprintf(name, "Chan%d", sbi.channel);
 
-               if (count < (int)sizeof(sbi)) {
-                       snd_printk("FM Error: Patch record too short\n");
-                       return -EINVAL;
-               }
-               if (copy_from_user(&sbi, buf, sizeof(sbi)))
-                       return -EFAULT;
+       err = snd_opl3_load_patch(opl3, sbi.channel, 127, type, name, NULL,
+                                 sbi.operators);
+       if (err < 0)
+               return err;
 
-               if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) {
-                       snd_printk("FM Error: Invalid instrument number %d\n", sbi.channel);
-                       return -EINVAL;
-               }
-
-               size = sizeof(*put) + sizeof(struct fm_xinstrument);
-               put = kzalloc(size, GFP_KERNEL);
-               if (put == NULL)
-                       return -ENOMEM;
-               /* build header */
-               data = &put->data;
-               data->type = SNDRV_SEQ_INSTR_ATYPE_DATA;
-               strcpy(data->data.format, SNDRV_SEQ_INSTR_ID_OPL2_3);
-               /* build data section */
-               xinstr = (struct fm_xinstrument *)(data + 1);
-               xinstr->stype = FM_STRU_INSTR;
-        
-               for (i = 0; i < 2; i++) {
-                       xinstr->op[i].am_vib = sbi.operators[AM_VIB + i];
-                       xinstr->op[i].ksl_level = sbi.operators[KSL_LEVEL + i];
-                       xinstr->op[i].attack_decay = sbi.operators[ATTACK_DECAY + i];
-                       xinstr->op[i].sustain_release = sbi.operators[SUSTAIN_RELEASE + i];
-                       xinstr->op[i].wave_select = sbi.operators[WAVE_SELECT + i];
-               }
-               xinstr->feedback_connection[0] = sbi.operators[CONNECTION];
-
-               if (format == OPL3_PATCH) {
-                       xinstr->type = FM_PATCH_OPL3;
-                       for (i = 0; i < 2; i++) {
-                               xinstr->op[i+2].am_vib = sbi.operators[OFFSET_4OP + AM_VIB + i];
-                               xinstr->op[i+2].ksl_level = sbi.operators[OFFSET_4OP + KSL_LEVEL + i];
-                               xinstr->op[i+2].attack_decay = sbi.operators[OFFSET_4OP + ATTACK_DECAY + i];
-                               xinstr->op[i+2].sustain_release = sbi.operators[OFFSET_4OP + SUSTAIN_RELEASE + i];
-                               xinstr->op[i+2].wave_select = sbi.operators[OFFSET_4OP + WAVE_SELECT + i];
-                       }
-                       xinstr->feedback_connection[1] = sbi.operators[OFFSET_4OP + CONNECTION];
-               } else {
-                       xinstr->type = FM_PATCH_OPL2;
-               }
-
-               put->id.instr.std = SNDRV_SEQ_INSTR_TYPE2_OPL2_3;
-               put->id.instr.bank = 127;
-               put->id.instr.prg = sbi.channel;
-               put->cmd = SNDRV_SEQ_INSTR_PUT_CMD_CREATE;
-
-               memset (&ev, 0, sizeof(ev));
-               ev.source.client = SNDRV_SEQ_CLIENT_OSS;
-               ev.dest = arg->addr; 
-
-               ev.flags = SNDRV_SEQ_EVENT_LENGTH_VARUSR;
-               ev.queue = SNDRV_SEQ_QUEUE_DIRECT;
-
-               fs = snd_enter_user();
-       __again:
-               ev.type = SNDRV_SEQ_EVENT_INSTR_PUT;
-               ev.data.ext.len = size;
-               ev.data.ext.ptr = put;
-
-               err = snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, &ev,
-                                   opl3->seq_client, 0, 0);
-               if (err == -EBUSY) {
-                       struct snd_seq_instr_header remove;
-
-                       memset (&remove, 0, sizeof(remove));
-                       remove.cmd = SNDRV_SEQ_INSTR_FREE_CMD_SINGLE;
-                       remove.id.instr = put->id.instr;
-
-                       /* remove instrument */
-                       ev.type = SNDRV_SEQ_EVENT_INSTR_FREE;
-                       ev.data.ext.len = sizeof(remove);
-                       ev.data.ext.ptr = &remove;
-
-                       snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, &ev,
-                                           opl3->seq_client, 0, 0);
-                       goto __again;
-               }
-               snd_leave_user(fs);
-
-               kfree(put);
-       }
-       return err;
+       return sizeof(sbi);
 }
 
 /* ioctl */
@@ -326,7 +249,8 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd,
 {
        struct snd_opl3 *opl3;
 
-       snd_assert(arg != NULL, return -ENXIO);
+       if (snd_BUG_ON(!arg))
+               return -ENXIO;
        opl3 = arg->private_data;
        switch (cmd) {
                case SNDCTL_FM_LOAD_INSTR:
@@ -351,7 +275,8 @@ static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg)
 {
        struct snd_opl3 *opl3;
 
-       snd_assert(arg != NULL, return -ENXIO);
+       if (snd_BUG_ON(!arg))
+               return -ENXIO;
        opl3 = arg->private_data;
 
        return 0;