source: GPL/alsa-kernel/isa/ad1816a/ad1816a.c@ 1

Last change on this file since 1 was 1, checked in by vladest, 20 years ago

initial import

File size: 12.4 KB
Line 
1
2/*
3 card-ad1816a.c - driver for ADI SoundPort AD1816A based soundcards.
4 Copyright (C) 2000 by Massimo Piccioni <dafastidio@libero.it>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#define SNDRV_MAIN_OBJECT_FILE
22#include <sound/driver.h>
23#define SNDRV_GET_ID
24#include <sound/initval.h>
25#include <sound/ad1816a.h>
26#include <sound/mpu401.h>
27#include <sound/opl3.h>
28
29#define chip_t ad1816a_t
30
31EXPORT_NO_SYMBOLS;
32MODULE_DESCRIPTION("AD1816A, AD1815");
33MODULE_CLASSES("{sound}");
34MODULE_DEVICES("{{Highscreen,Sound-Boostar 16 3D},"
35 "{Analog Devices,AD1815},"
36 "{Analog Devices,AD1816A},"
37 "{TerraTec,Base 64},"
38 "{Aztech/Newcom SC-16 3D}}");
39
40static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */
41static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
42static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
43static long snd_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
44static long snd_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
45static long snd_fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
46static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
47static int snd_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */
48static int snd_dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
49static int snd_dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
50
51MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
52MODULE_PARM_DESC(snd_index, "Index value for ad1816a based soundcard.");
53MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);
54MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
55MODULE_PARM_DESC(snd_id, "ID string for ad1816a based soundcard.");
56MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);
57MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
58MODULE_PARM_DESC(snd_enable, "Enable ad1816a based soundcard.");
59MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
60MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
61MODULE_PARM_DESC(snd_port, "Port # for ad1816a driver.");
62MODULE_PARM_SYNTAX(snd_port, SNDRV_PORT12_DESC);
63MODULE_PARM(snd_mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
64MODULE_PARM_DESC(snd_mpu_port, "MPU-401 port # for ad1816a driver.");
65MODULE_PARM_SYNTAX(snd_mpu_port, SNDRV_PORT12_DESC);
66MODULE_PARM(snd_fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
67MODULE_PARM_DESC(snd_fm_port, "FM port # for ad1816a driver.");
68MODULE_PARM_SYNTAX(snd_fm_port, SNDRV_PORT12_DESC);
69MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
70MODULE_PARM_DESC(snd_irq, "IRQ # for ad1816a driver.");
71MODULE_PARM_SYNTAX(snd_irq, SNDRV_IRQ_DESC);
72MODULE_PARM(snd_mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
73MODULE_PARM_DESC(snd_mpu_irq, "MPU-401 IRQ # for ad1816a driver.");
74MODULE_PARM_SYNTAX(snd_mpu_irq, SNDRV_IRQ_DESC);
75MODULE_PARM(snd_dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
76MODULE_PARM_DESC(snd_dma1, "1st DMA # for ad1816a driver.");
77MODULE_PARM_SYNTAX(snd_dma1, SNDRV_DMA_DESC);
78MODULE_PARM(snd_dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
79MODULE_PARM_DESC(snd_dma2, "2nd DMA # for ad1816a driver.");
80MODULE_PARM_SYNTAX(snd_dma2, SNDRV_DMA_DESC);
81
82struct snd_card_ad1816a {
83#ifdef __ISAPNP__
84 struct isapnp_dev *dev;
85 struct isapnp_dev *devmpu;
86#endif /* __ISAPNP__ */
87};
88
89static snd_card_t *snd_ad1816a_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
90
91#ifdef __ISAPNP__
92
93static struct isapnp_card *snd_ad1816a_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
94static const struct isapnp_card_id *snd_ad1816a_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
95
96#ifdef TARGET_OS2
97#define ISAPNP_AD1816A(_va, _vb, _vc, _device, _fa, _fb, _fc, _audio, _mpu401) \
98 { \
99 0, ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
100 { ISAPNP_DEVICE_ID(_fa, _fb, _fc, _audio), \
101 ISAPNP_DEVICE_ID(_fa, _fb, _fc, _mpu401), } \
102 }
103#else
104#define ISAPNP_AD1816A(_va, _vb, _vc, _device, _fa, _fb, _fc, _audio, _mpu401) \
105 { \
106 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
107 devs : { ISAPNP_DEVICE_ID(_fa, _fb, _fc, _audio), \
108 ISAPNP_DEVICE_ID(_fa, _fb, _fc, _mpu401), } \
109 }
110#endif
111
112static struct isapnp_card_id snd_ad1816a_pnpids[] __devinitdata = {
113 /* Highscreen Sound-Boostar 16 3D */
114 ISAPNP_AD1816A('M','D','K',0x1605,'A','D','S',0x7180,0x7181),
115 /* Highscreen Sound-Boostar 16 3D - added by Stefan Behnel */
116 ISAPNP_AD1816A('L','W','C',0x1061,'A','D','S',0x7180,0x7181),
117 /* Analog Devices AD1815 */
118 ISAPNP_AD1816A('A','D','S',0x7150,'A','D','S',0x7150,0x7151),
119 /* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */
120 ISAPNP_AD1816A('A','D','S',0x7181,'A','D','S',0x7180,0x7181),
121 /* Analog Devices AD1816A - Terratec Base 64 */
122 ISAPNP_AD1816A('T','E','R',0x1411,'A','D','S',0x7180,0x7181),
123 /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */
124 ISAPNP_AD1816A('A','Z','T',0x1022,'A','Z','T',0x1018,0x2002),
125 { ISAPNP_CARD_END, }
126};
127
128ISAPNP_CARD_TABLE(snd_ad1816a_pnpids);
129
130#endif /* __ISAPNP__ */
131
132#define DRIVER_NAME "snd-card-ad1816a"
133
134
135#ifdef __ISAPNP__
136static int __init snd_card_ad1816a_isapnp(int dev,
137 struct snd_card_ad1816a *acard)
138{
139 const struct isapnp_card_id *id = snd_ad1816a_isapnp_id[dev];
140 struct isapnp_card *card = snd_ad1816a_isapnp_cards[dev];
141 struct isapnp_dev *pdev;
142
143 acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
144 if (acard->dev->active) {
145 acard->dev = NULL;
146 return -EBUSY;
147 }
148 acard->devmpu = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
149 if (acard->devmpu->active) {
150 acard->dev = acard->devmpu = NULL;
151 return -EBUSY;
152 }
153
154 pdev = acard->dev;
155 if (pdev->prepare(pdev) < 0)
156 return -EAGAIN;
157
158 if (snd_port[dev] != SNDRV_AUTO_PORT)
159 isapnp_resource_change(&pdev->resource[2], snd_port[dev], 16);
160 if (snd_fm_port[dev] != SNDRV_AUTO_PORT)
161 isapnp_resource_change(&pdev->resource[1], snd_fm_port[dev], 4);
162 if (snd_dma1[dev] != SNDRV_AUTO_DMA)
163 isapnp_resource_change(&pdev->dma_resource[0], snd_dma1[dev],
164 1);
165 if (snd_dma2[dev] != SNDRV_AUTO_DMA)
166 isapnp_resource_change(&pdev->dma_resource[1], snd_dma2[dev],
167 1);
168 if (snd_irq[dev] != SNDRV_AUTO_IRQ)
169 isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
170
171 if (pdev->activate(pdev) < 0) {
172 snd_printk("AUDIO isapnp configure failure\n");
173 return -EBUSY;
174 }
175
176 snd_port[dev] = pdev->resource[2].start;
177 snd_fm_port[dev] = pdev->resource[1].start;
178 snd_dma1[dev] = pdev->dma_resource[0].start;
179 snd_dma2[dev] = pdev->dma_resource[1].start;
180 snd_irq[dev] = pdev->irq_resource[0].start;
181
182 pdev = acard->devmpu;
183 if (pdev == NULL || pdev->prepare(pdev) < 0) {
184 snd_mpu_port[dev] = -1;
185 acard->devmpu = NULL;
186 return 0;
187 }
188
189 if (snd_mpu_port[dev] != SNDRV_AUTO_PORT)
190 isapnp_resource_change(&pdev->resource[0], snd_mpu_port[dev],
191 2);
192 if (snd_mpu_irq[dev] != SNDRV_AUTO_IRQ)
193 isapnp_resource_change(&pdev->irq_resource[0], snd_mpu_irq[dev],
194 1);
195
196 if (pdev->activate(pdev) < 0) {
197 /* not fatal error */
198 snd_printk("MPU-401 isapnp configure failure\n");
199 snd_mpu_port[dev] = -1;
200 acard->devmpu = NULL;
201 } else {
202 snd_mpu_port[dev] = pdev->resource[0].start;
203 snd_mpu_irq[dev] = pdev->irq_resource[0].start;
204 }
205
206 return 0;
207}
208
209static void snd_card_ad1816a_deactivate(struct snd_card_ad1816a *acard)
210{
211 if (acard->dev) {
212 acard->dev->deactivate(acard->dev);
213 acard->dev = NULL;
214 }
215 if (acard->devmpu) {
216 acard->devmpu->deactivate(acard->devmpu);
217 acard->devmpu = NULL;
218 }
219}
220#endif /* __ISAPNP__ */
221
222static void snd_card_ad1816a_free(snd_card_t *card)
223{
224 struct snd_card_ad1816a *acard = (struct snd_card_ad1816a *)card->private_data;
225
226 if (acard) {
227#ifdef __ISAPNP__
228 snd_card_ad1816a_deactivate(acard);
229#endif /* __ISAPNP__ */
230 }
231}
232
233static int __init snd_card_ad1816a_probe(int dev)
234{
235 int error;
236 snd_card_t *card;
237 struct snd_card_ad1816a *acard;
238 ad1816a_t *chip;
239 opl3_t *opl3;
240
241 if ((card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE,
242 sizeof(struct snd_card_ad1816a))) == NULL)
243 return -ENOMEM;
244 acard = (struct snd_card_ad1816a *)card->private_data;
245 card->private_free = snd_card_ad1816a_free;
246
247#ifdef __ISAPNP__
248 if ((error = snd_card_ad1816a_isapnp(dev, acard))) {
249 snd_card_free(card);
250 return error;
251 }
252#else
253 snd_printk("you have to enable ISA PnP support.\n");
254 return -ENOSYS;
255#endif /* __ISAPNP__ */
256
257 if ((error = snd_ad1816a_create(card, snd_port[dev],
258 snd_irq[dev],
259 snd_dma1[dev],
260 snd_dma2[dev],
261 &chip)) < 0) {
262 snd_card_free(card);
263 return error;
264 }
265
266 if ((error = snd_ad1816a_pcm(chip, 0, NULL)) < 0) {
267 snd_card_free(card);
268 return error;
269 }
270
271 if ((error = snd_ad1816a_mixer(chip)) < 0) {
272 snd_card_free(card);
273 return error;
274 }
275
276 if (snd_mpu_port[dev] > 0) {
277 if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
278 snd_mpu_port[dev], 0, snd_mpu_irq[dev], SA_INTERRUPT,
279 NULL) < 0)
280 snd_printk("no MPU-401 device at 0x%lx.\n", snd_mpu_port[dev]);
281 }
282
283 if (snd_fm_port[dev] > 0) {
284 if (snd_opl3_create(card,
285 snd_fm_port[dev], snd_fm_port[dev] + 2,
286 OPL3_HW_AUTO, 0, &opl3) < 0) {
287 snd_printk("no OPL device at 0x%lx-0x%lx.\n", snd_fm_port[dev], snd_fm_port[dev] + 2);
288 } else {
289 if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) {
290 snd_card_free(card);
291 return error;
292 }
293 if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
294 snd_card_free(card);
295 return error;
296 }
297 }
298 }
299
300 strcpy(card->driver, "AD1816A");
301 strcpy(card->shortname, "ADI SoundPort AD1816A");
302 sprintf(card->longname, "%s soundcard, SS at 0x%lx, irq %d, dma %d&%d",
303 card->shortname, chip->port, snd_irq[dev], snd_dma1[dev], snd_dma2[dev]);
304
305 if ((error = snd_card_register(card)) < 0) {
306 snd_card_free(card);
307 return error;
308 }
309 snd_ad1816a_cards[dev] = card;
310 return 0;
311}
312
313#ifdef __ISAPNP__
314static int __init snd_ad1816a_isapnp_detect(struct isapnp_card *card,
315 const struct isapnp_card_id *id)
316{
317 static int dev = 0;
318 int res;
319
320 for ( ; dev < SNDRV_CARDS; dev++) {
321 if (!snd_enable[dev])
322 continue;
323 snd_ad1816a_isapnp_cards[dev] = card;
324 snd_ad1816a_isapnp_id[dev] = id;
325 res = snd_card_ad1816a_probe(dev);
326 if (res < 0)
327 return res;
328 dev++;
329 return 0;
330 }
331 return -ENODEV;
332}
333#endif
334
335static int __init alsa_card_ad1816a_init(void)
336{
337 int cards = 0;
338
339#ifdef __ISAPNP__
340 cards += isapnp_probe_cards(snd_ad1816a_pnpids, snd_ad1816a_isapnp_detect);
341#else
342 snd_printk("you have to enable ISA PnP support.\n");
343#endif
344#ifdef MODULE
345 if (!cards)
346 snd_printk("no AD1816A based soundcards found.\n");
347#endif /* MODULE */
348 return cards ? 0 : -ENODEV;
349}
350
351static void __exit alsa_card_ad1816a_exit(void)
352{
353 int dev;
354
355 for (dev = 0; dev < SNDRV_CARDS; dev++)
356 snd_card_free(snd_ad1816a_cards[dev]);
357}
358
359module_init(alsa_card_ad1816a_init)
360module_exit(alsa_card_ad1816a_exit)
361
362#ifndef MODULE
363
364/* format is: snd-card-ad1816a=snd_enable,snd_index,snd_id,snd_port,
365 snd_mpu_port,snd_fm_port,snd_irq,snd_mpu_irq,
366 snd_dma1,snd_dma2 */
367
368static int __init alsa_card_ad1816a_setup(char *str)
369{
370 static unsigned __initdata nr_dev = 0;
371
372 if (nr_dev >= SNDRV_CARDS)
373 return 0;
374 (void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&
375 get_option(&str,&snd_index[nr_dev]) == 2 &&
376 get_id(&str,&snd_id[nr_dev]) == 2 &&
377 get_option(&str,(int *)&snd_port[nr_dev]) == 2 &&
378 get_option(&str,(int *)&snd_mpu_port[nr_dev]) == 2 &&
379 get_option(&str,(int *)&snd_fm_port[nr_dev]) == 2 &&
380 get_option(&str,&snd_irq[nr_dev]) == 2 &&
381 get_option(&str,&snd_mpu_irq[nr_dev]) == 2 &&
382 get_option(&str,&snd_dma1[nr_dev]) == 2 &&
383 get_option(&str,&snd_dma2[nr_dev]) == 2);
384 nr_dev++;
385 return 1;
386}
387
388__setup("snd-card-ad1816a=", alsa_card_ad1816a_setup);
389
390#endif /* ifndef MODULE */
Note: See TracBrowser for help on using the repository browser.