ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / sound / isa / cs423x / pc98.c
1 /*
2  *  Driver for CS4232 on NEC PC9800 series
3  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4  *                   Osamu Tomita <tomita@cinet.co.jp>
5  *                   Takashi Iwai <tiwai@suse.de>
6  *                   Hideaki Okubo <okubo@msh.biglobe.ne.jp>
7  *
8  *
9  *   This program is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU General Public License as published by
11  *   the Free Software Foundation; either version 2 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This program is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with this program; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22  *
23  */
24
25 #include <sound/driver.h>
26 #include <linux/init.h>
27 #include <linux/slab.h>
28 #include <sound/core.h>
29 #include <sound/cs4231.h>
30 #include <sound/mpu401.h>
31 #include <sound/opl3.h>
32 #define SNDRV_GET_ID
33 #include <sound/initval.h>
34 #include "sound_pc9800.h"
35
36 #define chip_t cs4231_t
37
38 MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
39 MODULE_LICENSE("GPL");
40 MODULE_CLASSES("{sound}");
41 MODULE_DESCRIPTION("NEC PC9800 CS4232");
42 MODULE_DEVICES("{{NEC,PC9800}}");
43
44 #define IDENT "PC98-CS4232"
45
46 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
47 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
48 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
49 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;     /* PnP setup */
50 #if 0 /* NOT USED */
51 static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;    /* PnP setup */
52 #endif
53 static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */
54 static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;  /* PnP setup */
55 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;        /* 5,7,9,11,12,15 */
56 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;    /* 9,11,12,15 */
57 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;       /* 0,1,3,5,6,7 */
58 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;       /* 0,1,3,5,6,7 */
59 static int pc98ii[SNDRV_CARDS];                         /* PC98II */
60
61 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
62 MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard.");
63 MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
64 MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
65 MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard.");
66 MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
67 MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
68 MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
69 MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
70 MODULE_PARM(port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
71 MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
72 MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
73 #if 0 /* NOT USED */
74 MODULE_PARM(cport, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
75 MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
76 MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC);
77 #endif
78 MODULE_PARM(mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
79 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
80 MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
81 MODULE_PARM(fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
82 MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
83 MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
84 MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
85 MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
86 MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
87 MODULE_PARM(mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
88 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
89 MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
90 MODULE_PARM(dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
91 MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
92 MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
93 MODULE_PARM(dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
94 MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
95 MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
96 MODULE_PARM(pc98ii, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
97 MODULE_PARM_DESC(pc98ii, "Roland MPU-PC98II support.");
98 MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC);
99
100
101 static snd_card_t *snd_pc98_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
102
103 /*
104  * initialize MPU401-UART
105  */
106
107 static int __init pc98_mpu401_init(int irq)
108 {
109 #include "pc9801_118_magic.h"
110 #define outp118(reg,data) outb((reg),0x148e);outb((data),0x148f)
111 #define WAIT118 outb(0x00,0x5f)
112         int     mpu_intr, count;
113 #ifdef OOKUBO_ORIGINAL
114         int     err = 0;
115 #endif /* OOKUBO_ORIGINAL */
116
117         switch (irq) {
118         case 3:
119                 mpu_intr = 3;
120                 break;
121         case 5:
122                 mpu_intr = 2;
123                 break;
124         case 6:
125                 mpu_intr = 1;
126                 break;
127         case 10:
128                 mpu_intr = 0;
129                 break;
130         default:
131                 snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq);
132                 return -EINVAL;
133         }
134
135         outp118(0x21, mpu_intr);
136         WAIT118;
137         outb(0x00, 0x148e);
138         if (inb(0x148f) & 0x08) {
139                 snd_printk(KERN_INFO IDENT ": No MIDI daughter board found\n");
140                 return 0;
141         }
142
143         outp118(0x20, 0x00);
144         outp118(0x05, 0x04);
145         for (count = 0; count < 35000; count ++)
146                 WAIT118;
147         outb(0x05, 0x148e);
148         for (count = 0; count < 65000; count ++)
149                 if (inb(0x148f) == 0x04)
150                         goto set_mode_118;
151         snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage1\n\n");
152         return -EINVAL;
153
154  set_mode_118:
155         outp118(0x05, 0x0c);
156         outb(0xaa, 0x485);
157         outb(0x99, 0x485);
158         outb(0x2a, 0x485);
159         for (count = 0; count < sizeof(Data0485_99); count ++) {
160                 outb(Data0485_99[count], 0x485);
161                 WAIT118;
162         }
163
164         outb(0x00, 0x486);
165         outb(0xaa, 0x485);
166         outb(0x9e, 0x485);
167         outb(0x2a, 0x485);
168         for (count = 0; count < sizeof(Data0485_9E); count ++)
169                 if (inb(0x485) != Data0485_9E[count]) {
170 #ifdef OOKUBO_ORIGINAL
171                         err = 1;
172 #endif /* OOKUBO_ORIGINAL */
173                         break;
174                 }
175         outb(0x00, 0x486);
176         for (count = 0; count < 2000; count ++)
177                 WAIT118;
178 #ifdef OOKUBO_ORIGINAL
179         if (!err) {
180                 outb(0xaa, 0x485);
181                 outb(0x36, 0x485);
182                 outb(0x28, 0x485);
183                 for (count = 0; count < sizeof(Data0485_36); count ++)
184                         outb(Data0485_36[count], 0x485);
185                 outb(0x00, 0x486);
186                 for (count = 0; count < 1500; count ++)
187                         WAIT118;
188                 outp118(0x05, inb(0x148f) | 0x08);
189                 outb(0xff, 0x148c);
190                 outp118(0x05, inb(0x148f) & 0xf7);
191                 for (count = 0; count < 1500; count ++)
192                         WAIT118;
193         }
194 #endif /* OOKUBO_ORIGINAL */
195
196         outb(0xaa, 0x485);
197         outb(0xa9, 0x485);
198         outb(0x21, 0x485);
199         for (count = 0; count < sizeof(Data0485_A9); count ++) {
200                 outb(Data0485_A9[count], 0x485);
201                 WAIT118;
202         }
203
204         outb(0x00, 0x486);
205         outb(0xaa, 0x485);
206         outb(0x0c, 0x485);
207         outb(0x20, 0x485);
208         for (count = 0; count < sizeof(Data0485_0C); count ++) {
209                 outb(Data0485_0C[count], 0x485);
210                 WAIT118;
211         }
212
213         outb(0x00, 0x486);
214         outb(0xaa, 0x485);
215         outb(0x66, 0x485);
216         outb(0x20, 0x485);
217         for (count = 0; count < sizeof(Data0485_66); count ++) {
218                 outb(Data0485_66[count], 0x485);
219                 WAIT118;
220         }
221
222         outb(0x00, 0x486);
223         outb(0xaa, 0x485);
224         outb(0x60, 0x485);
225         outb(0x20, 0x485);
226         for (count = 0; count < sizeof(Data0485_60); count ++) {
227                 outb(Data0485_60[count], 0x485);
228                 WAIT118;
229         }
230
231         outb(0x00, 0x486);
232         outp118(0x05, 0x04);
233         outp118(0x05, 0x00);
234         for (count = 0; count < 35000; count ++)
235                 WAIT118;
236         outb(0x05, 0x148e);
237         for (count = 0; count < 65000; count ++)
238                 if (inb(0x148f) == 0x00)
239                         goto end_mode_118;
240         snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage2\n");
241         return -EINVAL;
242
243  end_mode_118:
244         outb(0x3f, 0x148d);
245         snd_printk(KERN_INFO IDENT ": MIDI daughter board initialized\n");
246         return 0;
247 }
248
249 static int __init pc98_cs4231_chip_init(int dev)
250 {
251         int intr_bits, intr_bits2, dma_bits;
252
253         switch (irq[dev]) {
254         case 3:
255                 intr_bits = 0x08;
256                 intr_bits2 = 0x03;
257                 break;
258         case 5:
259                 intr_bits = 0x10;
260                 intr_bits2 = 0x08;
261                 break;
262         case 10:
263                 intr_bits = 0x18;
264                 intr_bits2 = 0x02;
265                 break;
266         case 12:
267                 intr_bits = 0x20;
268                 intr_bits2 = 0x00;
269                 break;
270         default:
271                 snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq[dev]);
272                 return -EINVAL;
273         }
274
275         switch (dma1[dev]) {
276         case 0:
277                 dma_bits = 0x01;
278                 break;
279         case 1:
280                 dma_bits = 0x02;
281                 break;
282         case 3:
283                 dma_bits = 0x03;
284                 break;
285         default:
286                 snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma1[dev]);
287                 return -EINVAL;
288         }
289
290         if (dma2[dev] >= 2) {
291                 snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma2[dev]);
292                 return -EINVAL;
293         }
294
295         outb(dma1[dev], 0x29);          /* dma1 boundary 64KB */
296         if (dma1[dev] != dma2[dev] && dma2[dev] >= 0) {
297                 outb(0, 0x5f);          /* wait */
298                 outb(dma2[dev], 0x29);  /* dma2 boundary 64KB */
299                 intr_bits |= 0x04;
300         }
301
302         if (PC9800_SOUND_ID() == PC9800_SOUND_ID_118) {
303                 /* Set up CanBe control registers. */
304                 snd_printd(KERN_INFO "Setting up CanBe Sound System\n");
305                 outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
306                 outb(0x01, 0x0f4a);
307                 outb(intr_bits2, 0x0f4b);
308         }
309
310         outb(intr_bits | dma_bits, 0xf40);
311         return 0;
312 }
313
314
315 static int __init snd_card_pc98_probe(int dev)
316 {
317         snd_card_t *card;
318         snd_pcm_t *pcm = NULL;
319         cs4231_t *chip;
320         opl3_t *opl3;
321         int err;
322
323         if (port[dev] == SNDRV_AUTO_PORT) {
324                 snd_printk(KERN_ERR IDENT ": specify port\n");
325                 return -EINVAL;
326         }
327         card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
328         if (card == NULL)
329                 return -ENOMEM;
330
331         if ((err = pc98_cs4231_chip_init(dev)) < 0) {
332                 snd_card_free(card);
333                 return err;
334         }
335
336         if ((err = snd_cs4231_create(card,
337                                      port[dev],
338                                      -1,
339                                      irq[dev],
340                                      dma1[dev],
341                                      dma2[dev],
342                                      CS4231_HW_DETECT,
343                                      0,
344                                      &chip)) < 0) {
345                 snd_card_free(card);
346                 return err;
347         }
348         if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
349                 snd_card_free(card);
350                 return err;
351         }
352         if ((err = snd_cs4231_mixer(chip)) < 0) {
353                 snd_card_free(card);
354                 return err;
355         }
356
357         if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) {
358                 snd_card_free(card);
359                 return err;
360         }
361
362         if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
363                 /* ??? */
364                 outb(0x00, fm_port[dev] + 6);
365                 inb(fm_port[dev] + 7);
366                 /* Enable OPL-3 Function */
367                 outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID);
368                 if (snd_opl3_create(card,
369                                     fm_port[dev], fm_port[dev] + 2,
370                                     OPL3_HW_OPL3_PC98, 0, &opl3) < 0) {
371                         printk(KERN_ERR IDENT ": OPL3 not detected\n");
372                 } else {
373                         if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
374                                 snd_card_free(card);
375                                 return err;
376                         }
377                 }
378         }
379
380         if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
381                 err = pc98_mpu401_init(mpu_irq[dev]);
382                 if (! err) {
383                         err = snd_mpu401_uart_new(card, 0,
384                                                   pc98ii[dev] ? MPU401_HW_PC98II : MPU401_HW_MPU401,
385                                                   mpu_port[dev], 0,
386                                                   mpu_irq[dev], SA_INTERRUPT, NULL);
387                         if (err < 0)
388                                 snd_printk(KERN_INFO IDENT ": MPU401 not detected\n");
389                 }
390         }
391
392         strcpy(card->driver, pcm->name);
393         strcpy(card->shortname, pcm->name);
394         sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
395                 pcm->name,
396                 chip->port,
397                 irq[dev],
398                 dma1[dev]);
399         if (dma2[dev] >= 0)
400                 sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
401         if ((err = snd_card_register(card)) < 0) {
402                 snd_card_free(card);
403                 return err;
404         }
405         snd_pc98_cards[dev] = card;
406         return 0;
407 }
408
409 static int __init alsa_card_pc98_init(void)
410 {
411         int dev, cards = 0;
412
413         for (dev = 0; dev < SNDRV_CARDS; dev++) {
414                 if (!enable[dev])
415                         continue;
416                 if (snd_card_pc98_probe(dev) >= 0)
417                         cards++;
418         }
419         if (!cards) {
420 #ifdef MODULE
421                 printk(KERN_ERR IDENT " soundcard not found or device busy\n");
422 #endif
423                 return -ENODEV;
424         }
425         return 0;
426 }
427
428 static void __exit alsa_card_pc98_exit(void)
429 {
430         int idx;
431
432         for (idx = 0; idx < SNDRV_CARDS; idx++)
433                 snd_card_free(snd_pc98_cards[idx]);
434 }
435
436 module_init(alsa_card_pc98_init)
437 module_exit(alsa_card_pc98_exit)
438
439 #ifndef MODULE
440
441 /* format is: snd-pc98-cs4232=enable,index,id,port,
442                          mpu_port,fm_port,
443                          irq,mpu_irq,dma1,dma2,pc98ii */
444
445 static int __init alsa_card_pc98_setup(char *str)
446 {
447         static unsigned __initdata nr_dev = 0;
448
449         if (nr_dev >= SNDRV_CARDS)
450                 return 0;
451         (void)(get_option(&str,&enable[nr_dev]) == 2 &&
452                get_option(&str,&index[nr_dev]) == 2 &&
453                get_id(&str,&id[nr_dev]) == 2 &&
454                get_option_long(&str,&port[nr_dev]) == 2 &&
455                get_option_long(&str,&mpu_port[nr_dev]) == 2 &&
456                get_option_long(&str,&fm_port[nr_dev]) == 2 &&
457                get_option(&str,&irq[nr_dev]) == 2 &&
458                get_option(&str,&mpu_irq[nr_dev]) == 2 &&
459                get_option(&str,&dma1[nr_dev]) == 2 &&
460                get_option(&str,&dma2[nr_dev]) == 2 &&
461                get_option(&str,&pc98ii[nr_dev]) == 2);
462         nr_dev++;
463         return 1;
464 }
465
466 __setup("snd-pc98-cs4232=", alsa_card_pc98_setup);
467
468 #endif /* ifndef MODULE */