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 <sound/opl3.h> 23 #include <sound/asound_fm.h> 24 25 /* 26 * There is 18 possible 2 OP voices 27 * (9 in the left and 9 in the right). 28 * The first OP is the modulator and 2nd is the carrier. 29 * 30 * The first three voices in the both sides may be connected 31 * with another voice to a 4 OP voice. For example voice 0 32 * can be connected with voice 3. The operators of voice 3 are 33 * used as operators 3 and 4 of the new 4 OP voice. 34 * In this case the 2 OP voice number 0 is the 'first half' and 35 * voice 3 is the second. 36 */ 37 38 39 /* 40 * Register offset table for OPL2/3 voices, 41 * OPL2 / one OPL3 register array side only 42 */ 43 44 char snd_opl3_regmap[MAX_OPL2_VOICES][4] = 45 { 46 /* OP1 OP2 OP3 OP4 */ 47 /* ------------------------ */ 48 { 0x00, 0x03, 0x08, 0x0b }, 49 { 0x01, 0x04, 0x09, 0x0c }, 50 { 0x02, 0x05, 0x0a, 0x0d }, 51 52 { 0x08, 0x0b, 0x00, 0x00 }, 53 { 0x09, 0x0c, 0x00, 0x00 }, 54 { 0x0a, 0x0d, 0x00, 0x00 }, 55 56 { 0x10, 0x13, 0x00, 0x00 }, /* used by percussive voices */ 57 { 0x11, 0x14, 0x00, 0x00 }, /* if the percussive mode */ 58 { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ 59 }; 60 61 /* 62 * prototypes 63 */ 64 static int snd_opl3_play_note(opl3_t * opl3, snd_dm_fm_note_t * note); 65 static int snd_opl3_set_voice(opl3_t * opl3, snd_dm_fm_voice_t * voice); 66 static int snd_opl3_set_params(opl3_t * opl3, snd_dm_fm_params_t * params); 67 static int snd_opl3_set_mode(opl3_t * opl3, int mode); 68 static int snd_opl3_set_connection(opl3_t * opl3, int connection); 69 70 /* ------------------------------ */ 71 72 /* 73 * open the device exclusively 74 */ 75 int snd_opl3_open(snd_hwdep_t * hw, struct file *file) 76 { 77 opl3_t *opl3 = hw->private_data; 78 79 down(&opl3->access_mutex); 80 if (opl3->used) { 81 up(&opl3->access_mutex); 82 return -EAGAIN; 83 } 84 opl3->used++; 85 up(&opl3->access_mutex); 86 87 return 0; 88 } 89 90 /* 91 * ioctl for hwdep device: 92 */ 93 int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file, 94 unsigned int cmd, unsigned long arg) 95 { 96 opl3_t *opl3 = hw->private_data; 97 void __user *argp = (void __user *)arg; 98 99 snd_assert(opl3 != NULL, return -EINVAL); 100 101 switch (cmd) { 102 /* get information */ 103 case SNDRV_DM_FM_IOCTL_INFO: 104 { 105 snd_dm_fm_info_t info; 106 107 info.fm_mode = opl3->fm_mode; 108 info.rhythm = opl3->rhythm; 109 if (copy_to_user(argp, &info, sizeof(snd_dm_fm_info_t))) 110 return -EFAULT; 111 return 0; 112 } 113 114 case SNDRV_DM_FM_IOCTL_RESET: 115 #ifdef CONFIG_SND_OSSEMUL 116 case SNDRV_DM_FM_OSS_IOCTL_RESET: 117 #endif 118 snd_opl3_reset(opl3); 119 return 0; 120 121 case SNDRV_DM_FM_IOCTL_PLAY_NOTE: 122 #ifdef CONFIG_SND_OSSEMUL 123 case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE: 124 #endif 125 { 126 snd_dm_fm_note_t note; 127 if (copy_from_user(¬e, argp, sizeof(snd_dm_fm_note_t))) 128 return -EFAULT; 129 return snd_opl3_play_note(opl3, ¬e); 130 } 131 132 case SNDRV_DM_FM_IOCTL_SET_VOICE: 133 #ifdef CONFIG_SND_OSSEMUL 134 case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE: 135 #endif 136 { 137 snd_dm_fm_voice_t voice; 138 if (copy_from_user(&voice, argp, sizeof(snd_dm_fm_voice_t))) 139 return -EFAULT; 140 return snd_opl3_set_voice(opl3, &voice); 141 } 142 143 case SNDRV_DM_FM_IOCTL_SET_PARAMS: 144 #ifdef CONFIG_SND_OSSEMUL 145 case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS: 146 #endif 147 { 148 snd_dm_fm_params_t params; 149 if (copy_from_user(¶ms, argp, sizeof(snd_dm_fm_params_t))) 150 return -EFAULT; 151 return snd_opl3_set_params(opl3, ¶ms); 152 } 153 154 case SNDRV_DM_FM_IOCTL_SET_MODE: 155 #ifdef CONFIG_SND_OSSEMUL 156 case SNDRV_DM_FM_OSS_IOCTL_SET_MODE: 157 #endif 158 return snd_opl3_set_mode(opl3, (int) arg); 159 160 case SNDRV_DM_FM_IOCTL_SET_CONNECTION: 161 #ifdef CONFIG_SND_OSSEMUL 162 case SNDRV_DM_FM_OSS_IOCTL_SET_OPL: 163 #endif 164 return snd_opl3_set_connection(opl3, (int) arg); 165 166 #ifdef CONFIG_SND_DEBUG 167 default: 168 snd_printk("unknown IOCTL: 0x%x\n", cmd); 169 #endif 170 } 171 return -ENOTTY; 172 } 173 174 /* 175 * close the device 176 */ 177 int snd_opl3_release(snd_hwdep_t * hw, struct file *file) 178 { 179 opl3_t *opl3 = hw->private_data; 180 181 snd_opl3_reset(opl3); 182 down(&opl3->access_mutex); 183 opl3->used--; 184 up(&opl3->access_mutex); 185 186 return 0; 187 } 188 189 /* ------------------------------ */ 190 191 void snd_opl3_reset(opl3_t * opl3) 192 { 193 unsigned short opl3_reg; 194 195 unsigned short reg_side; 196 unsigned char voice_offset; 197 198 int max_voices, i; 199 200 max_voices = (opl3->hardware < OPL3_HW_OPL3) ? 201 MAX_OPL2_VOICES : MAX_OPL3_VOICES; 202 203 for (i = 0; i < max_voices; i++) { 204 /* Get register array side and offset of voice */ 205 if (i < MAX_OPL2_VOICES) { 206 /* Left register block for voices 0 .. 8 */ 207 reg_side = OPL3_LEFT; 208 voice_offset = i; 209 } else { 210 /* Right register block for voices 9 .. 17 */ 211 reg_side = OPL3_RIGHT; 212 voice_offset = i - MAX_OPL2_VOICES; 213 } 214 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][0]); 215 opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 1 volume */ 216 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][1]); 217 opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 2 volume */ 218 219 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); 220 opl3->command(opl3, opl3_reg, 0x00); /* Note off */ 221 } 222 223 opl3->max_voices = MAX_OPL2_VOICES; 224 opl3->fm_mode = SNDRV_DM_FM_MODE_OPL2; 225 226 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT); 227 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */ 228 opl3->rhythm = 0; 229 } 230 231 232 static int snd_opl3_play_note(opl3_t * opl3, snd_dm_fm_note_t * note) 233 { 234 unsigned short reg_side; 235 unsigned char voice_offset; 236 237 unsigned short opl3_reg; 238 unsigned char reg_val; 239 240 /* Voices 0 - 8 in OPL2 mode */ 241 /* Voices 0 - 17 in OPL3 mode */ 242 if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? 243 MAX_OPL3_VOICES : MAX_OPL2_VOICES)) 244 return -EINVAL; 245 246 /* Get register array side and offset of voice */ 247 if (note->voice < MAX_OPL2_VOICES) { 248 /* Left register block for voices 0 .. 8 */ 249 reg_side = OPL3_LEFT; 250 voice_offset = note->voice; 251 } else { 252 /* Right register block for voices 9 .. 17 */ 253 reg_side = OPL3_RIGHT; 254 voice_offset = note->voice - MAX_OPL2_VOICES; 255 } 256 257 /* Set lower 8 bits of note frequency */ 258 reg_val = (unsigned char) note->fnum; 259 opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset); 260 opl3->command(opl3, opl3_reg, reg_val); 261 262 reg_val = 0x00; 263 /* Set output sound flag */ 264 if (note->key_on) 265 reg_val |= OPL3_KEYON_BIT; 266 /* Set octave */ 267 reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK; 268 /* Set higher 2 bits of note frequency */ 269 reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK; 270 271 /* Set OPL3 KEYON_BLOCK register of requested voice */ 272 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); 273 opl3->command(opl3, opl3_reg, reg_val); 274 275 return 0; 276 } 277 278 279 static int snd_opl3_set_voice(opl3_t * opl3, snd_dm_fm_voice_t * voice) 280 { 281 unsigned short reg_side; 282 unsigned char op_offset; 283 unsigned char voice_offset; 284 285 unsigned short opl3_reg; 286 unsigned char reg_val; 287 288 /* Only operators 1 and 2 */ 289 if (voice->op > 1) 290 return -EINVAL; 291 /* Voices 0 - 8 in OPL2 mode */ 292 /* Voices 0 - 17 in OPL3 mode */ 293 if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ? 294 MAX_OPL3_VOICES : MAX_OPL2_VOICES)) 295 return -EINVAL; 296 297 /* Get register array side and offset of voice */ 298 if (voice->voice < MAX_OPL2_VOICES) { 299 /* Left register block for voices 0 .. 8 */ 300 reg_side = OPL3_LEFT; 301 voice_offset = voice->voice; 302 } else { 303 /* Right register block for voices 9 .. 17 */ 304 reg_side = OPL3_RIGHT; 305 voice_offset = voice->voice - MAX_OPL2_VOICES; 306 } 307 /* Get register offset of operator */ 308 op_offset = snd_opl3_regmap[voice_offset][voice->op]; 309 310 reg_val = 0x00; 311 /* Set amplitude modulation (tremolo) effect */ 312 if (voice->am) 313 reg_val |= OPL3_TREMOLO_ON; 314 /* Set vibrato effect */ 315 if (voice->vibrato) 316 reg_val |= OPL3_VIBRATO_ON; 317 /* Set sustaining sound phase */ 318 if (voice->do_sustain) 319 reg_val |= OPL3_SUSTAIN_ON; 320 /* Set keyboard scaling bit */ 321 if (voice->kbd_scale) 322 reg_val |= OPL3_KSR; 323 /* Set harmonic or frequency multiplier */ 324 reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK; 325 326 /* Set OPL3 AM_VIB register of requested voice/operator */ 327 opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset); 328 opl3->command(opl3, opl3_reg, reg_val); 329 330 /* Set decreasing volume of higher notes */ 331 reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK; 332 /* Set output volume */ 333 reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK; 334 335 /* Set OPL3 KSL_LEVEL register of requested voice/operator */ 336 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset); 337 opl3->command(opl3, opl3_reg, reg_val); 338 339 /* Set attack phase level */ 340 reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK; 341 /* Set decay phase level */ 342 reg_val |= voice->decay & OPL3_DECAY_MASK; 343 344 /* Set OPL3 ATTACK_DECAY register of requested voice/operator */ 345 opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset); 346 opl3->command(opl3, opl3_reg, reg_val); 347 348 /* Set sustain phase level */ 349 reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK; 350 /* Set release phase level */ 351 reg_val |= voice->release & OPL3_RELEASE_MASK; 352 353 /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */ 354 opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset); 355 opl3->command(opl3, opl3_reg, reg_val); 356 357 /* Set inter-operator feedback */ 358 reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK; 359 /* Set inter-operator connection */ 360 if (voice->connection) 361 reg_val |= OPL3_CONNECTION_BIT; 362 /* OPL-3 only */ 363 if (opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) { 364 if (voice->left) 365 reg_val |= OPL3_VOICE_TO_LEFT; 366 if (voice->right) 367 reg_val |= OPL3_VOICE_TO_RIGHT; 368 } 369 /* Feedback/connection bits are applicable to voice */ 370 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset); 371 opl3->command(opl3, opl3_reg, reg_val); 372 373 /* Select waveform */ 374 reg_val = voice->waveform & OPL3_WAVE_SELECT_MASK; 375 opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset); 376 opl3->command(opl3, opl3_reg, reg_val); 377 378 return 0; 379 } 380 381 static int snd_opl3_set_params(opl3_t * opl3, snd_dm_fm_params_t * params) 382 { 383 unsigned char reg_val; 384 385 reg_val = 0x00; 386 /* Set keyboard split method */ 387 if (params->kbd_split) 388 reg_val |= OPL3_KEYBOARD_SPLIT; 389 opl3->command(opl3, OPL3_LEFT | OPL3_REG_KBD_SPLIT, reg_val); 390 391 reg_val = 0x00; 392 /* Set amplitude modulation (tremolo) depth */ 393 if (params->am_depth) 394 reg_val |= OPL3_TREMOLO_DEPTH; 395 /* Set vibrato depth */ 396 if (params->vib_depth) 397 reg_val |= OPL3_VIBRATO_DEPTH; 398 /* Set percussion mode */ 399 if (params->rhythm) { 400 reg_val |= OPL3_PERCUSSION_ENABLE; 401 opl3->rhythm = 1; 402 } else { 403 opl3->rhythm = 0; 404 } 405 /* Play percussion instruments */ 406 if (params->bass) 407 reg_val |= OPL3_BASSDRUM_ON; 408 if (params->snare) 409 reg_val |= OPL3_SNAREDRUM_ON; 410 if (params->tomtom) 411 reg_val |= OPL3_TOMTOM_ON; 412 if (params->cymbal) 413 reg_val |= OPL3_CYMBAL_ON; 414 if (params->hihat) 415 reg_val |= OPL3_HIHAT_ON; 416 417 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, reg_val); 418 return 0; 419 } 420 421 static int snd_opl3_set_mode(opl3_t * opl3, int mode) 422 { 423 if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3)) 424 return -EINVAL; 425 426 opl3->fm_mode = mode; 427 if (opl3->hardware >= OPL3_HW_OPL3) 428 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 0x00); /* Clear 4-op connections */ 429 430 return 0; 431 } 432 433 static int snd_opl3_set_connection(opl3_t * opl3, int connection) 434 { 435 unsigned char reg_val; 436 437 /* OPL-3 only */ 438 if (opl3->fm_mode != SNDRV_DM_FM_MODE_OPL3) 439 return -EINVAL; 440 441 reg_val = connection & (OPL3_RIGHT_4OP_0 | OPL3_RIGHT_4OP_1 | OPL3_RIGHT_4OP_2 | 442 OPL3_LEFT_4OP_0 | OPL3_LEFT_4OP_1 | OPL3_LEFT_4OP_2); 443 /* Set 4-op connections */ 444 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val); 445 446 return 0; 447 } 448