Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) by Uros Bizjak <uros@kss-loka.si>
0004  *                   
0005  *  Routines for OPL2/OPL3/OPL4 control
0006  */
0007 
0008 #include <linux/slab.h>
0009 #include <linux/export.h>
0010 #include <linux/nospec.h>
0011 #include <sound/opl3.h>
0012 #include <sound/asound_fm.h>
0013 #include "opl3_voice.h"
0014 
0015 #if IS_ENABLED(CONFIG_SND_SEQUENCER)
0016 #define OPL3_SUPPORT_SYNTH
0017 #endif
0018 
0019 /*
0020  *    There is 18 possible 2 OP voices
0021  *      (9 in the left and 9 in the right).
0022  *      The first OP is the modulator and 2nd is the carrier.
0023  *
0024  *      The first three voices in the both sides may be connected
0025  *      with another voice to a 4 OP voice. For example voice 0
0026  *      can be connected with voice 3. The operators of voice 3 are
0027  *      used as operators 3 and 4 of the new 4 OP voice.
0028  *      In this case the 2 OP voice number 0 is the 'first half' and
0029  *      voice 3 is the second.
0030  */
0031 
0032 
0033 /*
0034  *    Register offset table for OPL2/3 voices,
0035  *    OPL2 / one OPL3 register array side only
0036  */
0037 
0038 char snd_opl3_regmap[MAX_OPL2_VOICES][4] =
0039 {
0040 /*    OP1   OP2   OP3   OP4     */
0041 /*   ------------------------   */
0042     { 0x00, 0x03, 0x08, 0x0b },
0043     { 0x01, 0x04, 0x09, 0x0c },
0044     { 0x02, 0x05, 0x0a, 0x0d },
0045 
0046     { 0x08, 0x0b, 0x00, 0x00 },
0047     { 0x09, 0x0c, 0x00, 0x00 },
0048     { 0x0a, 0x0d, 0x00, 0x00 },
0049 
0050     { 0x10, 0x13, 0x00, 0x00 }, /* used by percussive voices */
0051     { 0x11, 0x14, 0x00, 0x00 }, /* if the percussive mode */
0052     { 0x12, 0x15, 0x00, 0x00 }  /* is selected (only left reg block) */
0053 };
0054 
0055 EXPORT_SYMBOL(snd_opl3_regmap);
0056 
0057 /*
0058  * prototypes
0059  */
0060 static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note);
0061 static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice);
0062 static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params);
0063 static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode);
0064 static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection);
0065 
0066 /* ------------------------------ */
0067 
0068 /*
0069  * open the device exclusively
0070  */
0071 int snd_opl3_open(struct snd_hwdep * hw, struct file *file)
0072 {
0073     return 0;
0074 }
0075 
0076 /*
0077  * ioctl for hwdep device:
0078  */
0079 int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
0080            unsigned int cmd, unsigned long arg)
0081 {
0082     struct snd_opl3 *opl3 = hw->private_data;
0083     void __user *argp = (void __user *)arg;
0084 
0085     if (snd_BUG_ON(!opl3))
0086         return -EINVAL;
0087 
0088     switch (cmd) {
0089         /* get information */
0090     case SNDRV_DM_FM_IOCTL_INFO:
0091         {
0092             struct snd_dm_fm_info info;
0093 
0094             memset(&info, 0, sizeof(info));
0095 
0096             info.fm_mode = opl3->fm_mode;
0097             info.rhythm = opl3->rhythm;
0098             if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info)))
0099                 return -EFAULT;
0100             return 0;
0101         }
0102 
0103     case SNDRV_DM_FM_IOCTL_RESET:
0104 #ifdef CONFIG_SND_OSSEMUL
0105     case SNDRV_DM_FM_OSS_IOCTL_RESET:
0106 #endif
0107         snd_opl3_reset(opl3);
0108         return 0;
0109 
0110     case SNDRV_DM_FM_IOCTL_PLAY_NOTE:
0111 #ifdef CONFIG_SND_OSSEMUL
0112     case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE:
0113 #endif
0114         {
0115             struct snd_dm_fm_note note;
0116             if (copy_from_user(&note, argp, sizeof(struct snd_dm_fm_note)))
0117                 return -EFAULT;
0118             return snd_opl3_play_note(opl3, &note);
0119         }
0120 
0121     case SNDRV_DM_FM_IOCTL_SET_VOICE:
0122 #ifdef CONFIG_SND_OSSEMUL
0123     case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE:
0124 #endif
0125         {
0126             struct snd_dm_fm_voice voice;
0127             if (copy_from_user(&voice, argp, sizeof(struct snd_dm_fm_voice)))
0128                 return -EFAULT;
0129             return snd_opl3_set_voice(opl3, &voice);
0130         }
0131 
0132     case SNDRV_DM_FM_IOCTL_SET_PARAMS:
0133 #ifdef CONFIG_SND_OSSEMUL
0134     case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS:
0135 #endif
0136         {
0137             struct snd_dm_fm_params params;
0138             if (copy_from_user(&params, argp, sizeof(struct snd_dm_fm_params)))
0139                 return -EFAULT;
0140             return snd_opl3_set_params(opl3, &params);
0141         }
0142 
0143     case SNDRV_DM_FM_IOCTL_SET_MODE:
0144 #ifdef CONFIG_SND_OSSEMUL
0145     case SNDRV_DM_FM_OSS_IOCTL_SET_MODE:
0146 #endif
0147         return snd_opl3_set_mode(opl3, (int) arg);
0148 
0149     case SNDRV_DM_FM_IOCTL_SET_CONNECTION:
0150 #ifdef CONFIG_SND_OSSEMUL
0151     case SNDRV_DM_FM_OSS_IOCTL_SET_OPL:
0152 #endif
0153         return snd_opl3_set_connection(opl3, (int) arg);
0154 
0155 #ifdef OPL3_SUPPORT_SYNTH
0156     case SNDRV_DM_FM_IOCTL_CLEAR_PATCHES:
0157         snd_opl3_clear_patches(opl3);
0158         return 0;
0159 #endif
0160 
0161 #ifdef CONFIG_SND_DEBUG
0162     default:
0163         snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd);
0164 #endif
0165     }
0166     return -ENOTTY;
0167 }
0168 
0169 /*
0170  * close the device
0171  */
0172 int snd_opl3_release(struct snd_hwdep * hw, struct file *file)
0173 {
0174     struct snd_opl3 *opl3 = hw->private_data;
0175 
0176     snd_opl3_reset(opl3);
0177     return 0;
0178 }
0179 
0180 #ifdef OPL3_SUPPORT_SYNTH
0181 /*
0182  * write the device - load patches
0183  */
0184 long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count,
0185             loff_t *offset)
0186 {
0187     struct snd_opl3 *opl3 = hw->private_data;
0188     long result = 0;
0189     int err = 0;
0190     struct sbi_patch inst;
0191 
0192     while (count >= sizeof(inst)) {
0193         unsigned char type;
0194         if (copy_from_user(&inst, buf, sizeof(inst)))
0195             return -EFAULT;
0196         if (!memcmp(inst.key, FM_KEY_SBI, 4) ||
0197             !memcmp(inst.key, FM_KEY_2OP, 4))
0198             type = FM_PATCH_OPL2;
0199         else if (!memcmp(inst.key, FM_KEY_4OP, 4))
0200             type = FM_PATCH_OPL3;
0201         else /* invalid type */
0202             break;
0203         err = snd_opl3_load_patch(opl3, inst.prog, inst.bank, type,
0204                       inst.name, inst.extension,
0205                       inst.data);
0206         if (err < 0)
0207             break;
0208         result += sizeof(inst);
0209         count -= sizeof(inst);
0210     }
0211     return result > 0 ? result : err;
0212 }
0213 
0214 
0215 /*
0216  * Patch management
0217  */
0218 
0219 /* offsets for SBI params */
0220 #define AM_VIB      0
0221 #define KSL_LEVEL   2
0222 #define ATTACK_DECAY    4
0223 #define SUSTAIN_RELEASE 6
0224 #define WAVE_SELECT 8
0225 
0226 /* offset for SBI instrument */
0227 #define CONNECTION  10
0228 #define OFFSET_4OP  11
0229 
0230 /*
0231  * load a patch, obviously.
0232  *
0233  * loaded on the given program and bank numbers with the given type
0234  * (FM_PATCH_OPLx).
0235  * data is the pointer of SBI record _without_ header (key and name).
0236  * name is the name string of the patch.
0237  * ext is the extension data of 7 bytes long (stored in name of SBI
0238  * data up to offset 25), or NULL to skip.
0239  * return 0 if successful or a negative error code.
0240  */
0241 int snd_opl3_load_patch(struct snd_opl3 *opl3,
0242             int prog, int bank, int type,
0243             const char *name,
0244             const unsigned char *ext,
0245             const unsigned char *data)
0246 {
0247     struct fm_patch *patch;
0248     int i;
0249 
0250     patch = snd_opl3_find_patch(opl3, prog, bank, 1);
0251     if (!patch)
0252         return -ENOMEM;
0253 
0254     patch->type = type;
0255 
0256     for (i = 0; i < 2; i++) {
0257         patch->inst.op[i].am_vib = data[AM_VIB + i];
0258         patch->inst.op[i].ksl_level = data[KSL_LEVEL + i];
0259         patch->inst.op[i].attack_decay = data[ATTACK_DECAY + i];
0260         patch->inst.op[i].sustain_release = data[SUSTAIN_RELEASE + i];
0261         patch->inst.op[i].wave_select = data[WAVE_SELECT + i];
0262     }
0263     patch->inst.feedback_connection[0] = data[CONNECTION];
0264 
0265     if (type == FM_PATCH_OPL3) {
0266         for (i = 0; i < 2; i++) {
0267             patch->inst.op[i+2].am_vib =
0268                 data[OFFSET_4OP + AM_VIB + i];
0269             patch->inst.op[i+2].ksl_level =
0270                 data[OFFSET_4OP + KSL_LEVEL + i];
0271             patch->inst.op[i+2].attack_decay =
0272                 data[OFFSET_4OP + ATTACK_DECAY + i];
0273             patch->inst.op[i+2].sustain_release =
0274                 data[OFFSET_4OP + SUSTAIN_RELEASE + i];
0275             patch->inst.op[i+2].wave_select =
0276                 data[OFFSET_4OP + WAVE_SELECT + i];
0277         }
0278         patch->inst.feedback_connection[1] =
0279             data[OFFSET_4OP + CONNECTION];
0280     }
0281 
0282     if (ext) {
0283         patch->inst.echo_delay = ext[0];
0284         patch->inst.echo_atten = ext[1];
0285         patch->inst.chorus_spread = ext[2];
0286         patch->inst.trnsps = ext[3];
0287         patch->inst.fix_dur = ext[4];
0288         patch->inst.modes = ext[5];
0289         patch->inst.fix_key = ext[6];
0290     }
0291 
0292     if (name)
0293         strscpy(patch->name, name, sizeof(patch->name));
0294 
0295     return 0;
0296 }
0297 EXPORT_SYMBOL(snd_opl3_load_patch);
0298 
0299 /*
0300  * find a patch with the given program and bank numbers, returns its pointer
0301  * if no matching patch is found and create_patch is set, it creates a
0302  * new patch object.
0303  */
0304 struct fm_patch *snd_opl3_find_patch(struct snd_opl3 *opl3, int prog, int bank,
0305                      int create_patch)
0306 {
0307     /* pretty dumb hash key */
0308     unsigned int key = (prog + bank) % OPL3_PATCH_HASH_SIZE;
0309     struct fm_patch *patch;
0310 
0311     for (patch = opl3->patch_table[key]; patch; patch = patch->next) {
0312         if (patch->prog == prog && patch->bank == bank)
0313             return patch;
0314     }
0315     if (!create_patch)
0316         return NULL;
0317 
0318     patch = kzalloc(sizeof(*patch), GFP_KERNEL);
0319     if (!patch)
0320         return NULL;
0321     patch->prog = prog;
0322     patch->bank = bank;
0323     patch->next = opl3->patch_table[key];
0324     opl3->patch_table[key] = patch;
0325     return patch;
0326 }
0327 EXPORT_SYMBOL(snd_opl3_find_patch);
0328 
0329 /*
0330  * Clear all patches of the given OPL3 instance
0331  */
0332 void snd_opl3_clear_patches(struct snd_opl3 *opl3)
0333 {
0334     int i;
0335     for (i = 0; i <  OPL3_PATCH_HASH_SIZE; i++) {
0336         struct fm_patch *patch, *next;
0337         for (patch = opl3->patch_table[i]; patch; patch = next) {
0338             next = patch->next;
0339             kfree(patch);
0340         }
0341     }
0342     memset(opl3->patch_table, 0, sizeof(opl3->patch_table));
0343 }
0344 #endif /* OPL3_SUPPORT_SYNTH */
0345 
0346 /* ------------------------------ */
0347 
0348 void snd_opl3_reset(struct snd_opl3 * opl3)
0349 {
0350     unsigned short opl3_reg;
0351 
0352     unsigned short reg_side;
0353     unsigned char voice_offset;
0354 
0355     int max_voices, i;
0356 
0357     max_voices = (opl3->hardware < OPL3_HW_OPL3) ?
0358         MAX_OPL2_VOICES : MAX_OPL3_VOICES;
0359 
0360     for (i = 0; i < max_voices; i++) {
0361         /* Get register array side and offset of voice */
0362         if (i < MAX_OPL2_VOICES) {
0363             /* Left register block for voices 0 .. 8 */
0364             reg_side = OPL3_LEFT;
0365             voice_offset = i;
0366         } else {
0367             /* Right register block for voices 9 .. 17 */
0368             reg_side = OPL3_RIGHT;
0369             voice_offset = i - MAX_OPL2_VOICES;
0370         }
0371         opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][0]);
0372         opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 1 volume */
0373         opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][1]);
0374         opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 2 volume */
0375 
0376         opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0377         opl3->command(opl3, opl3_reg, 0x00);    /* Note off */
0378     }
0379 
0380     opl3->max_voices = MAX_OPL2_VOICES;
0381     opl3->fm_mode = SNDRV_DM_FM_MODE_OPL2;
0382 
0383     opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
0384     opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */
0385     opl3->rhythm = 0;
0386 }
0387 
0388 EXPORT_SYMBOL(snd_opl3_reset);
0389 
0390 static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note)
0391 {
0392     unsigned short reg_side;
0393     unsigned char voice_offset;
0394 
0395     unsigned short opl3_reg;
0396     unsigned char reg_val;
0397 
0398     /* Voices 0 -  8 in OPL2 mode */
0399     /* Voices 0 - 17 in OPL3 mode */
0400     if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
0401                 MAX_OPL3_VOICES : MAX_OPL2_VOICES))
0402         return -EINVAL;
0403 
0404     /* Get register array side and offset of voice */
0405     if (note->voice < MAX_OPL2_VOICES) {
0406         /* Left register block for voices 0 .. 8 */
0407         reg_side = OPL3_LEFT;
0408         voice_offset = note->voice;
0409     } else {
0410         /* Right register block for voices 9 .. 17 */
0411         reg_side = OPL3_RIGHT;
0412         voice_offset = note->voice - MAX_OPL2_VOICES;
0413     }
0414 
0415     /* Set lower 8 bits of note frequency */
0416     reg_val = (unsigned char) note->fnum;
0417     opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
0418     opl3->command(opl3, opl3_reg, reg_val);
0419     
0420     reg_val = 0x00;
0421     /* Set output sound flag */
0422     if (note->key_on)
0423         reg_val |= OPL3_KEYON_BIT;
0424     /* Set octave */
0425     reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK;
0426     /* Set higher 2 bits of note frequency */
0427     reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK;
0428 
0429     /* Set OPL3 KEYON_BLOCK register of requested voice */ 
0430     opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0431     opl3->command(opl3, opl3_reg, reg_val);
0432 
0433     return 0;
0434 }
0435 
0436 
0437 static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice)
0438 {
0439     unsigned short reg_side;
0440     unsigned char op_offset;
0441     unsigned char voice_offset, voice_op;
0442 
0443     unsigned short opl3_reg;
0444     unsigned char reg_val;
0445 
0446     /* Only operators 1 and 2 */
0447     if (voice->op > 1)
0448         return -EINVAL;
0449     /* Voices 0 -  8 in OPL2 mode */
0450     /* Voices 0 - 17 in OPL3 mode */
0451     if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
0452                  MAX_OPL3_VOICES : MAX_OPL2_VOICES))
0453         return -EINVAL;
0454 
0455     /* Get register array side and offset of voice */
0456     if (voice->voice < MAX_OPL2_VOICES) {
0457         /* Left register block for voices 0 .. 8 */
0458         reg_side = OPL3_LEFT;
0459         voice_offset = voice->voice;
0460     } else {
0461         /* Right register block for voices 9 .. 17 */
0462         reg_side = OPL3_RIGHT;
0463         voice_offset = voice->voice - MAX_OPL2_VOICES;
0464     }
0465     /* Get register offset of operator */
0466     voice_offset = array_index_nospec(voice_offset, MAX_OPL2_VOICES);
0467     voice_op = array_index_nospec(voice->op, 4);
0468     op_offset = snd_opl3_regmap[voice_offset][voice_op];
0469 
0470     reg_val = 0x00;
0471     /* Set amplitude modulation (tremolo) effect */
0472     if (voice->am)
0473         reg_val |= OPL3_TREMOLO_ON;
0474     /* Set vibrato effect */
0475     if (voice->vibrato)
0476         reg_val |= OPL3_VIBRATO_ON;
0477     /* Set sustaining sound phase */
0478     if (voice->do_sustain)
0479         reg_val |= OPL3_SUSTAIN_ON;
0480     /* Set keyboard scaling bit */ 
0481     if (voice->kbd_scale)
0482         reg_val |= OPL3_KSR;
0483     /* Set harmonic or frequency multiplier */
0484     reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK;
0485 
0486     /* Set OPL3 AM_VIB register of requested voice/operator */ 
0487     opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset);
0488     opl3->command(opl3, opl3_reg, reg_val);
0489 
0490     /* Set decreasing volume of higher notes */
0491     reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK;
0492     /* Set output volume */
0493     reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK;
0494 
0495     /* Set OPL3 KSL_LEVEL register of requested voice/operator */ 
0496     opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset);
0497     opl3->command(opl3, opl3_reg, reg_val);
0498 
0499     /* Set attack phase level */
0500     reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK;
0501     /* Set decay phase level */
0502     reg_val |= voice->decay & OPL3_DECAY_MASK;
0503 
0504     /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ 
0505     opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset);
0506     opl3->command(opl3, opl3_reg, reg_val);
0507 
0508     /* Set sustain phase level */
0509     reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK;
0510     /* Set release phase level */
0511     reg_val |= voice->release & OPL3_RELEASE_MASK;
0512 
0513     /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ 
0514     opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
0515     opl3->command(opl3, opl3_reg, reg_val);
0516 
0517     /* Set inter-operator feedback */
0518     reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK;
0519     /* Set inter-operator connection */
0520     if (voice->connection)
0521         reg_val |= OPL3_CONNECTION_BIT;
0522     /* OPL-3 only */
0523     if (opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) {
0524         if (voice->left)
0525             reg_val |= OPL3_VOICE_TO_LEFT;
0526         if (voice->right)
0527             reg_val |= OPL3_VOICE_TO_RIGHT;
0528     }
0529     /* Feedback/connection bits are applicable to voice */
0530     opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
0531     opl3->command(opl3, opl3_reg, reg_val);
0532 
0533     /* Select waveform */
0534     reg_val = voice->waveform & OPL3_WAVE_SELECT_MASK;
0535     opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset);
0536     opl3->command(opl3, opl3_reg, reg_val);
0537 
0538     return 0;
0539 }
0540 
0541 static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params)
0542 {
0543     unsigned char reg_val;
0544 
0545     reg_val = 0x00;
0546     /* Set keyboard split method */
0547     if (params->kbd_split)
0548         reg_val |= OPL3_KEYBOARD_SPLIT;
0549     opl3->command(opl3, OPL3_LEFT | OPL3_REG_KBD_SPLIT, reg_val);
0550 
0551     reg_val = 0x00;
0552     /* Set amplitude modulation (tremolo) depth */
0553     if (params->am_depth)
0554         reg_val |= OPL3_TREMOLO_DEPTH;
0555     /* Set vibrato depth */
0556     if (params->vib_depth)
0557         reg_val |= OPL3_VIBRATO_DEPTH;
0558     /* Set percussion mode */
0559     if (params->rhythm) {
0560         reg_val |= OPL3_PERCUSSION_ENABLE;
0561         opl3->rhythm = 1;
0562     } else {
0563         opl3->rhythm = 0;
0564     }
0565     /* Play percussion instruments */
0566     if (params->bass)
0567         reg_val |= OPL3_BASSDRUM_ON;
0568     if (params->snare)
0569         reg_val |= OPL3_SNAREDRUM_ON;
0570     if (params->tomtom)
0571         reg_val |= OPL3_TOMTOM_ON;
0572     if (params->cymbal)
0573         reg_val |= OPL3_CYMBAL_ON;
0574     if (params->hihat)
0575         reg_val |= OPL3_HIHAT_ON;
0576 
0577     opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, reg_val);
0578     return 0;
0579 }
0580 
0581 static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode)
0582 {
0583     if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3))
0584         return -EINVAL;
0585 
0586     opl3->fm_mode = mode;
0587     if (opl3->hardware >= OPL3_HW_OPL3)
0588         opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 0x00); /* Clear 4-op connections */
0589 
0590     return 0;
0591 }
0592 
0593 static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection)
0594 {
0595     unsigned char reg_val;
0596 
0597     /* OPL-3 only */
0598     if (opl3->fm_mode != SNDRV_DM_FM_MODE_OPL3)
0599         return -EINVAL;
0600 
0601     reg_val = connection & (OPL3_RIGHT_4OP_0 | OPL3_RIGHT_4OP_1 | OPL3_RIGHT_4OP_2 |
0602                 OPL3_LEFT_4OP_0 | OPL3_LEFT_4OP_1 | OPL3_LEFT_4OP_2);
0603     /* Set 4-op connections */
0604     opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val);
0605 
0606     return 0;
0607 }
0608