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

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

initial import

File size: 11.6 KB
Line 
1
2/*
3 card-dt0197h.c - driver for Diamond Technologies DT-0197H based soundcards.
4 Copyright (C) 1999 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/mpu401.h>
26#include <sound/opl3.h>
27#include <sound/sb.h>
28
29#define chip_t sb_t
30
31EXPORT_NO_SYMBOLS;
32MODULE_DESCRIPTION("Diamond Technologies DT-0197H");
33MODULE_CLASSES("{sound}");
34MODULE_DEVICES("{{Diamond Technologies,DT-0197H}}");
35
36static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
37static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
38static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
39static long snd_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
40static long snd_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
41static long snd_fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
42static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */
43static int snd_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */
44static int snd_dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */
45
46MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
47MODULE_PARM_DESC(snd_index, "Index value for dt0197h based soundcard.");
48MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);
49MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
50MODULE_PARM_DESC(snd_id, "ID string for dt0197h based soundcard.");
51MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);
52MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
53MODULE_PARM_DESC(snd_enable, "Enable dt0197h based soundcard.");
54MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
55MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
56MODULE_PARM_DESC(snd_port, "Port # for dt0197h driver.");
57MODULE_PARM_SYNTAX(snd_port, SNDRV_PORT12_DESC);
58MODULE_PARM(snd_mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
59MODULE_PARM_DESC(snd_mpu_port, "MPU-401 port # for dt0197h driver.");
60MODULE_PARM_SYNTAX(snd_mpu_port, SNDRV_PORT12_DESC);
61MODULE_PARM(snd_fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
62MODULE_PARM_DESC(snd_fm_port, "FM port # for dt0197h driver.");
63MODULE_PARM_SYNTAX(snd_fm_port, SNDRV_PORT12_DESC);
64MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
65MODULE_PARM_DESC(snd_irq, "IRQ # for dt0197h driver.");
66MODULE_PARM_SYNTAX(snd_irq, SNDRV_IRQ_DESC);
67MODULE_PARM(snd_mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
68MODULE_PARM_DESC(snd_mpu_irq, "MPU-401 IRQ # for dt0197h driver.");
69MODULE_PARM_SYNTAX(snd_mpu_irq, SNDRV_IRQ_DESC);
70MODULE_PARM(snd_dma8, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
71MODULE_PARM_DESC(snd_dma8, "8-bit DMA # for dt0197h driver.");
72MODULE_PARM_SYNTAX(snd_dma8, SNDRV_DMA8_DESC);
73
74struct snd_card_dt0197h {
75#ifdef __ISAPNP__
76 struct isapnp_dev *dev;
77 struct isapnp_dev *devmpu;
78 struct isapnp_dev *devopl;
79#endif /* __ISAPNP__ */
80};
81
82static snd_card_t *snd_dt0197h_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
83
84#ifdef __ISAPNP__
85static struct isapnp_card *snd_dt0197h_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
86static const struct isapnp_card_id *snd_dt0197h_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
87
88static struct isapnp_card_id snd_dt0197h_pnpids[] __devinitdata = {
89 /* DT197A30 */
90 {
91#ifdef TARGET_OS2
92 0, ISAPNP_CARD_ID('R','W','B',0x1688),
93 { ISAPNP_DEVICE_ID('@','@','@',0x1688),
94 ISAPNP_DEVICE_ID('@','X','@',0x0001),
95 ISAPNP_DEVICE_ID('@','H','@',0x0001) }
96#else
97 ISAPNP_CARD_ID('R','W','B',0x1688),
98 devs: { ISAPNP_DEVICE_ID('@','@','@',0x1688),
99 ISAPNP_DEVICE_ID('@','X','@',0x0001),
100 ISAPNP_DEVICE_ID('@','H','@',0x0001) }
101#endif
102 },
103 { ISAPNP_CARD_END, }
104};
105
106ISAPNP_CARD_TABLE(snd_dt0197h_pnpids);
107
108#endif /* __ISAPNP__ */
109
110#define DRIVER_NAME "snd-card-dt0197h"
111
112
113#ifdef __ISAPNP__
114static int __init snd_card_dt0197h_isapnp(int dev, struct snd_card_dt0197h *acard)
115{
116 const struct isapnp_card_id *id = snd_dt0197h_isapnp_id[dev];
117 struct isapnp_card *card = snd_dt0197h_isapnp_cards[dev];
118 struct isapnp_dev *pdev;
119
120 acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
121 if (acard->dev->active) {
122 acard->dev = NULL;
123 return -EBUSY;
124 }
125 acard->devmpu = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
126 if (acard->devmpu->active) {
127 acard->dev = acard->devmpu = NULL;
128 return -EBUSY;
129 }
130 acard->devopl = isapnp_find_dev(card, id->devs[2].vendor, id->devs[2].function, NULL);
131 if (acard->devopl->active) {
132 acard->dev = acard->devmpu = acard->devopl = NULL;
133 return -EBUSY;
134 }
135
136 pdev = acard->dev;
137 if (pdev->prepare(pdev)<0)
138 return -EAGAIN;
139
140 if (snd_port[dev] != SNDRV_AUTO_PORT)
141 isapnp_resource_change(&pdev->resource[0], snd_port[dev], 16);
142 if (snd_dma8[dev] != SNDRV_AUTO_DMA)
143 isapnp_resource_change(&pdev->dma_resource[0], snd_dma8[dev],
144 1);
145 if (snd_irq[dev] != SNDRV_AUTO_IRQ)
146 isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
147
148 if (pdev->activate(pdev)<0) {
149 snd_printk("AUDIO isapnp configure failure\n");
150 return -EBUSY;
151 }
152
153 snd_port[dev] = pdev->resource[0].start;
154 snd_dma8[dev] = pdev->dma_resource[0].start;
155 snd_irq[dev] = pdev->irq_resource[0].start;
156
157 pdev = acard->devmpu;
158 if (pdev || pdev->prepare(pdev)<0)
159 return 0;
160
161 if (snd_mpu_port[dev] != SNDRV_AUTO_PORT)
162 isapnp_resource_change(&pdev->resource[0], snd_mpu_port[dev],
163 2);
164 if (snd_mpu_irq[dev] != SNDRV_AUTO_IRQ)
165 isapnp_resource_change(&pdev->irq_resource[0], snd_mpu_irq[dev],
166 1);
167
168 if (pdev->activate(pdev)<0) {
169 snd_printk("MPU-401 isapnp configure failure\n");
170 snd_mpu_port[dev] = -1;
171 acard->devmpu = NULL;
172 } else {
173 snd_mpu_port[dev] = pdev->resource[0].start;
174 snd_mpu_irq[dev] = pdev->irq_resource[0].start;
175 }
176
177 pdev = acard->devopl;
178 if (pdev == NULL || pdev->prepare(pdev)<0)
179 return 0;
180
181 if (snd_fm_port[dev] != SNDRV_AUTO_PORT)
182 isapnp_resource_change(&pdev->resource[0], snd_fm_port[dev], 4);
183
184 if (pdev->activate(pdev)<0) {
185 snd_printk("OPL isapnp configure failure\n");
186 snd_fm_port[dev] = -1;
187 acard->devopl = NULL;
188 } else {
189 snd_fm_port[dev] = pdev->resource[0].start;
190 }
191
192 return 0;
193}
194
195static void snd_card_dt0197h_deactivate(struct snd_card_dt0197h *acard)
196{
197 if (acard->dev) {
198 acard->dev->deactivate(acard->dev);
199 acard->dev = NULL;
200 }
201 if (acard->devmpu) {
202 acard->devmpu->deactivate(acard->devmpu);
203 acard->devmpu = NULL;
204 }
205 if (acard->devopl) {
206 acard->devopl->deactivate(acard->devopl);
207 acard->devopl = NULL;
208 }
209}
210#endif /* __ISAPNP__ */
211
212static void snd_card_dt0197h_free(snd_card_t *card)
213{
214 struct snd_card_dt0197h *acard = (struct snd_card_dt0197h *)card->private_data;
215
216 if (acard != NULL) {
217#ifdef __ISAPNP__
218 snd_card_dt0197h_deactivate(acard);
219#endif /* __ISAPNP__ */
220 }
221}
222
223static int __init snd_card_dt0197h_probe(int dev)
224{
225 int error;
226 sb_t *chip;
227 snd_card_t *card;
228 struct snd_card_dt0197h *acard;
229 opl3_t *opl3;
230
231 if ((card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE,
232 sizeof(struct snd_card_dt0197h))) == NULL)
233 return -ENOMEM;
234 acard = (struct snd_card_dt0197h *)card->private_data;
235 card->private_free = snd_card_dt0197h_free;
236
237#ifdef __ISAPNP__
238 if ((error = snd_card_dt0197h_isapnp(dev, acard))) {
239 snd_card_free(card);
240 return error;
241 }
242#else
243 snd_printk("you have to enable PnP support ...\n");
244 snd_card_free(card);
245 return -ENOSYS;
246#endif /* __ISAPNP__ */
247
248 if ((error = snd_sbdsp_create(card, snd_port[dev],
249 snd_irq[dev],
250 snd_sb16dsp_interrupt,
251 snd_dma8[dev],
252 -1,
253 SB_HW_AUTO,
254 &chip)) < 0) {
255 snd_card_free(card);
256 return error;
257 }
258
259 if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) {
260 snd_card_free(card);
261 return error;
262 }
263 if ((error = snd_sbmixer_new(chip)) < 0) {
264 snd_card_free(card);
265 return error;
266 }
267
268 if (snd_mpu_port[dev] > 0) {
269 if (snd_mpu401_uart_new(card, 0,
270 MPU401_HW_MPU401,
271 snd_mpu_port[dev], 0,
272 snd_mpu_irq[dev],
273 SA_INTERRUPT,
274 NULL) < 0)
275 snd_printk("no MPU-401 device at 0x%lx ?\n",
276 snd_mpu_port[dev]);
277 }
278
279 if (snd_fm_port[dev] > 0) {
280 if (snd_opl3_create(card,
281 snd_fm_port[dev],
282 snd_fm_port[dev] + 2,
283 OPL3_HW_AUTO, 0, &opl3) < 0) {
284 snd_printk("no OPL device at 0x%lx-0x%lx ?\n",
285 snd_fm_port[dev], snd_fm_port[dev] + 2);
286 } else {
287 if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) {
288 snd_card_free(card);
289 return error;
290 }
291 if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
292 snd_card_free(card);
293 return error;
294 }
295 }
296 }
297
298 strcpy(card->driver, "DT-0197H");
299 strcpy(card->shortname, "Diamond Tech. DT-0197H");
300 sprintf(card->longname, "%s soundcard, %s at 0x%lx, irq %d, dma %d",
301 card->shortname, chip->name, chip->port,
302 snd_irq[dev], snd_dma8[dev]);
303 if ((error = snd_card_register(card)) < 0) {
304 snd_card_free(card);
305 return error;
306 }
307 snd_dt0197h_cards[dev] = card;
308 return 0;
309}
310
311#ifdef __ISAPNP__
312static int __init snd_dt0197h_isapnp_detect(struct isapnp_card *card,
313 const struct isapnp_card_id *id)
314{
315 static int dev = 0;
316 int res;
317
318 for ( ; dev < SNDRV_CARDS; dev++) {
319 if (!snd_enable[dev])
320 continue;
321 snd_dt0197h_isapnp_cards[dev] = card;
322 snd_dt0197h_isapnp_id[dev] = id;
323 res = snd_card_dt0197h_probe(dev);
324 if (res < 0)
325 return res;
326 dev++;
327 return 0;
328 }
329 return -ENODEV;
330}
331#endif /* __ISAPNP__ */
332
333static int __init alsa_card_dt0197h_init(void)
334{
335 int cards = 0;
336
337#ifdef __ISAPNP__
338 cards += isapnp_probe_cards(snd_dt0197h_pnpids, snd_dt0197h_isapnp_detect);
339#else
340 snd_printk("you have to enable ISA PnP support.\n");
341#endif
342#ifdef MODULE
343 if (!cards)
344 snd_printk("no DT-0197H based soundcards found\n");
345#endif
346 return cards ? 0 : -ENODEV;
347}
348
349static void __exit alsa_card_dt0197h_exit(void)
350{
351 int dev;
352
353 for (dev = 0; dev < SNDRV_CARDS; dev++)
354 snd_card_free(snd_dt0197h_cards[dev]);
355}
356
357module_init(alsa_card_dt0197h_init)
358module_exit(alsa_card_dt0197h_exit)
359
360#ifndef MODULE
361
362/* format is: snd-card-dt0197h=snd_enable,snd_index,snd_id,snd_isapnp,
363 snd_port,snd_mpu_port,snd_fm_port,
364 snd_irq,snd_mpu_irq,snd_dma8,snd_dma8_size */
365
366static int __init alsa_card_dt0197h_setup(char *str)
367{
368 static unsigned __initdata nr_dev = 0;
369
370 if (nr_dev >= SNDRV_CARDS)
371 return 0;
372 (void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&
373 get_option(&str,&snd_index[nr_dev]) == 2 &&
374 get_id(&str,&snd_id[nr_dev]) == 2 &&
375 get_option(&str,(int *)&snd_port[nr_dev]) == 2 &&
376 get_option(&str,(int *)&snd_mpu_port[nr_dev]) == 2 &&
377 get_option(&str,(int *)&snd_fm_port[nr_dev]) == 2 &&
378 get_option(&str,&snd_irq[nr_dev]) == 2 &&
379 get_option(&str,&snd_mpu_irq[nr_dev]) == 2 &&
380 get_option(&str,&snd_dma8[nr_dev]) == 2);
381 nr_dev++;
382 return 1;
383}
384
385__setup("snd-card-dt0197h=", alsa_card_dt0197h_setup);
386
387#endif /* ifndef MODULE */
Note: See TracBrowser for help on using the repository browser.