1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) by Uros Bizjak <uros@kss-loka.si> 4 * 5 * Midi Sequencer interface routines for OPL2/OPL3/OPL4 FM 6 * 7 * OPL2/3 FM instrument loader: 8 * alsa-tools/seq/sbiload/ 9 */ 10 11 #include "opl3_voice.h" 12 #include <linux/init.h> 13 #include <linux/moduleparam.h> 14 #include <linux/module.h> 15 #include <sound/initval.h> 16 17 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); 18 MODULE_LICENSE("GPL"); 19 MODULE_DESCRIPTION("ALSA driver for OPL3 FM synth"); 20 21 bool use_internal_drums = 0; 22 module_param(use_internal_drums, bool, 0444); 23 MODULE_PARM_DESC(use_internal_drums, "Enable internal OPL2/3 drums."); 24 25 int snd_opl3_synth_use_inc(struct snd_opl3 * opl3) 26 { 27 if (!try_module_get(opl3->card->module)) 28 return -EFAULT; 29 return 0; 30 31 } 32 33 void snd_opl3_synth_use_dec(struct snd_opl3 * opl3) 34 { 35 module_put(opl3->card->module); 36 } 37 38 int snd_opl3_synth_setup(struct snd_opl3 * opl3) 39 { 40 int idx; 41 struct snd_hwdep *hwdep = opl3->hwdep; 42 43 mutex_lock(&hwdep->open_mutex); 44 if (hwdep->used) { 45 mutex_unlock(&hwdep->open_mutex); 46 return -EBUSY; 47 } 48 hwdep->used++; 49 mutex_unlock(&hwdep->open_mutex); 50 51 snd_opl3_reset(opl3); 52 53 for (idx = 0; idx < MAX_OPL3_VOICES; idx++) { 54 opl3->voices[idx].state = SNDRV_OPL3_ST_OFF; 55 opl3->voices[idx].time = 0; 56 opl3->voices[idx].keyon_reg = 0x00; 57 } 58 opl3->use_time = 0; 59 opl3->connection_reg = 0x00; 60 if (opl3->hardware >= OPL3_HW_OPL3) { 61 /* Clear 4-op connections */ 62 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 63 opl3->connection_reg); 64 opl3->max_voices = MAX_OPL3_VOICES; 65 } 66 return 0; 67 } 68 69 void snd_opl3_synth_cleanup(struct snd_opl3 * opl3) 70 { 71 unsigned long flags; 72 struct snd_hwdep *hwdep; 73 74 /* Stop system timer */ 75 spin_lock_irqsave(&opl3->sys_timer_lock, flags); 76 if (opl3->sys_timer_status) { 77 del_timer(&opl3->tlist); 78 opl3->sys_timer_status = 0; 79 } 80 spin_unlock_irqrestore(&opl3->sys_timer_lock, flags); 81 82 snd_opl3_reset(opl3); 83 hwdep = opl3->hwdep; 84 mutex_lock(&hwdep->open_mutex); 85 hwdep->used--; 86 mutex_unlock(&hwdep->open_mutex); 87 wake_up(&hwdep->open_wait); 88 } 89 90 static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe * info) 91 { 92 struct snd_opl3 *opl3 = private_data; 93 int err; 94 95 if ((err = snd_opl3_synth_setup(opl3)) < 0) 96 return err; 97 98 if (use_internal_drums) { 99 /* Percussion mode */ 100 opl3->voices[6].state = opl3->voices[7].state = 101 opl3->voices[8].state = SNDRV_OPL3_ST_NOT_AVAIL; 102 snd_opl3_load_drums(opl3); 103 opl3->drum_reg = OPL3_PERCUSSION_ENABLE; 104 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, opl3->drum_reg); 105 } else { 106 opl3->drum_reg = 0x00; 107 } 108 109 if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { 110 if ((err = snd_opl3_synth_use_inc(opl3)) < 0) 111 return err; 112 } 113 opl3->synth_mode = SNDRV_OPL3_MODE_SEQ; 114 return 0; 115 } 116 117 static int snd_opl3_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info) 118 { 119 struct snd_opl3 *opl3 = private_data; 120 121 snd_opl3_synth_cleanup(opl3); 122 123 if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) 124 snd_opl3_synth_use_dec(opl3); 125 return 0; 126 } 127 128 /* 129 * MIDI emulation operators 130 */ 131 const struct snd_midi_op opl3_ops = { 132 .note_on = snd_opl3_note_on, 133 .note_off = snd_opl3_note_off, 134 .key_press = snd_opl3_key_press, 135 .note_terminate = snd_opl3_terminate_note, 136 .control = snd_opl3_control, 137 .nrpn = snd_opl3_nrpn, 138 .sysex = snd_opl3_sysex, 139 }; 140 141 static int snd_opl3_synth_event_input(struct snd_seq_event * ev, int direct, 142 void *private_data, int atomic, int hop) 143 { 144 struct snd_opl3 *opl3 = private_data; 145 146 snd_midi_process_event(&opl3_ops, ev, opl3->chset); 147 return 0; 148 } 149 150 /* ------------------------------ */ 151 152 static void snd_opl3_synth_free_port(void *private_data) 153 { 154 struct snd_opl3 *opl3 = private_data; 155 156 snd_midi_channel_free_set(opl3->chset); 157 } 158 159 static int snd_opl3_synth_create_port(struct snd_opl3 * opl3) 160 { 161 struct snd_seq_port_callback callbacks; 162 char name[32]; 163 int voices, opl_ver; 164 165 voices = (opl3->hardware < OPL3_HW_OPL3) ? 166 MAX_OPL2_VOICES : MAX_OPL3_VOICES; 167 opl3->chset = snd_midi_channel_alloc_set(16); 168 if (opl3->chset == NULL) 169 return -ENOMEM; 170 opl3->chset->private_data = opl3; 171 172 memset(&callbacks, 0, sizeof(callbacks)); 173 callbacks.owner = THIS_MODULE; 174 callbacks.use = snd_opl3_synth_use; 175 callbacks.unuse = snd_opl3_synth_unuse; 176 callbacks.event_input = snd_opl3_synth_event_input; 177 callbacks.private_free = snd_opl3_synth_free_port; 178 callbacks.private_data = opl3; 179 180 opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; 181 sprintf(name, "OPL%i FM Port", opl_ver); 182 183 opl3->chset->client = opl3->seq_client; 184 opl3->chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks, 185 SNDRV_SEQ_PORT_CAP_WRITE | 186 SNDRV_SEQ_PORT_CAP_SUBS_WRITE, 187 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | 188 SNDRV_SEQ_PORT_TYPE_MIDI_GM | 189 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | 190 SNDRV_SEQ_PORT_TYPE_HARDWARE | 191 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, 192 16, voices, 193 name); 194 if (opl3->chset->port < 0) { 195 int port; 196 port = opl3->chset->port; 197 snd_midi_channel_free_set(opl3->chset); 198 return port; 199 } 200 return 0; 201 } 202 203 /* ------------------------------ */ 204 205 static int snd_opl3_seq_probe(struct device *_dev) 206 { 207 struct snd_seq_device *dev = to_seq_dev(_dev); 208 struct snd_opl3 *opl3; 209 int client, err; 210 char name[32]; 211 int opl_ver; 212 213 opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); 214 if (opl3 == NULL) 215 return -EINVAL; 216 217 spin_lock_init(&opl3->voice_lock); 218 219 opl3->seq_client = -1; 220 221 /* allocate new client */ 222 opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; 223 sprintf(name, "OPL%i FM synth", opl_ver); 224 client = opl3->seq_client = 225 snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num, 226 name); 227 if (client < 0) 228 return client; 229 230 if ((err = snd_opl3_synth_create_port(opl3)) < 0) { 231 snd_seq_delete_kernel_client(client); 232 opl3->seq_client = -1; 233 return err; 234 } 235 236 /* setup system timer */ 237 timer_setup(&opl3->tlist, snd_opl3_timer_func, 0); 238 spin_lock_init(&opl3->sys_timer_lock); 239 opl3->sys_timer_status = 0; 240 241 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) 242 snd_opl3_init_seq_oss(opl3, name); 243 #endif 244 return 0; 245 } 246 247 static int snd_opl3_seq_remove(struct device *_dev) 248 { 249 struct snd_seq_device *dev = to_seq_dev(_dev); 250 struct snd_opl3 *opl3; 251 252 opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); 253 if (opl3 == NULL) 254 return -EINVAL; 255 256 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) 257 snd_opl3_free_seq_oss(opl3); 258 #endif 259 if (opl3->seq_client >= 0) { 260 snd_seq_delete_kernel_client(opl3->seq_client); 261 opl3->seq_client = -1; 262 } 263 return 0; 264 } 265 266 static struct snd_seq_driver opl3_seq_driver = { 267 .driver = { 268 .name = KBUILD_MODNAME, 269 .probe = snd_opl3_seq_probe, 270 .remove = snd_opl3_seq_remove, 271 }, 272 .id = SNDRV_SEQ_DEV_ID_OPL3, 273 .argsize = sizeof(struct snd_opl3 *), 274 }; 275 276 module_snd_seq_driver(opl3_seq_driver); 277