Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/isa/sb/sb16.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Driver for SoundBlaster 16/AWE32/AWE64 soundcards
4
* Copyright (c) by Jaroslav Kysela <[email protected]>
5
*/
6
7
#include <asm/dma.h>
8
#include <linux/init.h>
9
#include <linux/pnp.h>
10
#include <linux/err.h>
11
#include <linux/isa.h>
12
#include <linux/module.h>
13
#include <linux/string.h>
14
#include <sound/core.h>
15
#include <sound/sb.h>
16
#include <sound/sb16_csp.h>
17
#include <sound/mpu401.h>
18
#include <sound/opl3.h>
19
#include <sound/emu8000.h>
20
#include <sound/seq_device.h>
21
#define SNDRV_LEGACY_FIND_FREE_IRQ
22
#define SNDRV_LEGACY_FIND_FREE_DMA
23
#include <sound/initval.h>
24
25
MODULE_AUTHOR("Jaroslav Kysela <[email protected]>");
26
MODULE_LICENSE("GPL");
27
#ifndef SNDRV_SBAWE
28
MODULE_DESCRIPTION("Sound Blaster 16");
29
#else
30
MODULE_DESCRIPTION("Sound Blaster AWE");
31
#endif
32
33
#if 0
34
#define SNDRV_DEBUG_IRQ
35
#endif
36
37
#if defined(SNDRV_SBAWE) && IS_ENABLED(CONFIG_SND_SEQUENCER)
38
#define SNDRV_SBAWE_EMU8000
39
#endif
40
41
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
42
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
43
static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
44
#ifdef CONFIG_PNP
45
static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
46
#endif
47
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
48
static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x330,0x300 */
49
static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
50
#ifdef SNDRV_SBAWE_EMU8000
51
static long awe_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
52
#endif
53
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
54
static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
55
static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */
56
static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
57
#ifdef CONFIG_SND_SB16_CSP
58
static int csp[SNDRV_CARDS];
59
#endif
60
#ifdef SNDRV_SBAWE_EMU8000
61
static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
62
#endif
63
64
module_param_array(index, int, NULL, 0444);
65
MODULE_PARM_DESC(index, "Index value for SoundBlaster 16 soundcard.");
66
module_param_array(id, charp, NULL, 0444);
67
MODULE_PARM_DESC(id, "ID string for SoundBlaster 16 soundcard.");
68
module_param_array(enable, bool, NULL, 0444);
69
MODULE_PARM_DESC(enable, "Enable SoundBlaster 16 soundcard.");
70
#ifdef CONFIG_PNP
71
module_param_array(isapnp, bool, NULL, 0444);
72
MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
73
#endif
74
module_param_hw_array(port, long, ioport, NULL, 0444);
75
MODULE_PARM_DESC(port, "Port # for SB16 driver.");
76
module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
77
MODULE_PARM_DESC(mpu_port, "MPU-401 port # for SB16 driver.");
78
module_param_hw_array(fm_port, long, ioport, NULL, 0444);
79
MODULE_PARM_DESC(fm_port, "FM port # for SB16 PnP driver.");
80
#ifdef SNDRV_SBAWE_EMU8000
81
module_param_hw_array(awe_port, long, ioport, NULL, 0444);
82
MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver.");
83
#endif
84
module_param_hw_array(irq, int, irq, NULL, 0444);
85
MODULE_PARM_DESC(irq, "IRQ # for SB16 driver.");
86
module_param_hw_array(dma8, int, dma, NULL, 0444);
87
MODULE_PARM_DESC(dma8, "8-bit DMA # for SB16 driver.");
88
module_param_hw_array(dma16, int, dma, NULL, 0444);
89
MODULE_PARM_DESC(dma16, "16-bit DMA # for SB16 driver.");
90
module_param_array(mic_agc, int, NULL, 0444);
91
MODULE_PARM_DESC(mic_agc, "Mic Auto-Gain-Control switch.");
92
#ifdef CONFIG_SND_SB16_CSP
93
module_param_array(csp, int, NULL, 0444);
94
MODULE_PARM_DESC(csp, "ASP/CSP chip support.");
95
#endif
96
#ifdef SNDRV_SBAWE_EMU8000
97
module_param_array(seq_ports, int, NULL, 0444);
98
MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
99
#endif
100
101
#ifdef CONFIG_PNP
102
static int isa_registered;
103
static int pnp_registered;
104
#endif
105
106
struct snd_card_sb16 {
107
struct resource *fm_res; /* used to block FM i/o region for legacy cards */
108
struct snd_sb *chip;
109
#ifdef CONFIG_PNP
110
int dev_no;
111
struct pnp_dev *dev;
112
#ifdef SNDRV_SBAWE_EMU8000
113
struct pnp_dev *devwt;
114
#endif
115
#endif
116
};
117
118
#ifdef CONFIG_PNP
119
120
static const struct pnp_card_device_id snd_sb16_pnpids[] = {
121
#ifndef SNDRV_SBAWE
122
/* Sound Blaster 16 PnP */
123
{ .id = "CTL0024", .devs = { { "CTL0031" } } },
124
/* Sound Blaster 16 PnP */
125
{ .id = "CTL0025", .devs = { { "CTL0031" } } },
126
/* Sound Blaster 16 PnP */
127
{ .id = "CTL0026", .devs = { { "CTL0031" } } },
128
/* Sound Blaster 16 PnP */
129
{ .id = "CTL0027", .devs = { { "CTL0031" } } },
130
/* Sound Blaster 16 PnP */
131
{ .id = "CTL0028", .devs = { { "CTL0031" } } },
132
/* Sound Blaster 16 PnP */
133
{ .id = "CTL0029", .devs = { { "CTL0031" } } },
134
/* Sound Blaster 16 PnP */
135
{ .id = "CTL002a", .devs = { { "CTL0031" } } },
136
/* Sound Blaster 16 PnP */
137
/* Note: This card has also a CTL0051:StereoEnhance device!!! */
138
{ .id = "CTL002b", .devs = { { "CTL0031" } } },
139
/* Sound Blaster 16 PnP */
140
{ .id = "CTL002c", .devs = { { "CTL0031" } } },
141
/* Sound Blaster Vibra16S */
142
{ .id = "CTL0051", .devs = { { "CTL0001" } } },
143
/* Sound Blaster Vibra16C */
144
{ .id = "CTL0070", .devs = { { "CTL0001" } } },
145
/* Sound Blaster Vibra16CL - added by [email protected] */
146
{ .id = "CTL0080", .devs = { { "CTL0041" } } },
147
/* Sound Blaster 16 'value' PnP. It says model ct4130 on the pcb, */
148
/* but ct4131 on a sticker on the board.. */
149
{ .id = "CTL0086", .devs = { { "CTL0041" } } },
150
/* Sound Blaster Vibra16X */
151
{ .id = "CTL00f0", .devs = { { "CTL0043" } } },
152
/* Sound Blaster 16 (Virtual PC 2004) */
153
{ .id = "tBA03b0", .devs = { {.id="PNPb003" } } },
154
#else /* SNDRV_SBAWE defined */
155
/* Sound Blaster AWE 32 PnP */
156
{ .id = "CTL0035", .devs = { { "CTL0031" }, { "CTL0021" } } },
157
/* Sound Blaster AWE 32 PnP */
158
{ .id = "CTL0039", .devs = { { "CTL0031" }, { "CTL0021" } } },
159
/* Sound Blaster AWE 32 PnP */
160
{ .id = "CTL0042", .devs = { { "CTL0031" }, { "CTL0021" } } },
161
/* Sound Blaster AWE 32 PnP */
162
{ .id = "CTL0043", .devs = { { "CTL0031" }, { "CTL0021" } } },
163
/* Sound Blaster AWE 32 PnP */
164
/* Note: This card has also a CTL0051:StereoEnhance device!!! */
165
{ .id = "CTL0044", .devs = { { "CTL0031" }, { "CTL0021" } } },
166
/* Sound Blaster AWE 32 PnP */
167
/* Note: This card has also a CTL0051:StereoEnhance device!!! */
168
{ .id = "CTL0045", .devs = { { "CTL0031" }, { "CTL0021" } } },
169
/* Sound Blaster AWE 32 PnP */
170
{ .id = "CTL0046", .devs = { { "CTL0031" }, { "CTL0021" } } },
171
/* Sound Blaster AWE 32 PnP */
172
{ .id = "CTL0047", .devs = { { "CTL0031" }, { "CTL0021" } } },
173
/* Sound Blaster AWE 32 PnP */
174
{ .id = "CTL0048", .devs = { { "CTL0031" }, { "CTL0021" } } },
175
/* Sound Blaster AWE 32 PnP */
176
{ .id = "CTL0054", .devs = { { "CTL0031" }, { "CTL0021" } } },
177
/* Sound Blaster AWE 32 PnP */
178
{ .id = "CTL009a", .devs = { { "CTL0041" }, { "CTL0021" } } },
179
/* Sound Blaster AWE 32 PnP */
180
{ .id = "CTL009c", .devs = { { "CTL0041" }, { "CTL0021" } } },
181
/* Sound Blaster 32 PnP */
182
{ .id = "CTL009f", .devs = { { "CTL0041" }, { "CTL0021" } } },
183
/* Sound Blaster AWE 64 PnP */
184
{ .id = "CTL009d", .devs = { { "CTL0042" }, { "CTL0022" } } },
185
/* Sound Blaster AWE 64 PnP Gold */
186
{ .id = "CTL009e", .devs = { { "CTL0044" }, { "CTL0023" } } },
187
/* Sound Blaster AWE 64 PnP Gold */
188
{ .id = "CTL00b2", .devs = { { "CTL0044" }, { "CTL0023" } } },
189
/* Sound Blaster AWE 64 PnP */
190
{ .id = "CTL00c1", .devs = { { "CTL0042" }, { "CTL0022" } } },
191
/* Sound Blaster AWE 64 PnP */
192
{ .id = "CTL00c3", .devs = { { "CTL0045" }, { "CTL0022" } } },
193
/* Sound Blaster AWE 64 PnP */
194
{ .id = "CTL00c5", .devs = { { "CTL0045" }, { "CTL0022" } } },
195
/* Sound Blaster AWE 64 PnP */
196
{ .id = "CTL00c7", .devs = { { "CTL0045" }, { "CTL0022" } } },
197
/* Sound Blaster AWE 64 PnP */
198
{ .id = "CTL00e4", .devs = { { "CTL0045" }, { "CTL0022" } } },
199
/* Sound Blaster AWE 64 PnP */
200
{ .id = "CTL00e9", .devs = { { "CTL0045" }, { "CTL0022" } } },
201
/* Sound Blaster 16 PnP (AWE) */
202
{ .id = "CTL00ed", .devs = { { "CTL0041" }, { "CTL0070" } } },
203
/* Generic entries */
204
{ .id = "CTLXXXX" , .devs = { { "CTL0031" }, { "CTL0021" } } },
205
{ .id = "CTLXXXX" , .devs = { { "CTL0041" }, { "CTL0021" } } },
206
{ .id = "CTLXXXX" , .devs = { { "CTL0042" }, { "CTL0022" } } },
207
{ .id = "CTLXXXX" , .devs = { { "CTL0044" }, { "CTL0023" } } },
208
{ .id = "CTLXXXX" , .devs = { { "CTL0045" }, { "CTL0022" } } },
209
#endif /* SNDRV_SBAWE */
210
{ .id = "", }
211
};
212
213
MODULE_DEVICE_TABLE(pnp_card, snd_sb16_pnpids);
214
215
#endif /* CONFIG_PNP */
216
217
#ifdef SNDRV_SBAWE_EMU8000
218
#define DRIVER_NAME "snd-card-sbawe"
219
#else
220
#define DRIVER_NAME "snd-card-sb16"
221
#endif
222
223
#ifdef CONFIG_PNP
224
225
static int snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard,
226
struct pnp_card_link *card,
227
const struct pnp_card_device_id *id)
228
{
229
struct pnp_dev *pdev;
230
int err;
231
232
acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
233
if (acard->dev == NULL)
234
return -ENODEV;
235
236
#ifdef SNDRV_SBAWE_EMU8000
237
acard->devwt = pnp_request_card_device(card, id->devs[1].id, acard->dev);
238
#endif
239
/* Audio initialization */
240
pdev = acard->dev;
241
242
err = pnp_activate_dev(pdev);
243
if (err < 0) {
244
dev_err(&pdev->dev, "AUDIO pnp configure failure\n");
245
return err;
246
}
247
port[dev] = pnp_port_start(pdev, 0);
248
mpu_port[dev] = pnp_port_start(pdev, 1);
249
fm_port[dev] = pnp_port_start(pdev, 2);
250
dma8[dev] = pnp_dma(pdev, 0);
251
dma16[dev] = pnp_dma(pdev, 1);
252
irq[dev] = pnp_irq(pdev, 0);
253
dev_dbg(&pdev->dev, "pnp SB16: port=0x%lx, mpu port=0x%lx, fm port=0x%lx\n",
254
port[dev], mpu_port[dev], fm_port[dev]);
255
dev_dbg(&pdev->dev, "pnp SB16: dma1=%i, dma2=%i, irq=%i\n",
256
dma8[dev], dma16[dev], irq[dev]);
257
#ifdef SNDRV_SBAWE_EMU8000
258
/* WaveTable initialization */
259
pdev = acard->devwt;
260
if (pdev != NULL) {
261
err = pnp_activate_dev(pdev);
262
if (err < 0) {
263
goto __wt_error;
264
}
265
awe_port[dev] = pnp_port_start(pdev, 0);
266
dev_dbg(&pdev->dev, "pnp SB16: wavetable port=0x%llx\n",
267
(unsigned long long)pnp_port_start(pdev, 0));
268
} else {
269
__wt_error:
270
if (pdev) {
271
pnp_release_card_device(pdev);
272
dev_err(&pdev->dev, "WaveTable pnp configure failure\n");
273
}
274
acard->devwt = NULL;
275
awe_port[dev] = -1;
276
}
277
#endif
278
return 0;
279
}
280
281
#endif /* CONFIG_PNP */
282
283
#ifdef CONFIG_PNP
284
#define is_isapnp_selected(dev) isapnp[dev]
285
#else
286
#define is_isapnp_selected(dev) 0
287
#endif
288
289
static int snd_sb16_card_new(struct device *devptr, int dev,
290
struct snd_card **cardp)
291
{
292
struct snd_card *card;
293
int err;
294
295
err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
296
sizeof(struct snd_card_sb16), &card);
297
if (err < 0)
298
return err;
299
*cardp = card;
300
return 0;
301
}
302
303
static int snd_sb16_probe(struct snd_card *card, int dev)
304
{
305
int xirq, xdma8, xdma16;
306
struct snd_sb *chip;
307
struct snd_card_sb16 *acard = card->private_data;
308
struct snd_opl3 *opl3;
309
struct snd_hwdep *synth = NULL;
310
#ifdef CONFIG_SND_SB16_CSP
311
struct snd_hwdep *xcsp = NULL;
312
#endif
313
unsigned long flags;
314
int err;
315
316
xirq = irq[dev];
317
xdma8 = dma8[dev];
318
xdma16 = dma16[dev];
319
320
err = snd_sbdsp_create(card, port[dev], xirq, snd_sb16dsp_interrupt,
321
xdma8, xdma16, SB_HW_AUTO, &chip);
322
if (err < 0)
323
return err;
324
325
acard->chip = chip;
326
if (chip->hardware != SB_HW_16) {
327
dev_err(card->dev, "SB 16 chip was not detected at 0x%lx\n", port[dev]);
328
return -ENODEV;
329
}
330
chip->mpu_port = mpu_port[dev];
331
if (!is_isapnp_selected(dev)) {
332
err = snd_sb16dsp_configure(chip);
333
if (err < 0)
334
return err;
335
}
336
337
err = snd_sb16dsp_pcm(chip, 0);
338
if (err < 0)
339
return err;
340
341
strscpy(card->driver,
342
#ifdef SNDRV_SBAWE_EMU8000
343
awe_port[dev] > 0 ? "SB AWE" :
344
#endif
345
"SB16");
346
strscpy(card->shortname, chip->name);
347
sprintf(card->longname, "%s at 0x%lx, irq %i, dma ",
348
chip->name,
349
chip->port,
350
xirq);
351
if (xdma8 >= 0)
352
sprintf(card->longname + strlen(card->longname), "%d", xdma8);
353
if (xdma16 >= 0)
354
sprintf(card->longname + strlen(card->longname), "%s%d",
355
xdma8 >= 0 ? "&" : "", xdma16);
356
357
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
358
err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
359
chip->mpu_port,
360
MPU401_INFO_IRQ_HOOK, -1,
361
&chip->rmidi);
362
if (err < 0)
363
return err;
364
chip->rmidi_callback = snd_mpu401_uart_interrupt;
365
}
366
367
#ifdef SNDRV_SBAWE_EMU8000
368
if (awe_port[dev] == SNDRV_AUTO_PORT)
369
awe_port[dev] = 0; /* disable */
370
#endif
371
372
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
373
if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
374
OPL3_HW_OPL3,
375
acard->fm_res != NULL || fm_port[dev] == port[dev],
376
&opl3) < 0) {
377
dev_err(card->dev, "no OPL device at 0x%lx-0x%lx\n",
378
fm_port[dev], fm_port[dev] + 2);
379
} else {
380
#ifdef SNDRV_SBAWE_EMU8000
381
int seqdev = awe_port[dev] > 0 ? 2 : 1;
382
#else
383
int seqdev = 1;
384
#endif
385
err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth);
386
if (err < 0)
387
return err;
388
}
389
}
390
391
err = snd_sbmixer_new(chip);
392
if (err < 0)
393
return err;
394
395
#ifdef CONFIG_SND_SB16_CSP
396
/* CSP chip on SB16ASP/AWE32 */
397
if ((chip->hardware == SB_HW_16) && csp[dev]) {
398
snd_sb_csp_new(chip, synth != NULL ? 1 : 0, &xcsp);
399
if (xcsp) {
400
chip->csp = xcsp->private_data;
401
chip->hardware = SB_HW_16CSP;
402
} else {
403
dev_info(card->dev,
404
"warning - CSP chip not detected on soundcard #%i\n",
405
dev + 1);
406
}
407
}
408
#endif
409
#ifdef SNDRV_SBAWE_EMU8000
410
if (awe_port[dev] > 0) {
411
err = snd_emu8000_new(card, 1, awe_port[dev],
412
seq_ports[dev], NULL);
413
if (err < 0) {
414
dev_err(card->dev,
415
"fatal error - EMU-8000 synthesizer not detected at 0x%lx\n",
416
awe_port[dev]);
417
418
return err;
419
}
420
}
421
#endif
422
423
/* setup Mic AGC */
424
spin_lock_irqsave(&chip->mixer_lock, flags);
425
snd_sbmixer_write(chip, SB_DSP4_MIC_AGC,
426
(snd_sbmixer_read(chip, SB_DSP4_MIC_AGC) & 0x01) |
427
(mic_agc[dev] ? 0x00 : 0x01));
428
spin_unlock_irqrestore(&chip->mixer_lock, flags);
429
430
err = snd_card_register(card);
431
if (err < 0)
432
return err;
433
434
return 0;
435
}
436
437
#ifdef CONFIG_PM
438
static int snd_sb16_suspend(struct snd_card *card, pm_message_t state)
439
{
440
struct snd_card_sb16 *acard = card->private_data;
441
struct snd_sb *chip = acard->chip;
442
443
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
444
snd_sbmixer_suspend(chip);
445
return 0;
446
}
447
448
static int snd_sb16_resume(struct snd_card *card)
449
{
450
struct snd_card_sb16 *acard = card->private_data;
451
struct snd_sb *chip = acard->chip;
452
453
snd_sbdsp_reset(chip);
454
snd_sbmixer_resume(chip);
455
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
456
return 0;
457
}
458
#endif
459
460
static int snd_sb16_isa_probe1(int dev, struct device *pdev)
461
{
462
struct snd_card_sb16 *acard;
463
struct snd_card *card;
464
int err;
465
466
err = snd_sb16_card_new(pdev, dev, &card);
467
if (err < 0)
468
return err;
469
470
acard = card->private_data;
471
/* non-PnP FM port address is hardwired with base port address */
472
fm_port[dev] = port[dev];
473
/* block the 0x388 port to avoid PnP conflicts */
474
acard->fm_res = devm_request_region(card->dev, 0x388, 4,
475
"SoundBlaster FM");
476
#ifdef SNDRV_SBAWE_EMU8000
477
/* non-PnP AWE port address is hardwired with base port address */
478
awe_port[dev] = port[dev] + 0x400;
479
#endif
480
481
err = snd_sb16_probe(card, dev);
482
if (err < 0)
483
return err;
484
dev_set_drvdata(pdev, card);
485
return 0;
486
}
487
488
489
static int snd_sb16_isa_match(struct device *pdev, unsigned int dev)
490
{
491
return enable[dev] && !is_isapnp_selected(dev);
492
}
493
494
static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
495
{
496
int err;
497
static const int possible_irqs[] = {5, 9, 10, 7, -1};
498
static const int possible_dmas8[] = {1, 3, 0, -1};
499
static const int possible_dmas16[] = {5, 6, 7, -1};
500
501
if (irq[dev] == SNDRV_AUTO_IRQ) {
502
irq[dev] = snd_legacy_find_free_irq(possible_irqs);
503
if (irq[dev] < 0) {
504
dev_err(pdev, "unable to find a free IRQ\n");
505
return -EBUSY;
506
}
507
}
508
if (dma8[dev] == SNDRV_AUTO_DMA) {
509
dma8[dev] = snd_legacy_find_free_dma(possible_dmas8);
510
if (dma8[dev] < 0) {
511
dev_err(pdev, "unable to find a free 8-bit DMA\n");
512
return -EBUSY;
513
}
514
}
515
if (dma16[dev] == SNDRV_AUTO_DMA) {
516
dma16[dev] = snd_legacy_find_free_dma(possible_dmas16);
517
if (dma16[dev] < 0) {
518
dev_err(pdev, "unable to find a free 16-bit DMA\n");
519
return -EBUSY;
520
}
521
}
522
523
if (port[dev] != SNDRV_AUTO_PORT)
524
return snd_sb16_isa_probe1(dev, pdev);
525
else {
526
static const int possible_ports[] = {0x220, 0x240, 0x260, 0x280};
527
int i;
528
for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
529
port[dev] = possible_ports[i];
530
err = snd_sb16_isa_probe1(dev, pdev);
531
if (! err)
532
return 0;
533
}
534
return err;
535
}
536
}
537
538
#ifdef CONFIG_PM
539
static int snd_sb16_isa_suspend(struct device *dev, unsigned int n,
540
pm_message_t state)
541
{
542
return snd_sb16_suspend(dev_get_drvdata(dev), state);
543
}
544
545
static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
546
{
547
return snd_sb16_resume(dev_get_drvdata(dev));
548
}
549
#endif
550
551
#ifdef SNDRV_SBAWE
552
#define DEV_NAME "sbawe"
553
#else
554
#define DEV_NAME "sb16"
555
#endif
556
557
static struct isa_driver snd_sb16_isa_driver = {
558
.match = snd_sb16_isa_match,
559
.probe = snd_sb16_isa_probe,
560
#ifdef CONFIG_PM
561
.suspend = snd_sb16_isa_suspend,
562
.resume = snd_sb16_isa_resume,
563
#endif
564
.driver = {
565
.name = DEV_NAME
566
},
567
};
568
569
570
#ifdef CONFIG_PNP
571
static int snd_sb16_pnp_detect(struct pnp_card_link *pcard,
572
const struct pnp_card_device_id *pid)
573
{
574
static int dev;
575
struct snd_card *card;
576
int res;
577
578
for ( ; dev < SNDRV_CARDS; dev++) {
579
if (!enable[dev] || !isapnp[dev])
580
continue;
581
res = snd_sb16_card_new(&pcard->card->dev, dev, &card);
582
if (res < 0)
583
return res;
584
res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid);
585
if (res < 0)
586
return res;
587
res = snd_sb16_probe(card, dev);
588
if (res < 0)
589
return res;
590
pnp_set_card_drvdata(pcard, card);
591
dev++;
592
return 0;
593
}
594
595
return -ENODEV;
596
}
597
598
#ifdef CONFIG_PM
599
static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
600
{
601
return snd_sb16_suspend(pnp_get_card_drvdata(pcard), state);
602
}
603
static int snd_sb16_pnp_resume(struct pnp_card_link *pcard)
604
{
605
return snd_sb16_resume(pnp_get_card_drvdata(pcard));
606
}
607
#endif
608
609
static struct pnp_card_driver sb16_pnpc_driver = {
610
.flags = PNP_DRIVER_RES_DISABLE,
611
#ifdef SNDRV_SBAWE
612
.name = "sbawe",
613
#else
614
.name = "sb16",
615
#endif
616
.id_table = snd_sb16_pnpids,
617
.probe = snd_sb16_pnp_detect,
618
#ifdef CONFIG_PM
619
.suspend = snd_sb16_pnp_suspend,
620
.resume = snd_sb16_pnp_resume,
621
#endif
622
};
623
624
#endif /* CONFIG_PNP */
625
626
static int __init alsa_card_sb16_init(void)
627
{
628
int err;
629
630
err = isa_register_driver(&snd_sb16_isa_driver, SNDRV_CARDS);
631
#ifdef CONFIG_PNP
632
if (!err)
633
isa_registered = 1;
634
635
err = pnp_register_card_driver(&sb16_pnpc_driver);
636
if (!err)
637
pnp_registered = 1;
638
639
if (isa_registered)
640
err = 0;
641
#endif
642
return err;
643
}
644
645
static void __exit alsa_card_sb16_exit(void)
646
{
647
#ifdef CONFIG_PNP
648
if (pnp_registered)
649
pnp_unregister_card_driver(&sb16_pnpc_driver);
650
if (isa_registered)
651
#endif
652
isa_unregister_driver(&snd_sb16_isa_driver);
653
}
654
655
module_init(alsa_card_sb16_init)
656
module_exit(alsa_card_sb16_exit)
657
658