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