0001
0002
0003
0004
0005
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
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 char snd_opl3_regmap[MAX_OPL2_VOICES][4] =
0039 {
0040
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 },
0051 { 0x11, 0x14, 0x00, 0x00 },
0052 { 0x12, 0x15, 0x00, 0x00 }
0053 };
0054
0055 EXPORT_SYMBOL(snd_opl3_regmap);
0056
0057
0058
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
0070
0071 int snd_opl3_open(struct snd_hwdep * hw, struct file *file)
0072 {
0073 return 0;
0074 }
0075
0076
0077
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
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(¬e, argp, sizeof(struct snd_dm_fm_note)))
0117 return -EFAULT;
0118 return snd_opl3_play_note(opl3, ¬e);
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(¶ms, argp, sizeof(struct snd_dm_fm_params)))
0139 return -EFAULT;
0140 return snd_opl3_set_params(opl3, ¶ms);
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
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
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
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
0217
0218
0219
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
0227 #define CONNECTION 10
0228 #define OFFSET_4OP 11
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
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
0301
0302
0303
0304 struct fm_patch *snd_opl3_find_patch(struct snd_opl3 *opl3, int prog, int bank,
0305 int create_patch)
0306 {
0307
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
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
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
0362 if (i < MAX_OPL2_VOICES) {
0363
0364 reg_side = OPL3_LEFT;
0365 voice_offset = i;
0366 } else {
0367
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);
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);
0375
0376 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
0377 opl3->command(opl3, opl3_reg, 0x00);
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);
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
0399
0400 if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
0401 MAX_OPL3_VOICES : MAX_OPL2_VOICES))
0402 return -EINVAL;
0403
0404
0405 if (note->voice < MAX_OPL2_VOICES) {
0406
0407 reg_side = OPL3_LEFT;
0408 voice_offset = note->voice;
0409 } else {
0410
0411 reg_side = OPL3_RIGHT;
0412 voice_offset = note->voice - MAX_OPL2_VOICES;
0413 }
0414
0415
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
0422 if (note->key_on)
0423 reg_val |= OPL3_KEYON_BIT;
0424
0425 reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK;
0426
0427 reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK;
0428
0429
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
0447 if (voice->op > 1)
0448 return -EINVAL;
0449
0450
0451 if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
0452 MAX_OPL3_VOICES : MAX_OPL2_VOICES))
0453 return -EINVAL;
0454
0455
0456 if (voice->voice < MAX_OPL2_VOICES) {
0457
0458 reg_side = OPL3_LEFT;
0459 voice_offset = voice->voice;
0460 } else {
0461
0462 reg_side = OPL3_RIGHT;
0463 voice_offset = voice->voice - MAX_OPL2_VOICES;
0464 }
0465
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
0472 if (voice->am)
0473 reg_val |= OPL3_TREMOLO_ON;
0474
0475 if (voice->vibrato)
0476 reg_val |= OPL3_VIBRATO_ON;
0477
0478 if (voice->do_sustain)
0479 reg_val |= OPL3_SUSTAIN_ON;
0480
0481 if (voice->kbd_scale)
0482 reg_val |= OPL3_KSR;
0483
0484 reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK;
0485
0486
0487 opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset);
0488 opl3->command(opl3, opl3_reg, reg_val);
0489
0490
0491 reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK;
0492
0493 reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK;
0494
0495
0496 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset);
0497 opl3->command(opl3, opl3_reg, reg_val);
0498
0499
0500 reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK;
0501
0502 reg_val |= voice->decay & OPL3_DECAY_MASK;
0503
0504
0505 opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset);
0506 opl3->command(opl3, opl3_reg, reg_val);
0507
0508
0509 reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK;
0510
0511 reg_val |= voice->release & OPL3_RELEASE_MASK;
0512
0513
0514 opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
0515 opl3->command(opl3, opl3_reg, reg_val);
0516
0517
0518 reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK;
0519
0520 if (voice->connection)
0521 reg_val |= OPL3_CONNECTION_BIT;
0522
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
0530 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
0531 opl3->command(opl3, opl3_reg, reg_val);
0532
0533
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
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
0553 if (params->am_depth)
0554 reg_val |= OPL3_TREMOLO_DEPTH;
0555
0556 if (params->vib_depth)
0557 reg_val |= OPL3_VIBRATO_DEPTH;
0558
0559 if (params->rhythm) {
0560 reg_val |= OPL3_PERCUSSION_ENABLE;
0561 opl3->rhythm = 1;
0562 } else {
0563 opl3->rhythm = 0;
0564 }
0565
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);
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
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
0604 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val);
0605
0606 return 0;
0607 }
0608