Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/drivers/opl3/opl3_lib.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) by Jaroslav Kysela <[email protected]>,
4
* Hannu Savolainen 1993-1996,
5
* Rob Hooft
6
*
7
* Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)
8
*
9
* Most if code is ported from OSS/Lite.
10
*/
11
12
#include <sound/opl3.h>
13
#include <linux/io.h>
14
#include <linux/delay.h>
15
#include <linux/module.h>
16
#include <linux/init.h>
17
#include <linux/slab.h>
18
#include <linux/ioport.h>
19
#include <sound/minors.h>
20
#include "opl3_voice.h"
21
22
MODULE_AUTHOR("Jaroslav Kysela <[email protected]>, Hannu Savolainen 1993-1996, Rob Hooft");
23
MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)");
24
MODULE_LICENSE("GPL");
25
26
static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)
27
{
28
unsigned long flags;
29
unsigned long port;
30
31
/*
32
* The original 2-OP synth requires a quite long delay
33
* after writing to a register.
34
*/
35
36
port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;
37
38
spin_lock_irqsave(&opl3->reg_lock, flags);
39
40
outb((unsigned char) cmd, port);
41
udelay(10);
42
43
outb((unsigned char) val, port + 1);
44
udelay(30);
45
46
spin_unlock_irqrestore(&opl3->reg_lock, flags);
47
}
48
49
static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)
50
{
51
unsigned long flags;
52
unsigned long port;
53
54
/*
55
* The OPL-3 survives with just two INBs
56
* after writing to a register.
57
*/
58
59
port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;
60
61
spin_lock_irqsave(&opl3->reg_lock, flags);
62
63
outb((unsigned char) cmd, port);
64
inb(opl3->l_port);
65
inb(opl3->l_port);
66
67
outb((unsigned char) val, port + 1);
68
inb(opl3->l_port);
69
inb(opl3->l_port);
70
71
spin_unlock_irqrestore(&opl3->reg_lock, flags);
72
}
73
74
static int snd_opl3_detect(struct snd_opl3 * opl3)
75
{
76
/*
77
* This function returns 1 if the FM chip is present at the given I/O port
78
* The detection algorithm plays with the timer built in the FM chip and
79
* looks for a change in the status register.
80
*
81
* Note! The timers of the FM chip are not connected to AdLib (and compatible)
82
* boards.
83
*
84
* Note2! The chip is initialized if detected.
85
*/
86
87
unsigned char stat1, stat2, signature;
88
89
/* Reset timers 1 and 2 */
90
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);
91
/* Reset the IRQ of the FM chip */
92
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
93
signature = stat1 = inb(opl3->l_port); /* Status register */
94
if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */
95
dev_dbg(opl3->card->dev, "OPL3: stat1 = 0x%x\n", stat1);
96
return -ENODEV;
97
}
98
/* Set timer1 to 0xff */
99
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 0xff);
100
/* Unmask and start timer 1 */
101
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER2_MASK | OPL3_TIMER1_START);
102
/* Now we have to delay at least 80us */
103
udelay(200);
104
/* Read status after timers have expired */
105
stat2 = inb(opl3->l_port);
106
/* Stop the timers */
107
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);
108
/* Reset the IRQ of the FM chip */
109
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
110
if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */
111
dev_dbg(opl3->card->dev, "OPL3: stat2 = 0x%x\n", stat2);
112
return -ENODEV;
113
}
114
115
/* If the toplevel code knows exactly the type of chip, don't try
116
to detect it. */
117
if (opl3->hardware != OPL3_HW_AUTO)
118
return 0;
119
120
/* There is a FM chip on this address. Detect the type (OPL2 to OPL4) */
121
if (signature == 0x06) { /* OPL2 */
122
opl3->hardware = OPL3_HW_OPL2;
123
} else {
124
/*
125
* If we had an OPL4 chip, opl3->hardware would have been set
126
* by the OPL4 driver; so we can assume OPL3 here.
127
*/
128
if (snd_BUG_ON(!opl3->r_port))
129
return -ENODEV;
130
opl3->hardware = OPL3_HW_OPL3;
131
}
132
return 0;
133
}
134
135
/*
136
* AdLib timers
137
*/
138
139
/*
140
* Timer 1 - 80us
141
*/
142
143
static int snd_opl3_timer1_start(struct snd_timer * timer)
144
{
145
unsigned long flags;
146
unsigned char tmp;
147
unsigned int ticks;
148
struct snd_opl3 *opl3;
149
150
opl3 = snd_timer_chip(timer);
151
spin_lock_irqsave(&opl3->timer_lock, flags);
152
ticks = timer->sticks;
153
tmp = (opl3->timer_enable | OPL3_TIMER1_START) & ~OPL3_TIMER1_MASK;
154
opl3->timer_enable = tmp;
155
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 256 - ticks); /* timer 1 count */
156
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */
157
spin_unlock_irqrestore(&opl3->timer_lock, flags);
158
return 0;
159
}
160
161
static int snd_opl3_timer1_stop(struct snd_timer * timer)
162
{
163
unsigned long flags;
164
unsigned char tmp;
165
struct snd_opl3 *opl3;
166
167
opl3 = snd_timer_chip(timer);
168
spin_lock_irqsave(&opl3->timer_lock, flags);
169
tmp = (opl3->timer_enable | OPL3_TIMER1_MASK) & ~OPL3_TIMER1_START;
170
opl3->timer_enable = tmp;
171
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */
172
spin_unlock_irqrestore(&opl3->timer_lock, flags);
173
return 0;
174
}
175
176
/*
177
* Timer 2 - 320us
178
*/
179
180
static int snd_opl3_timer2_start(struct snd_timer * timer)
181
{
182
unsigned long flags;
183
unsigned char tmp;
184
unsigned int ticks;
185
struct snd_opl3 *opl3;
186
187
opl3 = snd_timer_chip(timer);
188
spin_lock_irqsave(&opl3->timer_lock, flags);
189
ticks = timer->sticks;
190
tmp = (opl3->timer_enable | OPL3_TIMER2_START) & ~OPL3_TIMER2_MASK;
191
opl3->timer_enable = tmp;
192
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER2, 256 - ticks); /* timer 1 count */
193
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */
194
spin_unlock_irqrestore(&opl3->timer_lock, flags);
195
return 0;
196
}
197
198
static int snd_opl3_timer2_stop(struct snd_timer * timer)
199
{
200
unsigned long flags;
201
unsigned char tmp;
202
struct snd_opl3 *opl3;
203
204
opl3 = snd_timer_chip(timer);
205
spin_lock_irqsave(&opl3->timer_lock, flags);
206
tmp = (opl3->timer_enable | OPL3_TIMER2_MASK) & ~OPL3_TIMER2_START;
207
opl3->timer_enable = tmp;
208
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */
209
spin_unlock_irqrestore(&opl3->timer_lock, flags);
210
return 0;
211
}
212
213
/*
214
215
*/
216
217
static const struct snd_timer_hardware snd_opl3_timer1 =
218
{
219
.flags = SNDRV_TIMER_HW_STOP,
220
.resolution = 80000,
221
.ticks = 256,
222
.start = snd_opl3_timer1_start,
223
.stop = snd_opl3_timer1_stop,
224
};
225
226
static const struct snd_timer_hardware snd_opl3_timer2 =
227
{
228
.flags = SNDRV_TIMER_HW_STOP,
229
.resolution = 320000,
230
.ticks = 256,
231
.start = snd_opl3_timer2_start,
232
.stop = snd_opl3_timer2_stop,
233
};
234
235
static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no)
236
{
237
struct snd_timer *timer = NULL;
238
struct snd_timer_id tid;
239
int err;
240
241
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
242
tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
243
tid.card = opl3->card->number;
244
tid.device = timer_no;
245
tid.subdevice = 0;
246
err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer);
247
if (err >= 0) {
248
strscpy(timer->name, "AdLib timer #1");
249
timer->private_data = opl3;
250
timer->hw = snd_opl3_timer1;
251
}
252
opl3->timer1 = timer;
253
return err;
254
}
255
256
static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no)
257
{
258
struct snd_timer *timer = NULL;
259
struct snd_timer_id tid;
260
int err;
261
262
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
263
tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
264
tid.card = opl3->card->number;
265
tid.device = timer_no;
266
tid.subdevice = 0;
267
err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer);
268
if (err >= 0) {
269
strscpy(timer->name, "AdLib timer #2");
270
timer->private_data = opl3;
271
timer->hw = snd_opl3_timer2;
272
}
273
opl3->timer2 = timer;
274
return err;
275
}
276
277
/*
278
279
*/
280
281
void snd_opl3_interrupt(struct snd_hwdep * hw)
282
{
283
unsigned char status;
284
struct snd_opl3 *opl3;
285
struct snd_timer *timer;
286
287
if (hw == NULL)
288
return;
289
290
opl3 = hw->private_data;
291
status = inb(opl3->l_port);
292
if (!(status & 0x80))
293
return;
294
295
if (status & 0x40) {
296
timer = opl3->timer1;
297
snd_timer_interrupt(timer, timer->sticks);
298
}
299
if (status & 0x20) {
300
timer = opl3->timer2;
301
snd_timer_interrupt(timer, timer->sticks);
302
}
303
}
304
305
EXPORT_SYMBOL(snd_opl3_interrupt);
306
307
/*
308
309
*/
310
311
static int snd_opl3_free(struct snd_opl3 *opl3)
312
{
313
if (snd_BUG_ON(!opl3))
314
return -ENXIO;
315
if (opl3->private_free)
316
opl3->private_free(opl3);
317
snd_opl3_clear_patches(opl3);
318
release_and_free_resource(opl3->res_l_port);
319
release_and_free_resource(opl3->res_r_port);
320
kfree(opl3);
321
return 0;
322
}
323
324
static int snd_opl3_dev_free(struct snd_device *device)
325
{
326
struct snd_opl3 *opl3 = device->device_data;
327
return snd_opl3_free(opl3);
328
}
329
330
int snd_opl3_new(struct snd_card *card,
331
unsigned short hardware,
332
struct snd_opl3 **ropl3)
333
{
334
static const struct snd_device_ops ops = {
335
.dev_free = snd_opl3_dev_free,
336
};
337
struct snd_opl3 *opl3;
338
int err;
339
340
*ropl3 = NULL;
341
opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
342
if (!opl3)
343
return -ENOMEM;
344
345
opl3->card = card;
346
opl3->hardware = hardware;
347
spin_lock_init(&opl3->reg_lock);
348
spin_lock_init(&opl3->timer_lock);
349
350
err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops);
351
if (err < 0) {
352
snd_opl3_free(opl3);
353
return err;
354
}
355
356
*ropl3 = opl3;
357
return 0;
358
}
359
360
EXPORT_SYMBOL(snd_opl3_new);
361
362
int snd_opl3_init(struct snd_opl3 *opl3)
363
{
364
if (! opl3->command) {
365
dev_err(opl3->card->dev,
366
"snd_opl3_init: command not defined!\n");
367
return -EINVAL;
368
}
369
370
opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
371
/* Melodic mode */
372
opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);
373
374
switch (opl3->hardware & OPL3_HW_MASK) {
375
case OPL3_HW_OPL2:
376
opl3->max_voices = MAX_OPL2_VOICES;
377
break;
378
case OPL3_HW_OPL3:
379
case OPL3_HW_OPL4:
380
opl3->max_voices = MAX_OPL3_VOICES;
381
/* Enter OPL3 mode */
382
opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);
383
}
384
return 0;
385
}
386
387
EXPORT_SYMBOL(snd_opl3_init);
388
389
int snd_opl3_create(struct snd_card *card,
390
unsigned long l_port,
391
unsigned long r_port,
392
unsigned short hardware,
393
int integrated,
394
struct snd_opl3 ** ropl3)
395
{
396
struct snd_opl3 *opl3;
397
int err;
398
399
*ropl3 = NULL;
400
err = snd_opl3_new(card, hardware, &opl3);
401
if (err < 0)
402
return err;
403
if (! integrated) {
404
opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");
405
if (!opl3->res_l_port) {
406
dev_err(card->dev, "opl3: can't grab left port 0x%lx\n", l_port);
407
snd_device_free(card, opl3);
408
return -EBUSY;
409
}
410
if (r_port != 0) {
411
opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
412
if (!opl3->res_r_port) {
413
dev_err(card->dev, "opl3: can't grab right port 0x%lx\n", r_port);
414
snd_device_free(card, opl3);
415
return -EBUSY;
416
}
417
}
418
}
419
opl3->l_port = l_port;
420
opl3->r_port = r_port;
421
422
switch (opl3->hardware) {
423
/* some hardware doesn't support timers */
424
case OPL3_HW_OPL3_SV:
425
case OPL3_HW_OPL3_CS:
426
case OPL3_HW_OPL3_FM801:
427
opl3->command = &snd_opl3_command;
428
break;
429
default:
430
opl3->command = &snd_opl2_command;
431
err = snd_opl3_detect(opl3);
432
if (err < 0) {
433
dev_dbg(card->dev, "OPL2/3 chip not detected at 0x%lx/0x%lx\n",
434
opl3->l_port, opl3->r_port);
435
snd_device_free(card, opl3);
436
return err;
437
}
438
/* detect routine returns correct hardware type */
439
switch (opl3->hardware & OPL3_HW_MASK) {
440
case OPL3_HW_OPL3:
441
case OPL3_HW_OPL4:
442
opl3->command = &snd_opl3_command;
443
}
444
}
445
446
snd_opl3_init(opl3);
447
448
*ropl3 = opl3;
449
return 0;
450
}
451
452
EXPORT_SYMBOL(snd_opl3_create);
453
454
int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
455
{
456
int err;
457
458
if (timer1_dev >= 0) {
459
err = snd_opl3_timer1_init(opl3, timer1_dev);
460
if (err < 0)
461
return err;
462
}
463
if (timer2_dev >= 0) {
464
err = snd_opl3_timer2_init(opl3, timer2_dev);
465
if (err < 0) {
466
snd_device_free(opl3->card, opl3->timer1);
467
opl3->timer1 = NULL;
468
return err;
469
}
470
}
471
return 0;
472
}
473
474
EXPORT_SYMBOL(snd_opl3_timer_new);
475
476
int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
477
int device, int seq_device,
478
struct snd_hwdep ** rhwdep)
479
{
480
struct snd_hwdep *hw;
481
struct snd_card *card = opl3->card;
482
int err;
483
484
if (rhwdep)
485
*rhwdep = NULL;
486
487
/* create hardware dependent device (direct FM) */
488
489
err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw);
490
if (err < 0) {
491
snd_device_free(card, opl3);
492
return err;
493
}
494
hw->private_data = opl3;
495
hw->exclusive = 1;
496
#ifdef CONFIG_SND_OSSEMUL
497
if (device == 0)
498
hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM;
499
#endif
500
strscpy(hw->name, hw->id);
501
switch (opl3->hardware & OPL3_HW_MASK) {
502
case OPL3_HW_OPL2:
503
strscpy(hw->name, "OPL2 FM");
504
hw->iface = SNDRV_HWDEP_IFACE_OPL2;
505
break;
506
case OPL3_HW_OPL3:
507
strscpy(hw->name, "OPL3 FM");
508
hw->iface = SNDRV_HWDEP_IFACE_OPL3;
509
break;
510
case OPL3_HW_OPL4:
511
strscpy(hw->name, "OPL4 FM");
512
hw->iface = SNDRV_HWDEP_IFACE_OPL4;
513
break;
514
}
515
516
/* operators - only ioctl */
517
hw->ops.open = snd_opl3_open;
518
hw->ops.ioctl = snd_opl3_ioctl;
519
hw->ops.write = snd_opl3_write;
520
hw->ops.release = snd_opl3_release;
521
522
opl3->hwdep = hw;
523
opl3->seq_dev_num = seq_device;
524
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
525
if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
526
sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {
527
strscpy(opl3->seq_dev->name, hw->name);
528
*(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;
529
}
530
#endif
531
if (rhwdep)
532
*rhwdep = hw;
533
return 0;
534
}
535
536
EXPORT_SYMBOL(snd_opl3_hwdep_new);
537
538