1 /* 2 * Copyright (c) by Uros Bizjak <uros@kss-loka.si> 3 * 4 * Routines for OPL2/OPL3/OPL4 control 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <linux/slab.h> 23 #include <linux/export.h> 24 #include <linux/nospec.h> 25 #include <sound/opl3.h> 26 #include <sound/asound_fm.h> 27 #include "opl3_voice.h" 28 29 #if IS_ENABLED(CONFIG_SND_SEQUENCER) 30 #define OPL3_SUPPORT_SYNTH 31 #endif 32 33 /* 34 * There is 18 possible 2 OP voices 35 * (9 in the left and 9 in the right). 36 * The first OP is the modulator and 2nd is the carrier. 37 * 38 * The first three voices in the both sides may be connected 39 * with another voice to a 4 OP voice. For example voice 0 40 * can be connected with voice 3. The operators of voice 3 are 41 * used as operators 3 and 4 of the new 4 OP voice. 42 * In this case the 2 OP voice number 0 is the 'first half' and 43 * voice 3 is the second. 44 */ 45 46 47 /* 48 * Register offset table for OPL2/3 voices, 49 * OPL2 / one OPL3 register array side only 50 */ 51 52 char snd_opl3_regmap[MAX_OPL2_VOICES][4] = 53 { 54 /* OP1 OP2 OP3 OP4 */ 55 /* ------------------------ */ 56 { 0x00, 0x03, 0x08, 0x0b }, 57 { 0x01, 0x04, 0x09, 0x0c }, 58 { 0x02, 0x05, 0x0a, 0x0d }, 59 60 { 0x08, 0x0b, 0x00, 0x00 }, 61 { 0x09, 0x0c, 0x00, 0x00 }, 62 { 0x0a, 0x0d, 0x00, 0x00 }, 63 64 { 0x10, 0x13, 0x00, 0x00 }, /* used by percussive voices */ 65 { 0x11, 0x14, 0x00, 0x00 }, /* if the percussive mode */ 66 { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ 67 }; 68 69 EXPORT_SYMBOL(snd_opl3_regmap); 70 71 /* 72 * prototypes 73 */ 74 static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note); 75 static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice); 76 static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params); 77 static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode); 78 static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection); 79 80 /* ------------------------------ */ 81 82 /* 83 * open the device exclusively 84 */ 85 int snd_opl3_open(struct snd_hwdep * hw, struct file *file) 86 { 87 return 0; 88 } 89 90 /* 91 * ioctl for hwdep device: 92 */ 93 int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, 94 unsigned int cmd, unsigned long arg) 95 { 96 struct snd_opl3 *opl3 = hw->private_data; 97 void __user *argp = (void __user *)arg; 98 99 if (snd_BUG_ON(!opl3)) 100 return -EINVAL; 101 102 switch (cmd) { 103 /* get information */ 104 case SNDRV_DM_FM_IOCTL_INFO: 105 { 106 struct snd_dm_fm_info info; 107 108 info.fm_mode = opl3->fm_mode; 109 info.rhythm = opl3->rhythm; 110 if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info))) 111 return -EFAULT; 112 return 0; 113 } 114 115 case SNDRV_DM_FM_IOCTL_RESET: 116 #ifdef CONFIG_SND_OSSEMUL 117 case SNDRV_DM_FM_OSS_IOCTL_RESET: 118 #endif 119 snd_opl3_reset(opl3); 120 return 0; 121 122 case SNDRV_DM_FM_IOCTL_PLAY_NOTE: 123 #ifdef CONFIG_SND_OSSEMUL 124 case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE: 125 #endif 126 { 127 struct snd_dm_fm_note note; 128 if (copy_from_user(¬e, argp, sizeof(struct snd_dm_fm_note))) 129 return -EFAULT; 130 return snd_opl3_play_note(opl3, ¬e); 131 } 132 133 case SNDRV_DM_FM_IOCTL_SET_VOICE: 134 #ifdef CONFIG_SND_OSSEMUL 135 case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE: 136 #endif 137 { 138 struct snd_dm_fm_voice voice; 139 if (copy_from_user(&voice, argp, sizeof(struct snd_dm_fm_voice))) 140 return -EFAULT; 141 return snd_opl3_set_voice(opl3, &voice); 142 } 143 144 case SNDRV_DM_FM_IOCTL_SET_PARAMS: 145 #ifdef CONFIG_SND_OSSEMUL 146 case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS: 147 #endif 148 { 149 struct snd_dm_fm_params params; 150 if (copy_from_user(¶ms, argp, sizeof(struct snd_dm_fm_params))) 151 return -EFAULT; 152 return snd_opl3_set_params(opl3, ¶ms); 153 } 154 155 case SNDRV_DM_FM_IOCTL_SET_MODE: 156 #ifdef CONFIG_SND_OSSEMUL 157 case SNDRV_DM_FM_OSS_IOCTL_SET_MODE: 158 #endif 159 return snd_opl3_set_mode(opl3, (int) arg); 160 161 case SNDRV_DM_FM_IOCTL_SET_CONNECTION: 162 #ifdef CONFIG_SND_OSSEMUL 163 case SNDRV_DM_FM_OSS_IOCTL_SET_OPL: 164 #endif 165 return snd_opl3_set_connection(opl3, (int) arg); 166 167 #ifdef OPL3_SUPPORT_SYNTH 168 case SNDRV_DM_FM_IOCTL_CLEAR_PATCHES: 169 snd_opl3_clear_patches(opl3); 170 return 0; 171 #endif 172 173 #ifdef CONFIG_SND_DEBUG 174 default: 175 snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd); 176 #endif 177 } 178 return -ENOTTY; 179 } 180 181 /* 182 * close the device 183 */ 184 int snd_opl3_release(struct snd_hwdep * hw, struct file *file) 185 { 186 struct snd_opl3 *opl3 = hw->private_data; 187 188 snd_opl3_reset(opl3); 189 return 0; 190 } 191 192 #ifdef OPL3_SUPPORT_SYNTH 193 /* 194 * write the device - load patches 195 */ 196 long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count, 197 loff_t *offset) 198 { 199 struct snd_opl3 *opl3 = hw->private_data; 200 long result = 0; 201 int err = 0; 202 struct sbi_patch inst; 203 204 while (count >= sizeof(inst)) { 205 unsigned char type; 206 if (copy_from_user(&inst, buf, sizeof(inst))) 207 return -EFAULT; 208 if (!memcmp(inst.key, FM_KEY_SBI, 4) || 209 !memcmp(inst.key, FM_KEY_2OP, 4)) 210 type = FM_PATCH_OPL2; 211 else if (!memcmp(inst.key, FM_KEY_4OP, 4)) 212 type = FM_PATCH_OPL3; 213 else /* invalid type */ 214 break; 215 err = snd_opl3_load_patch(opl3, inst.prog, inst.bank, type, 216 inst.name, inst.extension, 217 inst.data); 218 if (err < 0) 219 break; 220 result += sizeof(inst); 221 count -= sizeof(inst); 222 } 223 return result > 0 ? result : err; 224 } 225 226 227 /* 228 * Patch management 229 */ 230 231 /* offsets for SBI params */ 232 #define AM_VIB 0 233 #define KSL_LEVEL 2 234 #define ATTACK_DECAY 4 235 #define SUSTAIN_RELEASE 6 236 #define WAVE_SELECT 8 237 238 /* offset for SBI instrument */ 239 #define CONNECTION 10 240 #define OFFSET_4OP 11 241 242 /* 243 * load a patch, obviously. 244 * 245 * loaded on the given program and bank numbers with the given type 246 * (FM_PATCH_OPLx). 247 * data is the pointer of SBI record _without_ header (key and name). 248 * name is the name string of the patch. 249 * ext is the extension data of 7 bytes long (stored in name of SBI 250 * data up to offset 25), or NULL to skip. 251 * return 0 if successful or a negative error code. 252 */ 253 int snd_opl3_load_patch(struct snd_opl3 *opl3, 254 int prog, int bank, int type, 255 const char *name, 256 const unsigned char *ext, 257 const unsigned char *data) 258 { 259 struct fm_patch *patch; 260 int i; 261 262 patch = snd_opl3_find_patch(opl3, prog, bank, 1); 263 if (!patch) 264 return -ENOMEM; 265 266 patch->type = type; 267 268 for (i = 0; i < 2; i++) { 269 patch->inst.op[i].am_vib = data[AM_VIB + i]; 270 patch->inst.op[i].ksl_level = data[KSL_LEVEL + i]; 271 patch->inst.op[i].attack_decay = data[ATTACK_DECAY + i]; 272 patch->inst.op[i].sustain_release = data[SUSTAIN_RELEASE + i]; 273 patch->inst.op[i].wave_select = data[WAVE_SELECT + i]; 274 } 275 patch->inst.feedback_connection[0] = data[CONNECTION]; 276 277 if (type == FM_PATCH_OPL3) { 278 for (i = 0; i < 2; i++) { 279 patch->inst.op[i+2].am_vib = 280 data[OFFSET_4OP + AM_VIB + i]; 281 patch->inst.op[i+2].ksl_level = 282 data[OFFSET_4OP + KSL_LEVEL + i]; 283 patch->inst.op[i+2].attack_decay = 284 data[OFFSET_4OP + ATTACK_DECAY + i]; 285 patch->inst.op[i+2].sustain_release = 286 data[OFFSET_4OP + SUSTAIN_RELEASE + i]; 287 patch->inst.op[i+2].wave_select = 288 data[OFFSET_4OP + WAVE_SELECT + i]; 289 } 290 patch->inst.feedback_connection[1] = 291 data[OFFSET_4OP + CONNECTION]; 292 } 293 294 if (ext) { 295 patch->inst.echo_delay = ext[0]; 296 patch->inst.echo_atten = ext[1]; 297 patch->inst.chorus_spread = ext[2]; 298 patch->inst.trnsps = ext[3]; 299 patch->inst.fix_dur = ext[4]; 300 patch->inst.modes = ext[5]; 301 patch->inst.fix_key = ext[6]; 302 } 303 304 if (name) 305 strlcpy(patch->name, name, sizeof(patch->name)); 306 307 return 0; 308 } 309 EXPORT_SYMBOL(snd_opl3_load_patch); 310 311 /* 312 * find a patch with the given program and bank numbers, returns its pointer 313 * if no matching patch is found and create_patch is set, it creates a 314 * new patch object. 315 */ 316 struct fm_patch *snd_opl3_find_patch(struct snd_opl3 *opl3, int prog, int bank, 317 int create_patch) 318 { 319 /* pretty dumb hash key */ 320 unsigned int key = (prog + bank) % OPL3_PATCH_HASH_SIZE; 321 struct fm_patch *patch; 322 323 for (patch = opl3->patch_table[key]; patch; patch = patch->next) { 324 if (patch->prog == prog && patch->bank == bank) 325 return patch; 326 } 327 if (!create_patch) 328 return NULL; 329 330 patch = kzalloc(sizeof(*patch), GFP_KERNEL); 331 if (!patch) 332 return NULL; 333 patch->prog = prog; 334 patch->bank = bank; 335 patch->next = opl3->patch_table[key]; 336 opl3->patch_table[key] = patch; 337 return patch; 338 } 339 EXPORT_SYMBOL(snd_opl3_find_patch); 340 341 /* 342 * Clear all patches of the given OPL3 instance 343 */ 344 void snd_opl3_clear_patches(struct snd_opl3 *opl3) 345 { 346 int i; 347 for (i = 0; i < OPL3_PATCH_HASH_SIZE; i++) { 348 struct fm_patch *patch, *next; 349 for (patch = opl3->patch_table[i]; patch; patch = next) { 350 next = patch->next; 351 kfree(patch); 352 } 353 } 354 memset(opl3->patch_table, 0, sizeof(opl3->patch_table)); 355 } 356 #endif /* OPL3_SUPPORT_SYNTH */ 357 358 /* ------------------------------ */ 359 360 void snd_opl3_reset(struct snd_opl3 * opl3) 361 { 362 unsigned short opl3_reg; 363 364 unsigned short reg_side; 365 unsigned char voice_offset; 366 367 int max_voices, i; 368 369 max_voices = (opl3->hardware < OPL3_HW_OPL3) ? 370 MAX_OPL2_VOICES : MAX_OPL3_VOICES; 371 372 for (i = 0; i < max_voices; i++) { 373 /* Get register array side and offset of voice */ 374 if (i < MAX_OPL2_VOICES) { 375 /* Left register block for voices 0 .. 8 */ 376 reg_side = OPL3_LEFT; 377 voice_offset = i; 378 } else { 379 /* Right register block for voices 9 .. 17 */ 380 reg_side = OPL3_RIGHT; 381 voice_offset = i - MAX_OPL2_VOICES; 382 } 383 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][0]); 384 opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 1 volume */ 385 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][1]); 386 opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 2 volume */ 387 388 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); 389 opl3->command(opl3, opl3_reg, 0x00); /* Note off */ 390 } 391 392 opl3->max_voices = MAX_OPL2_VOICES; 393 opl3->fm_mode = SNDRV_DM_FM_MODE_OPL2; 394 395 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); 396 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */ 397 opl3->rhythm = 0; 398 } 399 400 EXPORT_SYMBOL(snd_opl3_reset); 401 402 static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note) 403 { 404 unsigned short reg_side; 405 unsigned char voice_offset; 406 407 unsigned short opl3_reg; 408 unsigned char reg_val; 409 410 /* Voices 0 - 8 in OPL2 mode */ 411 /* Voices 0 - 17 in OPL3 mode */ 412 if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? 413 MAX_OPL3_VOICES : MAX_OPL2_VOICES)) 414 return -EINVAL; 415 416 /* Get register array side and offset of voice */ 417 if (note->voice < MAX_OPL2_VOICES) { 418 /* Left register block for voices 0 .. 8 */ 419 reg_side = OPL3_LEFT; 420 voice_offset = note->voice; 421 } else { 422 /* Right register block for voices 9 .. 17 */ 423 reg_side = OPL3_RIGHT; 424 voice_offset = note->voice - MAX_OPL2_VOICES; 425 } 426 427 /* Set lower 8 bits of note frequency */ 428 reg_val = (unsigned char) note->fnum; 429 opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); 430 opl3->command(opl3, opl3_reg, reg_val); 431 432 reg_val = 0x00; 433 /* Set output sound flag */ 434 if (note->key_on) 435 reg_val |= OPL3_KEYON_BIT; 436 /* Set octave */ 437 reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK; 438 /* Set higher 2 bits of note frequency */ 439 reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK; 440 441 /* Set OPL3 KEYON_BLOCK register of requested voice */ 442 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); 443 opl3->command(opl3, opl3_reg, reg_val); 444 445 return 0; 446 } 447 448 449 static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice) 450 { 451 unsigned short reg_side; 452 unsigned char op_offset; 453 unsigned char voice_offset, voice_op; 454 455 unsigned short opl3_reg; 456 unsigned char reg_val; 457 458 /* Only operators 1 and 2 */ 459 if (voice->op > 1) 460 return -EINVAL; 461 /* Voices 0 - 8 in OPL2 mode */ 462 /* Voices 0 - 17 in OPL3 mode */ 463 if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? 464 MAX_OPL3_VOICES : MAX_OPL2_VOICES)) 465 return -EINVAL; 466 467 /* Get register array side and offset of voice */ 468 if (voice->voice < MAX_OPL2_VOICES) { 469 /* Left register block for voices 0 .. 8 */ 470 reg_side = OPL3_LEFT; 471 voice_offset = voice->voice; 472 } else { 473 /* Right register block for voices 9 .. 17 */ 474 reg_side = OPL3_RIGHT; 475 voice_offset = voice->voice - MAX_OPL2_VOICES; 476 } 477 /* Get register offset of operator */ 478 voice_offset = array_index_nospec(voice_offset, MAX_OPL2_VOICES); 479 voice_op = array_index_nospec(voice->op, 4); 480 op_offset = snd_opl3_regmap[voice_offset][voice_op]; 481 482 reg_val = 0x00; 483 /* Set amplitude modulation (tremolo) effect */ 484 if (voice->am) 485 reg_val |= OPL3_TREMOLO_ON; 486 /* Set vibrato effect */ 487 if (voice->vibrato) 488 reg_val |= OPL3_VIBRATO_ON; 489 /* Set sustaining sound phase */ 490 if (voice->do_sustain) 491 reg_val |= OPL3_SUSTAIN_ON; 492 /* Set keyboard scaling bit */ 493 if (voice->kbd_scale) 494 reg_val |= OPL3_KSR; 495 /* Set harmonic or frequency multiplier */ 496 reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK; 497 498 /* Set OPL3 AM_VIB register of requested voice/operator */ 499 opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset); 500 opl3->command(opl3, opl3_reg, reg_val); 501 502 /* Set decreasing volume of higher notes */ 503 reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK; 504 /* Set output volume */ 505 reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK; 506 507 /* Set OPL3 KSL_LEVEL register of requested voice/operator */ 508 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset); 509 opl3->command(opl3, opl3_reg, reg_val); 510 511 /* Set attack phase level */ 512 reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK; 513 /* Set decay phase level */ 514 reg_val |= voice->decay & OPL3_DECAY_MASK; 515 516 /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ 517 opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset); 518 opl3->command(opl3, opl3_reg, reg_val); 519 520 /* Set sustain phase level */ 521 reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK; 522 /* Set release phase level */ 523 reg_val |= voice->release & OPL3_RELEASE_MASK; 524 525 /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ 526 opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset); 527 opl3->command(opl3, opl3_reg, reg_val); 528 529 /* Set inter-operator feedback */ 530 reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK; 531 /* Set inter-operator connection */ 532 if (voice->connection) 533 reg_val |= OPL3_CONNECTION_BIT; 534 /* OPL-3 only */ 535 if (opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) { 536 if (voice->left) 537 reg_val |= OPL3_VOICE_TO_LEFT; 538 if (voice->right) 539 reg_val |= OPL3_VOICE_TO_RIGHT; 540 } 541 /* Feedback/connection bits are applicable to voice */ 542 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); 543 opl3->command(opl3, opl3_reg, reg_val); 544 545 /* Select waveform */ 546 reg_val = voice->waveform & OPL3_WAVE_SELECT_MASK; 547 opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset); 548 opl3->command(opl3, opl3_reg, reg_val); 549 550 return 0; 551 } 552 553 static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params) 554 { 555 unsigned char reg_val; 556 557 reg_val = 0x00; 558 /* Set keyboard split method */ 559 if (params->kbd_split) 560 reg_val |= OPL3_KEYBOARD_SPLIT; 561 opl3->command(opl3, OPL3_LEFT | OPL3_REG_KBD_SPLIT, reg_val); 562 563 reg_val = 0x00; 564 /* Set amplitude modulation (tremolo) depth */ 565 if (params->am_depth) 566 reg_val |= OPL3_TREMOLO_DEPTH; 567 /* Set vibrato depth */ 568 if (params->vib_depth) 569 reg_val |= OPL3_VIBRATO_DEPTH; 570 /* Set percussion mode */ 571 if (params->rhythm) { 572 reg_val |= OPL3_PERCUSSION_ENABLE; 573 opl3->rhythm = 1; 574 } else { 575 opl3->rhythm = 0; 576 } 577 /* Play percussion instruments */ 578 if (params->bass) 579 reg_val |= OPL3_BASSDRUM_ON; 580 if (params->snare) 581 reg_val |= OPL3_SNAREDRUM_ON; 582 if (params->tomtom) 583 reg_val |= OPL3_TOMTOM_ON; 584 if (params->cymbal) 585 reg_val |= OPL3_CYMBAL_ON; 586 if (params->hihat) 587 reg_val |= OPL3_HIHAT_ON; 588 589 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, reg_val); 590 return 0; 591 } 592 593 static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode) 594 { 595 if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3)) 596 return -EINVAL; 597 598 opl3->fm_mode = mode; 599 if (opl3->hardware >= OPL3_HW_OPL3) 600 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 0x00); /* Clear 4-op connections */ 601 602 return 0; 603 } 604 605 static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection) 606 { 607 unsigned char reg_val; 608 609 /* OPL-3 only */ 610 if (opl3->fm_mode != SNDRV_DM_FM_MODE_OPL3) 611 return -EINVAL; 612 613 reg_val = connection & (OPL3_RIGHT_4OP_0 | OPL3_RIGHT_4OP_1 | OPL3_RIGHT_4OP_2 | 614 OPL3_LEFT_4OP_0 | OPL3_LEFT_4OP_1 | OPL3_LEFT_4OP_2); 615 /* Set 4-op connections */ 616 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val); 617 618 return 0; 619 } 620 621