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

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

initial import

File size: 21.6 KB
Line 
1/*
2 * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
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
22#define SNDRV_MAIN_OBJECT_FILE
23#include <sound/driver.h>
24#include <sound/cs4231.h>
25#include <sound/mpu401.h>
26#include <sound/opl3.h>
27#define SNDRV_GET_ID
28#include <sound/initval.h>
29
30#define chip_t cs4231_t
31
32EXPORT_NO_SYMBOLS;
33#ifdef CS4232
34MODULE_DESCRIPTION("Cirrus Logic CS4232");
35MODULE_CLASSES("{sound}");
36MODULE_DEVICES("{{Turtle Beach,TBS-2000},"
37 "{Turtle Beach,Tropez Plus},"
38 "{SIC CrystalWave 32},"
39 "{HP,Omnibook 5500}},"
40 "{TerraTec,Maestro 32/96}");
41#else
42MODULE_DESCRIPTION("Cirrus Logic CS4235-9");
43MODULE_CLASSES("{sound}");
44MODULE_DEVICES("{{Crystal Semiconductors,CS4235},"
45 "{Crystal Semiconductors,CS4236},"
46 "{Crystal Semiconductors,CS4237},"
47 "{Crystal Semiconductors,CS4238},"
48 "{Crystal Semiconductors,CS4239},"
49 "{Genius,Sound Maker 3DJ},"
50 "{Hewlett Packard,HP6330 sound},"
51 "{Crystal Computer,TidalWave128},"
52 "{Acer,AW37},"
53 "{EliteGroup,P5TX-LA sound},"
54 "{Crystal,3D},"
55 "{Typhoon Soundsystem,CS4236B},"
56 "{TerraTec, AudioSystem EWS64XL},"
57 "{NewClear,3D},"
58 "{Dell,Optiplex GX1},"
59 "{Dell,Workstation 400 sound},"
60 "{Turtle Beach,Malibu},"
61 "{Crystal Semiconductors,CS4235},"
62 "{IBM,Adaptiva 2137 E24},"
63 "{Maxi Sound,16 PnP},"
64 "{Gallant,SC-70P},"
65 "{Acer,AW37/Pro},"
66 "{Acer,AW35/Pro},"
67 "{Intel, Marlin Spike Mobo CS4235},"
68 "{IBM,IntelliStation M Pro}}");
69#endif
70
71#ifdef CS4232
72#define IDENT "CS4232"
73#else
74#define IDENT "CS4236+"
75#endif
76
77static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
78static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
79static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
80#ifdef __ISAPNP__
81#ifdef TARGET_OS2
82static int snd_isapnp[SNDRV_CARDS] = {1,1,1,1,1,1,1,1};
83#else
84static int snd_isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
85#endif
86#endif
87static long snd_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
88static long snd_cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
89static long snd_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */
90static long snd_fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
91static long snd_sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
92static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
93static int snd_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */
94static int snd_dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
95static int snd_dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
96
97MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
98MODULE_PARM_DESC(snd_index, "Index value for " IDENT " soundcard.");
99MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);
100MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
101MODULE_PARM_DESC(snd_id, "ID string for " IDENT " soundcard.");
102MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);
103MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
104MODULE_PARM_DESC(snd_enable, "Enable " IDENT " soundcard.");
105MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
106#ifdef __ISAPNP__
107MODULE_PARM(snd_isapnp, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
108MODULE_PARM_DESC(snd_isapnp, "ISA PnP detection for specified soundcard.");
109MODULE_PARM_SYNTAX(snd_isapnp, SNDRV_ISAPNP_DESC);
110#endif
111MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
112MODULE_PARM_DESC(snd_port, "Port # for " IDENT " driver.");
113MODULE_PARM_SYNTAX(snd_port, SNDRV_PORT12_DESC);
114MODULE_PARM(snd_cport, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
115MODULE_PARM_DESC(snd_cport, "Control port # for " IDENT " driver.");
116MODULE_PARM_SYNTAX(snd_cport, SNDRV_PORT12_DESC);
117MODULE_PARM(snd_mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
118MODULE_PARM_DESC(snd_mpu_port, "MPU-401 port # for " IDENT " driver.");
119MODULE_PARM_SYNTAX(snd_mpu_port, SNDRV_PORT12_DESC);
120MODULE_PARM(snd_fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
121MODULE_PARM_DESC(snd_fm_port, "FM port # for " IDENT " driver.");
122MODULE_PARM_SYNTAX(snd_fm_port, SNDRV_PORT12_DESC);
123MODULE_PARM(snd_sb_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
124MODULE_PARM_DESC(snd_sb_port, "SB port # for " IDENT " driver (optional).");
125MODULE_PARM_SYNTAX(snd_sb_port, SNDRV_PORT12_DESC);
126MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
127MODULE_PARM_DESC(snd_irq, "IRQ # for " IDENT " driver.");
128MODULE_PARM_SYNTAX(snd_irq, SNDRV_IRQ_DESC);
129MODULE_PARM(snd_mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
130MODULE_PARM_DESC(snd_mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
131MODULE_PARM_SYNTAX(snd_mpu_irq, SNDRV_IRQ_DESC);
132MODULE_PARM(snd_dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
133MODULE_PARM_DESC(snd_dma1, "DMA1 # for " IDENT " driver.");
134MODULE_PARM_SYNTAX(snd_dma1, SNDRV_DMA_DESC);
135MODULE_PARM(snd_dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
136MODULE_PARM_DESC(snd_dma2, "DMA2 # for " IDENT " driver.");
137MODULE_PARM_SYNTAX(snd_dma2, SNDRV_DMA_DESC);
138
139struct snd_card_cs4236 {
140 struct resource *res_sb_port;
141#ifdef __ISAPNP__
142 struct isapnp_dev *wss;
143 struct isapnp_dev *ctrl;
144 struct isapnp_dev *mpu;
145#endif
146};
147
148static snd_card_t *snd_cs4236_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
149
150#ifdef __ISAPNP__
151
152static struct isapnp_card *snd_cs4236_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
153static const struct isapnp_card_id *snd_cs4236_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
154
155#ifdef TARGET_OS2
156#define ISAPNP_CS4232(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
157 { \
158 0, ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
159 { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
160 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
161 ISAPNP_DEVICE_ID(_va, _vb, _vc, _mpu401) } \
162 }
163#define ISAPNP_CS4232_1(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
164 { \
165 0, ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
166 { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
167 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
168 ISAPNP_DEVICE_ID('P', 'N', 'P', _mpu401) } \
169 }
170#define ISAPNP_CS4232_WOMPU(_va, _vb, _vc, _device, _wss, _ctrl) \
171 { \
172 0, ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
173 { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
174 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl) } \
175 }
176#else
177#define ISAPNP_CS4232(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
178 { \
179 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
180 devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
181 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
182 ISAPNP_DEVICE_ID(_va, _vb, _vc, _mpu401) } \
183 }
184#define ISAPNP_CS4232_1(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
185 { \
186 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
187 devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
188 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
189 ISAPNP_DEVICE_ID('P', 'N', 'P', _mpu401) } \
190 }
191#define ISAPNP_CS4232_WOMPU(_va, _vb, _vc, _device, _wss, _ctrl) \
192 { \
193 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
194 devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
195 ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl) } \
196 }
197#endif
198
199
200#ifdef CS4232
201static struct isapnp_card_id snd_card_pnpids[] __devinitdata = {
202 /* HP Omnibook 5500 onboard */
203 ISAPNP_CS4232('C','S','C',0x4232,0x0000,0x0002,0x0003),
204 /* Turtle Beach TBS-2000 (CS4232) */
205 ISAPNP_CS4232('C','S','C',0x7532,0x0000,0x0010,0xb006),
206 /* Turtle Beach Tropez Plus (CS4232) */
207 ISAPNP_CS4232_1('C','S','C',0x7632,0x0000,0x0010,0xb006),
208 /* SIC CrystalWave 32 (CS4232) */
209 ISAPNP_CS4232('C','S','C',0xf032,0x0000,0x0010,0x0003),
210 /* TerraTec Maestro 32/96 (CS4232) */
211 ISAPNP_CS4232('C','S','C',0x1a32,0x0000,0x0010,0x0003),
212 /* --- */
213 { ISAPNP_CARD_END, } /* end */
214};
215#else /* CS4236 */
216static struct isapnp_card_id snd_card_pnpids[] __devinitdata = {
217 /* Intel Marlin Spike Motherboard - CS4235 */
218 ISAPNP_CS4232('C','S','C',0x0225,0x0000,0x0010,0x0003),
219 /* Intel Marlin Spike Motherboard (#2) - CS4235 */
220 ISAPNP_CS4232('C','S','C',0x0225,0x0100,0x0110,0x0103),
221 /* Genius Sound Maker 3DJ - CS4237B */
222 ISAPNP_CS4232('C','S','C',0x0437,0x0000,0x0010,0x0003),
223 /* some uknown CS4236B */
224 ISAPNP_CS4232('C','S','C',0x0b35,0x0000,0x0010,0x0003),
225 /* CS4235 on mainboard without MPU */
226 ISAPNP_CS4232_WOMPU('C','S','C',0x1425,0x0100,0x0110),
227 /* HP 6330 Onboard sound */
228 ISAPNP_CS4232('C','S','C',0x1525,0x0100,0x0110,0x0103),
229 /* Crystal Computer TidalWave128 */
230 ISAPNP_CS4232('C','S','C',0x1e37,0x0000,0x0010,0x0003),
231 /* ACER AW37 - CS4235 */
232 ISAPNP_CS4232('C','S','C',0x4236,0x0000,0x0010,0x0003),
233 /* build-in soundcard in EliteGroup P5TX-LA motherboard - CS4237B */
234 ISAPNP_CS4232('C','S','C',0x4237,0x0000,0x0010,0x0003),
235 /* Crystal 3D - CS4237B */
236 ISAPNP_CS4232('C','S','C',0x4336,0x0000,0x0010,0x0003),
237 /* Typhoon Soundsystem PnP - CS4236B */
238 ISAPNP_CS4232('C','S','C',0x4536,0x0000,0x0010,0x0003),
239 /* TerraTec AudioSystem EWS64XL - CS4236B */
240 ISAPNP_CS4232('C','S','C',0xa836,0xa800,0xa810,0xa803),
241 /* Crystal Semiconductors CS4237B */
242 ISAPNP_CS4232('C','S','C',0x4637,0x0000,0x0010,0x0003),
243 /* NewClear 3D - CX4237B-XQ3 */
244 ISAPNP_CS4232('C','S','C',0x4837,0x0000,0x0010,0x0003),
245 /* Dell Optiplex GX1 - CS4236B */
246 ISAPNP_CS4232('C','S','C',0x6835,0x0000,0x0010,0x0003),
247 /* Dell P410 motherboard - CS4236B */
248 ISAPNP_CS4232_WOMPU('C','S','C',0x6835,0x0000,0x0010),
249 /* Dell Workstation 400 Onboard - CS4236B */
250 ISAPNP_CS4232('C','S','C',0x6836,0x0000,0x0010,0x0003),
251 /* Turtle Beach Malibu - CS4237B */
252 ISAPNP_CS4232('C','S','C',0x7537,0x0000,0x0010,0x0003),
253 /* CS4235 - onboard */
254 ISAPNP_CS4232('C','S','C',0x8025,0x0100,0x0110,0x0103),
255 /* IBM Aptiva 2137 E24 Onboard - CS4237B */
256 ISAPNP_CS4232('C','S','C',0x8037,0x0000,0x0010,0x0003),
257 /* Maxi Sound 16 PnP - CS4236B */
258 ISAPNP_CS4232('C','S','C',0x9836,0x0000,0x0010,0x0003),
259 /* Gallant SC-70P */
260 ISAPNP_CS4232('C','S','C',0x9837,0x0000,0x0010,0x0003),
261 /* IBM IntelliStation M Pro motherboard */
262 ISAPNP_CS4232_WOMPU('C','S','C',0xc835,0x0000,0x0010),
263 /* ACER AW37/Pro - CS4235 */
264 ISAPNP_CS4232('C','S','C',0xd925,0x0000,0x0010,0x0003),
265 /* ACER AW35/Pro - CS4237B */
266 ISAPNP_CS4232('C','S','C',0xd937,0x0000,0x0010,0x0003),
267 /* CS4235 without MPU401 */
268 ISAPNP_CS4232_WOMPU('C','S','C',0xe825,0x0100,0x0110),
269 /* CS4236B */
270 ISAPNP_CS4232('C','S','C',0xf235,0x0000,0x0010,0x0003),
271 /* CS4236B */
272 ISAPNP_CS4232('C','S','C',0xf238,0x0000,0x0010,0x0003),
273 /* --- */
274 { ISAPNP_CARD_END, } /* end */
275};
276#endif
277
278ISAPNP_CARD_TABLE(snd_card_pnpids);
279
280static int __init snd_card_cs4236_isapnp(int dev, struct snd_card_cs4236 *acard)
281{
282 const struct isapnp_card_id *id = snd_cs4236_isapnp_id[dev];
283 struct isapnp_card *card = snd_cs4236_isapnp_cards[dev];
284 struct isapnp_dev *pdev;
285
286 acard->wss = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
287 if (acard->wss->active) {
288 acard->wss = NULL;
289 return -EBUSY;
290 }
291 acard->ctrl = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
292 if (acard->ctrl->active) {
293 acard->wss = acard->ctrl = NULL;
294 return -EBUSY;
295 }
296 if (id->devs[2].vendor && id->devs[2].function) {
297 acard->mpu = isapnp_find_dev(card, id->devs[2].vendor, id->devs[2].function, NULL);
298 if (acard->mpu->active) {
299 acard->wss = acard->ctrl = acard->mpu = NULL;
300 return -EBUSY;
301 }
302 }
303
304 /* WSS initialization */
305 pdev = acard->wss;
306 if (pdev->prepare(pdev) < 0)
307 return -EAGAIN;
308 if (snd_port[dev] != SNDRV_AUTO_PORT)
309 isapnp_resource_change(&pdev->resource[0], snd_port[dev], 4);
310 if (snd_fm_port[dev] != SNDRV_AUTO_PORT)
311 isapnp_resource_change(&pdev->resource[1], snd_fm_port[dev], 4);
312 if (snd_sb_port[dev] != SNDRV_AUTO_PORT)
313 isapnp_resource_change(&pdev->resource[2], snd_sb_port[dev], 16);
314 if (snd_irq[dev] != SNDRV_AUTO_IRQ)
315 isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
316 if (snd_dma1[dev] != SNDRV_AUTO_DMA)
317 isapnp_resource_change(&pdev->dma_resource[0], snd_dma1[dev], 1);
318 if (snd_dma2[dev] != SNDRV_AUTO_DMA)
319 isapnp_resource_change(&pdev->dma_resource[1], snd_dma2[dev] < 0 ? 4 : snd_dma2[dev], 1);
320 if (pdev->activate(pdev)<0) {
321 snd_printk(IDENT " isapnp configure failed for WSS (out of resources?)\n");
322 return -EBUSY;
323 }
324 snd_port[dev] = pdev->resource[0].start;
325 snd_fm_port[dev] = pdev->resource[1].start;
326 snd_sb_port[dev] = pdev->resource[2].start;
327 snd_irq[dev] = pdev->irq_resource[0].start;
328 snd_dma1[dev] = pdev->dma_resource[0].start;
329 snd_dma2[dev] = pdev->dma_resource[1].start == 4 ? -1 : pdev->dma_resource[1].start;
330 snd_printdd("isapnp WSS: wss port=0x%lx, fm port=0x%lx, sb port=0x%lx\n",
331 snd_port[dev], snd_fm_port[dev], snd_sb_port[dev]);
332 snd_printdd("isapnp WSS: irq=%i, dma1=%i, dma2=%i\n",
333 snd_irq[dev], snd_dma1[dev], snd_dma2[dev]);
334 /* CTRL initialization */
335 pdev = acard->ctrl;
336 if (pdev->prepare(pdev) < 0) {
337 acard->wss->deactivate(acard->wss);
338 return -EAGAIN;
339 }
340 if (snd_cport[dev] != SNDRV_AUTO_PORT)
341 isapnp_resource_change(&pdev->resource[0], snd_cport[dev], 8);
342 if (pdev->activate(pdev)<0) {
343 snd_printk(IDENT " isapnp configure failed for control (out of resources?)\n");
344 acard->wss->deactivate(acard->wss);
345 return -EBUSY;
346 }
347 snd_cport[dev] = pdev->resource[0].start;
348 snd_printdd("isapnp CTRL: control port=0x%lx\n", snd_cport[dev]);
349 /* MPU initialization */
350 if (acard->mpu) {
351 pdev = acard->mpu;
352 if (pdev->prepare(pdev) < 0) {
353 acard->wss->deactivate(acard->wss);
354 acard->ctrl->deactivate(acard->ctrl);
355 return -EAGAIN;
356 }
357 if (snd_mpu_port[dev] != SNDRV_AUTO_PORT)
358 isapnp_resource_change(&pdev->resource[0], snd_mpu_port[dev], 2);
359 if (snd_mpu_irq[dev] != SNDRV_AUTO_IRQ)
360 isapnp_resource_change(&pdev->irq_resource[0], snd_mpu_irq[dev], 1);
361 if (pdev->activate(pdev)<0) {
362 snd_mpu_port[dev] = SNDRV_AUTO_PORT;
363 snd_printk(IDENT " isapnp configure failed for MPU (out of resources?)\n");
364 } else {
365 snd_mpu_port[dev] = pdev->resource[0].start;
366 snd_mpu_irq[dev] = pdev->irq_resource[0].start;
367 }
368 snd_printdd("isapnp MPU: port=0x%lx, irq=%i\n", snd_mpu_port[dev], snd_mpu_irq[dev]);
369 }
370 return 0;
371}
372
373static void snd_card_cs4236_deactivate(struct snd_card_cs4236 *acard)
374{
375 if (acard->wss) {
376 acard->wss->deactivate(acard->wss);
377 acard->wss = NULL;
378 }
379 if (acard->ctrl) {
380 acard->ctrl->deactivate(acard->ctrl);
381 acard->ctrl = NULL;
382 }
383 if (acard->mpu) {
384 acard->mpu->deactivate(acard->mpu);
385 acard->mpu = NULL;
386 }
387}
388#endif
389
390static void snd_card_cs4236_free(snd_card_t *card)
391{
392 struct snd_card_cs4236 *acard = (struct snd_card_cs4236 *)card->private_data;
393
394 if (acard) {
395#ifdef __ISAPNP__
396 snd_card_cs4236_deactivate(acard);
397#endif
398 if (acard->res_sb_port)
399 release_resource(acard->res_sb_port);
400 }
401}
402
403static int __init snd_card_cs4236_probe(int dev)
404{
405 snd_card_t *card;
406 struct snd_card_cs4236 *acard;
407 snd_pcm_t *pcm = NULL;
408 cs4231_t *chip;
409 opl3_t *opl3;
410 int err;
411
412#ifdef __ISAPNP__
413 if (!snd_isapnp[dev]) {
414#endif
415 if (snd_port[dev] == SNDRV_AUTO_PORT) {
416 snd_printk("specify snd_port\n");
417 return -EINVAL;
418 }
419 if (snd_cport[dev] == SNDRV_AUTO_PORT) {
420 snd_printk("specify snd_cport\n");
421 return -EINVAL;
422 }
423#ifdef __ISAPNP__
424 }
425#endif
426 card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE,
427 sizeof(struct snd_card_cs4236));
428 if (card == NULL)
429 return -ENOMEM;
430 acard = (struct snd_card_cs4236 *)card->private_data;
431 card->private_free = snd_card_cs4236_free;
432#ifdef __ISAPNP__
433 if (snd_isapnp[dev] && (err = snd_card_cs4236_isapnp(dev, acard))<0) {
434 snd_printk("isapnp detection failed and probing for " IDENT " is not supported\n");
435 snd_card_free(card);
436 return -ENXIO;
437 }
438#endif
439 if (snd_mpu_port[dev] < 0)
440 snd_mpu_port[dev] = SNDRV_AUTO_PORT;
441 if (snd_fm_port[dev] < 0)
442 snd_fm_port[dev] = SNDRV_AUTO_PORT;
443 if (snd_sb_port[dev] < 0)
444 snd_sb_port[dev] = SNDRV_AUTO_PORT;
445 if (snd_sb_port[dev] != SNDRV_AUTO_PORT)
446 if ((acard->res_sb_port = request_region(snd_sb_port[dev], 16, IDENT " SB")) == NULL) {
447 snd_printk("unable to register SB port at 0x%lx\n", snd_sb_port[dev]);
448 snd_card_free(card);
449 return -ENOMEM;
450 }
451
452#ifdef CS4232
453 if ((err = snd_cs4231_create(card,
454 snd_port[dev],
455 snd_cport[dev],
456 snd_irq[dev],
457 snd_dma1[dev],
458 snd_dma2[dev],
459 CS4231_HW_DETECT,
460 0,
461 &chip)) < 0) {
462 snd_card_free(card);
463 return err;
464 }
465 if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
466 snd_card_free(card);
467 return err;
468 }
469 if ((err = snd_cs4231_mixer(chip)) < 0) {
470 snd_card_free(card);
471 return err;
472 }
473
474#else /* CS4236 */
475 if ((err = snd_cs4236_create(card,
476 snd_port[dev],
477 snd_cport[dev],
478 snd_irq[dev],
479 snd_dma1[dev],
480 snd_dma2[dev],
481 CS4231_HW_DETECT,
482 0,
483 &chip)) < 0) {
484 snd_card_free(card);
485 return err;
486 }
487 if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0) {
488 snd_card_free(card);
489 return err;
490 }
491 if ((err = snd_cs4236_mixer(chip)) < 0) {
492 snd_card_free(card);
493 return err;
494 }
495#endif
496
497 if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
498 snd_card_free(card);
499 return err;
500 }
501
502 if (snd_fm_port[dev] != SNDRV_AUTO_PORT) {
503 if (snd_opl3_create(card,
504 snd_fm_port[dev], snd_fm_port[dev] + 2,
505 OPL3_HW_OPL3_CS, 0, &opl3) < 0) {
506 snd_printk(IDENT ": OPL3 not detected\n");
507 } else {
508 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
509 snd_card_free(card);
510 return err;
511 }
512 }
513 }
514
515 if (snd_mpu_irq[dev] >= 0 && snd_mpu_irq[dev] != SNDRV_AUTO_IRQ) {
516 if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
517 snd_mpu_port[dev], 0,
518 snd_mpu_irq[dev], SA_INTERRUPT, NULL) < 0)
519 snd_printk(IDENT ": MPU401 not detected\n");
520 }
521 strcpy(card->driver, pcm->name);
522 strcpy(card->shortname, pcm->name);
523 sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
524 pcm->name,
525 chip->port,
526 snd_irq[dev],
527 snd_dma1[dev]);
528 if (snd_dma1[dev] >= 0)
529 sprintf(card->longname + strlen(card->longname), "&%d", snd_dma2[dev]);
530 if ((err = snd_card_register(card)) < 0) {
531 snd_card_free(card);
532 return err;
533 }
534 snd_cs4236_cards[dev] = card;
535 return 0;
536}
537
538#ifdef __ISAPNP__
539static int __init snd_cs4236_isapnp_detect(struct isapnp_card *card,
540 const struct isapnp_card_id *id)
541{
542 static int dev = 0;
543 int res;
544
545 for ( ; dev < SNDRV_CARDS; dev++) {
546 if (!snd_enable[dev])
547 continue;
548 snd_cs4236_isapnp_cards[dev] = card;
549 snd_cs4236_isapnp_id[dev] = id;
550 res = snd_card_cs4236_probe(dev);
551 if (res < 0)
552 return res;
553 dev++;
554 return 0;
555 }
556 return -ENODEV;
557}
558#endif /* __ISAPNP__ */
559
560static int __init alsa_card_cs423x_init(void)
561{
562 int dev, cards = 0;
563
564 for (dev = 0; dev < SNDRV_CARDS; dev++) {
565 if (!snd_enable[dev])
566 continue;
567#ifdef __ISAPNP__
568 if (snd_isapnp[dev])
569 continue;
570#endif
571 if (snd_card_cs4236_probe(dev) >= 0)
572 cards++;
573 }
574#ifdef __ISAPNP__
575 cards += isapnp_probe_cards(snd_card_pnpids, snd_cs4236_isapnp_detect);
576#endif
577 if (!cards) {
578#ifdef MODULE
579 snd_printk(IDENT " soundcard not found or device busy\n");
580#endif
581 return -ENODEV;
582 }
583 return 0;
584}
585
586static void __exit alsa_card_cs423x_exit(void)
587{
588 int idx;
589
590 for (idx = 0; idx < SNDRV_CARDS; idx++)
591 snd_card_free(snd_cs4236_cards[idx]);
592}
593
594module_init(alsa_card_cs423x_init)
595module_exit(alsa_card_cs423x_exit)
596
597#ifndef MODULE
598
599/* format is: snd-card-cs4232=snd_enable,snd_index,snd_id,snd_isapnp,snd_port,
600 snd_cport,snd_mpu_port,snd_fm_port,snd_sb_port,
601 snd_irq,snd_mpu_irq,snd_dma1,snd_dma1_size,
602 snd_dma2,snd_dma2_size */
603/* format is: snd-card-cs4236=snd_enable,snd_index,snd_id,snd_isapnp,snd_port,
604 snd_cport,snd_mpu_port,snd_fm_port,snd_sb_port,
605 snd_irq,snd_mpu_irq,snd_dma1,snd_dma1_size,
606 snd_dma2,snd_dma2_size */
607
608static int __init alsa_card_cs423x_setup(char *str)
609{
610 static unsigned __initdata nr_dev = 0;
611 int __attribute__ ((__unused__)) pnp = INT_MAX;
612
613 if (nr_dev >= SNDRV_CARDS)
614 return 0;
615 (void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&
616 get_option(&str,&snd_index[nr_dev]) == 2 &&
617 get_id(&str,&snd_id[nr_dev]) == 2 &&
618 get_option(&str,&pnp) == 2 &&
619 get_option(&str,(int *)&snd_port[nr_dev]) == 2 &&
620 get_option(&str,(int *)&snd_cport[nr_dev]) == 2 &&
621 get_option(&str,(int *)&snd_mpu_port[nr_dev]) == 2 &&
622 get_option(&str,(int *)&snd_fm_port[nr_dev]) == 2 &&
623 get_option(&str,(int *)&snd_sb_port[nr_dev]) == 2 &&
624 get_option(&str,&snd_irq[nr_dev]) == 2 &&
625 get_option(&str,&snd_mpu_irq[nr_dev]) == 2 &&
626 get_option(&str,&snd_dma1[nr_dev]) == 2 &&
627 get_option(&str,&snd_dma2[nr_dev]) == 2);
628#ifdef __ISAPNP__
629 if (pnp != INT_MAX)
630 snd_isapnp[nr_dev] = pnp;
631#endif
632 nr_dev++;
633 return 1;
634}
635
636#ifdef CS4232
637__setup("snd-card-cs4232=", alsa_card_cs423x_setup);
638#else /* CS4236 */
639__setup("snd-card-cs4236=", alsa_card_cs423x_setup);
640#endif
641
642#endif /* ifndef MODULE */
Note: See TracBrowser for help on using the repository browser.