patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / sound / drivers / mtpav.c
1 /*
2  *      MOTU Midi Timepiece ALSA Main routines
3  *      Copyright by Michael T. Mayers (c) Jan 09, 2000
4  *      mail: michael@tweakoz.com
5  *      Thanks to John Galbraith
6  *
7  *      This program is free software; you can redistribute it and/or modify
8  *      it under the terms of the GNU General Public License as published by
9  *      the Free Software Foundation; either version 2 of the License, or
10  *      (at your option) any later version.
11  *
12  *      This program is distributed in the hope that it will be useful,
13  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *      GNU General Public License for more details.
16  *
17  *      You should have received a copy of the GNU General Public License
18  *      along with this program; if not, write to the Free Software
19  *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20  *
21  *
22  *      This driver is for the 'Mark Of The Unicorn' (MOTU)
23  *      MidiTimePiece AV multiport MIDI interface 
24  *
25  *      IOPORTS
26  *      -------
27  *      8 MIDI Ins and 8 MIDI outs
28  *      Video Sync In (BNC), Word Sync Out (BNC), 
29  *      ADAT Sync Out (DB9)
30  *      SMPTE in/out (1/4")
31  *      2 programmable pedal/footswitch inputs and 4 programmable MIDI controller knobs.
32  *      Macintosh RS422 serial port
33  *      RS422 "network" port for ganging multiple MTP's
34  *      PC Parallel Port ( which this driver currently uses )
35  *
36  *      MISC FEATURES
37  *      -------------
38  *      Hardware MIDI routing, merging, and filtering   
39  *      MIDI Synchronization to Video, ADAT, SMPTE and other Clock sources
40  *      128 'scene' memories, recallable from MIDI program change
41  *
42  *
43  * ChangeLog
44  * Jun 11 2001  Takashi Iwai <tiwai@suse.de>
45  *      - Recoded & debugged
46  *      - Added timer interrupt for midi outputs
47  *      - hwports is between 1 and 8, which specifies the number of hardware ports.
48  *        The three global ports, computer, adat and broadcast ports, are created
49  *        always after h/w and remote ports.
50  *
51  */
52
53 #include <sound/driver.h>
54 #include <linux/init.h>
55 #include <linux/interrupt.h>
56 #include <linux/slab.h>
57 #include <linux/ioport.h>
58 #include <linux/moduleparam.h>
59 #include <sound/core.h>
60 #include <sound/initval.h>
61 #include <sound/rawmidi.h>
62 #include <linux/delay.h>
63
64 #include <asm/io.h>
65
66 /*
67  *      globals
68  */
69 MODULE_AUTHOR("Michael T. Mayers");
70 MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI");
71 MODULE_LICENSE("GPL");
72 MODULE_CLASSES("{sound}");
73 MODULE_DEVICES("{{MOTU,MidiTimePiece AV multiport MIDI}}");
74
75 // io resources
76 #define MTPAV_IOBASE            0x378
77 #define MTPAV_IRQ               7
78 #define MTPAV_MAX_PORTS         8
79
80 static int index = SNDRV_DEFAULT_IDX1;
81 static char *id = SNDRV_DEFAULT_STR1;
82 static long port = MTPAV_IOBASE;        /* 0x378, 0x278 */
83 static int irq = MTPAV_IRQ;             /* 7, 5 */
84 static int hwports = MTPAV_MAX_PORTS;   /* use hardware ports 1-8 */
85
86 module_param(index, int, 0444);
87 MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI.");
88 MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
89 module_param(id, charp, 0444);
90 MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI.");
91 MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
92 module_param(port, long, 0444);
93 MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI.");
94 MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x378},{0x278}},dialog:list");
95 module_param(irq, int, 0444);
96 MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
97 MODULE_PARM_SYNTAX(irq,  SNDRV_ENABLED ",allows:{{7},{5}},dialog:list");
98 module_param(hwports, int, 0444);
99 MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
100 MODULE_PARM_SYNTAX(hwports, SNDRV_ENABLED ",allows:{{1,8}},dialog:list");
101
102 /*
103  *      defines
104  */
105 //#define USE_FAKE_MTP //       don't actually read/write to MTP device (for debugging without an actual unit) (does not work yet)
106
107 // parallel port usage masks
108 #define SIGS_BYTE 0x08
109 #define SIGS_RFD 0x80
110 #define SIGS_IRQ 0x40
111 #define SIGS_IN0 0x10
112 #define SIGS_IN1 0x20
113
114 #define SIGC_WRITE 0x04
115 #define SIGC_READ 0x08
116 #define SIGC_INTEN 0x10
117
118 #define DREG 0
119 #define SREG 1
120 #define CREG 2
121
122 //
123 #define MTPAV_MODE_INPUT_OPENED         0x01
124 #define MTPAV_MODE_OUTPUT_OPENED        0x02
125 #define MTPAV_MODE_INPUT_TRIGGERED      0x04
126 #define MTPAV_MODE_OUTPUT_TRIGGERED     0x08
127
128 #define NUMPORTS (0x12+1)
129
130
131 /*
132  */
133
134 typedef struct mtpav_port {
135         u8 number;
136         u8 hwport;
137         u8 mode;
138         u8 running_status;
139         snd_rawmidi_substream_t *input;
140         snd_rawmidi_substream_t *output;
141 } mtpav_port_t;
142
143 typedef struct mtpav {
144         snd_card_t *card;
145         unsigned long port;
146         struct resource *res_port;
147         int irq;                        /* interrupt (for inputs) */
148         spinlock_t spinlock;
149         int share_irq;                  /* number of accesses to input interrupts */
150         int istimer;                    /* number of accesses to timer interrupts */
151         struct timer_list timer;        /* timer interrupts for outputs */
152         snd_rawmidi_t *rmidi;
153         int num_ports;          /* number of hw ports (1-8) */
154         mtpav_port_t ports[NUMPORTS];   /* all ports including computer, adat and bc */
155
156         u32 inmidiport;         /* selected input midi port */
157         u32 inmidistate;        /* during midi command 0xf5 */
158
159         u32 outmidihwport;      /* selected output midi hw port */
160 } mtpav_t;
161
162
163 /*
164  * global instance
165  * hey, we handle at most only one card..
166  */
167 static mtpav_t *mtp_card;
168
169 /*
170  * possible hardware ports (selected by 0xf5 port message)
171  *      0x00            all ports
172  *      0x01 .. 0x08    this MTP's ports 1..8
173  *      0x09 .. 0x10    networked MTP's ports (9..16)
174  *      0x11            networked MTP's computer port
175  *      0x63            to ADAT
176  *
177  * mappig:
178  *  subdevice 0 - (X-1)    ports
179  *            X - (2*X-1)  networked ports
180  *            X            computer
181  *            X+1          ADAT
182  *            X+2          all ports
183  *
184  *  where X = chip->num_ports
185  */
186
187 #define MTPAV_PIDX_COMPUTER     0
188 #define MTPAV_PIDX_ADAT         1
189 #define MTPAV_PIDX_BROADCAST    2
190
191
192 static int translate_subdevice_to_hwport(mtpav_t *chip, int subdev)
193 {
194         if (subdev < 0)
195                 return 0x01; /* invalid - use port 0 as default */
196         else if (subdev < chip->num_ports)
197                 return subdev + 1; /* single mtp port */
198         else if (subdev < chip->num_ports * 2)
199                 return subdev - chip->num_ports + 0x09; /* remote port */
200         else if (subdev == chip->num_ports * 2 + MTPAV_PIDX_COMPUTER)
201                 return 0x11; /* computer port */
202         else if (subdev == chip->num_ports + MTPAV_PIDX_ADAT)
203                 return 0x63;            /* ADAT */
204         return 0; /* all ports */
205 }
206
207 static int translate_hwport_to_subdevice(mtpav_t *chip, int hwport)
208 {
209         int p;
210         if (hwport <= 0x00) /* all ports */
211                 return chip->num_ports + MTPAV_PIDX_BROADCAST;
212         else if (hwport <= 0x08) { /* single port */
213                 p = hwport - 1;
214                 if (p >= chip->num_ports)
215                         p = 0;
216                 return p;
217         } else if (hwport <= 0x10) { /* remote port */
218                 p = hwport - 0x09 + chip->num_ports;
219                 if (p >= chip->num_ports * 2)
220                         p = chip->num_ports;
221                 return p;
222         } else if (hwport == 0x11)  /* computer port */
223                 return chip->num_ports + MTPAV_PIDX_COMPUTER;
224         else  /* ADAT */
225                 return chip->num_ports + MTPAV_PIDX_ADAT;
226 }
227
228
229 /*
230  */
231
232 static u8 snd_mtpav_getreg(mtpav_t *chip, u16 reg)
233 {
234         u8 rval = 0;
235
236         if (reg == SREG) {
237                 rval = inb(chip->port + SREG);
238                 rval = (rval & 0xf8);
239         } else if (reg == CREG) {
240                 rval = inb(chip->port + CREG);
241                 rval = (rval & 0x1c);
242         }
243
244         return rval;
245 }
246
247 /*
248  */
249
250 static void snd_mtpav_mputreg(mtpav_t *chip, u16 reg, u8 val)
251 {
252         if (reg == DREG) {
253                 outb(val, chip->port + DREG);
254         } else if (reg == CREG) {
255                 outb(val, chip->port + CREG);
256         }
257 }
258
259 /*
260  */
261
262 static void snd_mtpav_wait_rfdhi(mtpav_t *chip)
263 {
264         int counts = 10000;
265         u8 sbyte;
266
267         sbyte = snd_mtpav_getreg(chip, SREG);
268         while (!(sbyte & SIGS_RFD) && counts--) {
269                 sbyte = snd_mtpav_getreg(chip, SREG);
270                 udelay(10);
271         }
272 }
273
274 static void snd_mtpav_send_byte(mtpav_t *chip, u8 byte)
275 {
276         u8 tcbyt;
277         u8 clrwrite;
278         u8 setwrite;
279
280         snd_mtpav_wait_rfdhi(chip);
281
282         /////////////////
283
284         tcbyt = snd_mtpav_getreg(chip, CREG);
285         clrwrite = tcbyt & (SIGC_WRITE ^ 0xff);
286         setwrite = tcbyt | SIGC_WRITE;
287
288         snd_mtpav_mputreg(chip, DREG, byte);
289         snd_mtpav_mputreg(chip, CREG, clrwrite);        // clear write bit
290
291         snd_mtpav_mputreg(chip, CREG, setwrite);        // set write bit
292
293 }
294
295
296 /*
297  */
298
299 /* call this with spin lock held */
300 static void snd_mtpav_output_port_write(mtpav_port_t *port,
301                                         snd_rawmidi_substream_t *substream)
302 {
303         u8 outbyte;
304
305         // Get the outbyte first, so we can emulate running status if
306         // necessary
307         if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1)
308                 return;
309
310         // send port change command if necessary
311
312         if (port->hwport != mtp_card->outmidihwport) {
313                 mtp_card->outmidihwport = port->hwport;
314
315                 snd_mtpav_send_byte(mtp_card, 0xf5);
316                 snd_mtpav_send_byte(mtp_card, port->hwport);
317                 //snd_printk("new outport: 0x%x\n", (unsigned int) port->hwport);
318
319                 if (!(outbyte & 0x80) && port->running_status)
320                         snd_mtpav_send_byte(mtp_card, port->running_status);
321         }
322
323         // send data
324
325         do {
326                 if (outbyte & 0x80)
327                         port->running_status = outbyte;
328                 
329                 snd_mtpav_send_byte(mtp_card, outbyte);
330         } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1);
331 }
332
333 static void snd_mtpav_output_write(snd_rawmidi_substream_t * substream)
334 {
335         mtpav_port_t *port = &mtp_card->ports[substream->number];
336         unsigned long flags;
337
338         spin_lock_irqsave(&mtp_card->spinlock, flags);
339         snd_mtpav_output_port_write(port, substream);
340         spin_unlock_irqrestore(&mtp_card->spinlock, flags);
341 }
342
343
344 /*
345  *      mtpav control
346  */
347
348 static void snd_mtpav_portscan(mtpav_t *chip)   // put mtp into smart routing mode
349 {
350         u8 p;
351
352         for (p = 0; p < 8; p++) {
353                 snd_mtpav_send_byte(chip, 0xf5);
354                 snd_mtpav_send_byte(chip, p);
355                 snd_mtpav_send_byte(chip, 0xfe);
356         }
357 }
358
359 /*
360  */
361
362 static int snd_mtpav_input_open(snd_rawmidi_substream_t * substream)
363 {
364         unsigned long flags;
365         mtpav_port_t *portp = &mtp_card->ports[substream->number];
366
367         //printk("mtpav port: %d opened\n", (int) substream->number);
368         spin_lock_irqsave(&mtp_card->spinlock, flags);
369         portp->mode |= MTPAV_MODE_INPUT_OPENED;
370         portp->input = substream;
371         if (mtp_card->share_irq++ == 0)
372                 snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE));   // enable pport interrupts
373         spin_unlock_irqrestore(&mtp_card->spinlock, flags);
374         return 0;
375 }
376
377 /*
378  */
379
380 static int snd_mtpav_input_close(snd_rawmidi_substream_t *substream)
381 {
382         unsigned long flags;
383         mtpav_port_t *portp = &mtp_card->ports[substream->number];
384
385         //printk("mtpav port: %d closed\n", (int) portp);
386
387         spin_lock_irqsave(&mtp_card->spinlock, flags);
388
389         portp->mode &= (~MTPAV_MODE_INPUT_OPENED);
390         portp->input = NULL;
391         if (--mtp_card->share_irq == 0)
392                 snd_mtpav_mputreg(mtp_card, CREG, 0);   // disable pport interrupts
393
394         spin_unlock_irqrestore(&mtp_card->spinlock, flags);
395         return 0;
396 }
397
398 /*
399  */
400
401 static void snd_mtpav_input_trigger(snd_rawmidi_substream_t * substream, int up)
402 {
403         unsigned long flags;
404         mtpav_port_t *portp = &mtp_card->ports[substream->number];
405
406         spin_lock_irqsave(&mtp_card->spinlock, flags);
407         if (up)
408                 portp->mode |= MTPAV_MODE_INPUT_TRIGGERED;
409         else
410                 portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED;
411         spin_unlock_irqrestore(&mtp_card->spinlock, flags);
412
413 }
414
415
416 /*
417  * timer interrupt for outputs
418  */
419
420 static void snd_mtpav_output_timer(unsigned long data)
421 {
422         mtpav_t *chip = snd_magic_cast(mtpav_t, (void *)data, return);
423         int p;
424
425         spin_lock(&chip->spinlock);
426         /* reprogram timer */
427         chip->timer.expires = 1 + jiffies;
428         add_timer(&chip->timer);
429         /* process each port */
430         for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) {
431                 mtpav_port_t *portp = &mtp_card->ports[p];
432                 if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
433                         snd_mtpav_output_port_write(portp, portp->output);
434         }
435         spin_unlock(&chip->spinlock);
436 }
437
438 /* spinlock held! */
439 static void snd_mtpav_add_output_timer(mtpav_t *chip)
440 {
441         init_timer(&chip->timer);
442         chip->timer.function = snd_mtpav_output_timer;
443         chip->timer.data = (unsigned long) mtp_card;
444         chip->timer.expires = 1 + jiffies;
445         add_timer(&chip->timer);
446 }
447
448 /* spinlock held! */
449 static void snd_mtpav_remove_output_timer(mtpav_t *chip)
450 {
451         del_timer(&chip->timer);
452 }
453
454 /*
455  */
456
457 static int snd_mtpav_output_open(snd_rawmidi_substream_t * substream)
458 {
459         unsigned long flags;
460         mtpav_port_t *portp = &mtp_card->ports[substream->number];
461
462         spin_lock_irqsave(&mtp_card->spinlock, flags);
463         portp->mode |= MTPAV_MODE_OUTPUT_OPENED;
464         portp->output = substream;
465         spin_unlock_irqrestore(&mtp_card->spinlock, flags);
466         return 0;
467 };
468
469 /*
470  */
471
472 static int snd_mtpav_output_close(snd_rawmidi_substream_t * substream)
473 {
474         unsigned long flags;
475         mtpav_port_t *portp = &mtp_card->ports[substream->number];
476
477         spin_lock_irqsave(&mtp_card->spinlock, flags);
478         portp->mode &= (~MTPAV_MODE_OUTPUT_OPENED);
479         portp->output = NULL;
480         spin_unlock_irqrestore(&mtp_card->spinlock, flags);
481         return 0;
482 };
483
484 /*
485  */
486
487 static void snd_mtpav_output_trigger(snd_rawmidi_substream_t * substream, int up)
488 {
489         unsigned long flags;
490         mtpav_port_t *portp = &mtp_card->ports[substream->number];
491
492         spin_lock_irqsave(&mtp_card->spinlock, flags);
493         if (up) {
494                 if (! (portp->mode  & MTPAV_MODE_OUTPUT_TRIGGERED)) {
495                         if (mtp_card->istimer++ == 0)
496                                 snd_mtpav_add_output_timer(mtp_card);
497                         portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED;
498                 }
499         } else {
500                 portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED;
501                 if (--mtp_card->istimer == 0)
502                         snd_mtpav_remove_output_timer(mtp_card);
503         }
504         spin_unlock_irqrestore(&mtp_card->spinlock, flags);
505
506         if (up)
507                 snd_mtpav_output_write(substream);
508 }
509
510 /*
511  * midi interrupt for inputs
512  */
513
514 static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte)
515 {
516         mtpav_port_t *portp;
517
518         if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST)
519                 return;
520
521         portp = &mcrd->ports[mcrd->inmidiport];
522         if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) {
523                 spin_unlock(&mcrd->spinlock);
524                 snd_rawmidi_receive(portp->input, &inbyte, 1);
525                 spin_lock(&mcrd->spinlock);
526         }
527 }
528
529 static void snd_mtpav_inmidi_h(mtpav_t * mcrd, u8 inbyte)
530 {
531         snd_assert(mcrd, return);
532
533         if (inbyte >= 0xf8) {
534                 /* real-time midi code */
535                 snd_mtpav_inmidi_process(mcrd, inbyte);
536                 return;
537         }
538
539         if (mcrd->inmidistate == 0) {   // awaiting command
540                 if (inbyte == 0xf5)     // MTP port #
541                         mcrd->inmidistate = 1;
542                 else
543                         snd_mtpav_inmidi_process(mcrd, inbyte);
544         } else if (mcrd->inmidistate) {
545                 mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte);
546                 mcrd->inmidistate = 0;
547         }
548 }
549
550 static void snd_mtpav_read_bytes(mtpav_t * mcrd)
551 {
552         u8 clrread, setread;
553         u8 mtp_read_byte;
554         u8 sr, cbyt;
555         int i;
556
557         u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
558
559         //printk("snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt);
560
561         if (!(sbyt & SIGS_BYTE))
562                 return;
563
564         cbyt = snd_mtpav_getreg(mcrd, CREG);
565         clrread = cbyt & (SIGC_READ ^ 0xff);
566         setread = cbyt | SIGC_READ;
567
568         do {
569
570                 mtp_read_byte = 0;
571                 for (i = 0; i < 4; i++) {
572                         snd_mtpav_mputreg(mcrd, CREG, setread);
573                         sr = snd_mtpav_getreg(mcrd, SREG);
574                         snd_mtpav_mputreg(mcrd, CREG, clrread);
575
576                         sr &= SIGS_IN0 | SIGS_IN1;
577                         sr >>= 4;
578                         mtp_read_byte |= sr << (i * 2);
579                 }
580
581                 snd_mtpav_inmidi_h(mcrd, mtp_read_byte);
582
583                 sbyt = snd_mtpav_getreg(mcrd, SREG);
584
585         } while (sbyt & SIGS_BYTE);
586 }
587
588 static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
589 {
590         mtpav_t *mcard = snd_magic_cast(mtpav_t, dev_id, return IRQ_NONE);
591
592         //printk("irqh()\n");
593         spin_lock(&mcard->spinlock);
594         snd_mtpav_read_bytes(mcard);
595         spin_unlock(&mcard->spinlock);
596         return IRQ_HANDLED;
597 }
598
599 /*
600  * get ISA resources
601  */
602 static int snd_mtpav_get_ISA(mtpav_t * mcard)
603 {
604         if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
605                 snd_printk("MTVAP port 0x%lx is busy\n", port);
606                 return -EBUSY;
607         }
608         mcard->port = port;
609         if (request_irq(irq, snd_mtpav_irqh, SA_INTERRUPT, "MOTU MTPAV", (void *)mcard)) {
610                 snd_printk("MTVAP IRQ %d busy\n", irq);
611                 return -EBUSY;
612         }
613         mcard->irq = irq;
614         return 0;
615 }
616
617
618 /*
619  */
620
621 static snd_rawmidi_ops_t snd_mtpav_output = {
622         .open =         snd_mtpav_output_open,
623         .close =        snd_mtpav_output_close,
624         .trigger =      snd_mtpav_output_trigger,
625 };
626
627 static snd_rawmidi_ops_t snd_mtpav_input = {
628         .open =         snd_mtpav_input_open,
629         .close =        snd_mtpav_input_close,
630         .trigger =      snd_mtpav_input_trigger,
631 };
632
633
634 /*
635  * get RAWMIDI resources
636  */
637
638 static void snd_mtpav_set_name(mtpav_t *chip, snd_rawmidi_substream_t *substream)
639 {
640         if (substream->number >= 0 && substream->number < chip->num_ports)
641                 sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
642         else if (substream->number >= 8 && substream->number < chip->num_ports * 2)
643                 sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1);
644         else if (substream->number == chip->num_ports * 2)
645                 strcpy(substream->name, "MTP computer");
646         else if (substream->number == chip->num_ports * 2 + 1)
647                 strcpy(substream->name, "MTP ADAT");
648         else
649                 strcpy(substream->name, "MTP broadcast");
650 }
651
652 static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
653 {
654         int rval = 0;
655         snd_rawmidi_t *rawmidi;
656         snd_rawmidi_substream_t *substream;
657         struct list_head *list;
658
659         //printk("entering snd_mtpav_get_RAWMIDI\n");
660
661         if (hwports < 1)
662                 mcard->num_ports = 1;
663         else if (hwports > 8)
664                 mcard->num_ports = 8;
665         else
666                 mcard->num_ports = hwports;
667
668         if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0,
669                                     mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
670                                     mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
671                                     &mcard->rmidi)) < 0)
672                 return rval;
673         rawmidi = mcard->rmidi;
674
675         list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
676                 substream = list_entry(list, snd_rawmidi_substream_t, list);
677                 snd_mtpav_set_name(mcard, substream);
678                 substream->ops = &snd_mtpav_input;
679         }
680         list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
681                 substream = list_entry(list, snd_rawmidi_substream_t, list);
682                 snd_mtpav_set_name(mcard, substream);
683                 substream->ops = &snd_mtpav_output;
684                 mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number);
685         }
686         rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
687                                SNDRV_RAWMIDI_INFO_DUPLEX;
688         sprintf(rawmidi->name, "MTP AV MIDI");
689         //printk("exiting snd_mtpav_get_RAWMIDI() \n");
690         return 0;
691 }
692
693 /*
694  */
695
696 static mtpav_t *new_mtpav(void)
697 {
698         mtpav_t *ncrd = (mtpav_t *) snd_magic_kcalloc(mtpav_t, 0, GFP_KERNEL);
699         if (ncrd != NULL) {
700                 spin_lock_init(&ncrd->spinlock);
701
702                 init_timer(&ncrd->timer);
703                 ncrd->card = NULL;
704                 ncrd->irq = -1;
705                 ncrd->share_irq = 0;
706
707                 ncrd->inmidiport = 0xffffffff;
708                 ncrd->inmidistate = 0;
709                 ncrd->outmidihwport = 0xffffffff;
710         }
711         return ncrd;
712 }
713
714 /*
715  */
716
717 static void free_mtpav(mtpav_t * crd)
718 {
719         unsigned long flags;
720
721         spin_lock_irqsave(&crd->spinlock, flags);
722         if (crd->istimer > 0)
723                 snd_mtpav_remove_output_timer(crd);
724         spin_unlock_irqrestore(&crd->spinlock, flags);
725         if (crd->irq >= 0)
726                 free_irq(crd->irq, (void *)crd);
727         if (crd->res_port) {
728                 release_resource(crd->res_port);
729                 kfree_nocheck(crd->res_port);
730         }
731         snd_magic_kfree(crd);
732 }
733
734 /*
735  */
736
737 static int __init alsa_card_mtpav_init(void)
738 {
739         int err = 0;
740         char longname_buffer[80];
741
742         mtp_card = new_mtpav();
743         if (mtp_card == NULL)
744                 return -ENOMEM;
745
746         mtp_card->card = snd_card_new(index, id, THIS_MODULE, 0);
747         if (mtp_card->card == NULL) {
748                 free_mtpav(mtp_card);
749                 return -ENOMEM;
750         }
751
752         err = snd_mtpav_get_ISA(mtp_card);
753         //printk("snd_mtpav_get_ISA returned: %d\n", err);
754         if (err < 0)
755                 goto __error;
756
757         strcpy(mtp_card->card->driver, "MTPAV");
758         strcpy(mtp_card->card->shortname, "MTPAV on parallel port");
759         memset(longname_buffer, 0, sizeof(longname_buffer));
760         sprintf(longname_buffer, "MTPAV on parallel port at");
761
762         err = snd_mtpav_get_RAWMIDI(mtp_card);
763         //snd_printk("snd_mtapv_get_RAWMIDI returned: %d\n", err);
764         if (err < 0)
765                 goto __error;
766
767         err = snd_card_register(mtp_card->card);        // don't snd_card_register until AFTER all cards reources done!
768
769         //printk("snd_card_register returned %d\n", err);
770         if (err < 0)
771                 goto __error;
772
773
774         snd_mtpav_portscan(mtp_card);
775
776         printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
777
778         return 0;
779
780       __error:
781         snd_card_free(mtp_card->card);
782         free_mtpav(mtp_card);
783         return err;
784 }
785
786 /*
787  */
788
789 static void __exit alsa_card_mtpav_exit(void)
790 {
791         if (mtp_card == NULL)
792                 return;
793         if (mtp_card->card)
794                 snd_card_free(mtp_card->card);
795         free_mtpav(mtp_card);
796 }
797
798 /*
799  */
800
801 module_init(alsa_card_mtpav_init)
802 module_exit(alsa_card_mtpav_exit)