Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *      MOTU Midi Timepiece ALSA Main routines
0004  *      Copyright by Michael T. Mayers (c) Jan 09, 2000
0005  *      mail: michael@tweakoz.com
0006  *      Thanks to John Galbraith
0007  *
0008  *      This driver is for the 'Mark Of The Unicorn' (MOTU)
0009  *      MidiTimePiece AV multiport MIDI interface 
0010  *
0011  *      IOPORTS
0012  *      -------
0013  *      8 MIDI Ins and 8 MIDI outs
0014  *      Video Sync In (BNC), Word Sync Out (BNC), 
0015  *      ADAT Sync Out (DB9)
0016  *      SMPTE in/out (1/4")
0017  *      2 programmable pedal/footswitch inputs and 4 programmable MIDI controller knobs.
0018  *      Macintosh RS422 serial port
0019  *      RS422 "network" port for ganging multiple MTP's
0020  *      PC Parallel Port ( which this driver currently uses )
0021  *
0022  *      MISC FEATURES
0023  *      -------------
0024  *      Hardware MIDI routing, merging, and filtering   
0025  *      MIDI Synchronization to Video, ADAT, SMPTE and other Clock sources
0026  *      128 'scene' memories, recallable from MIDI program change
0027  *
0028  * ChangeLog
0029  * Jun 11 2001  Takashi Iwai <tiwai@suse.de>
0030  *      - Recoded & debugged
0031  *      - Added timer interrupt for midi outputs
0032  *      - hwports is between 1 and 8, which specifies the number of hardware ports.
0033  *        The three global ports, computer, adat and broadcast ports, are created
0034  *        always after h/w and remote ports.
0035  */
0036 
0037 #include <linux/init.h>
0038 #include <linux/interrupt.h>
0039 #include <linux/module.h>
0040 #include <linux/err.h>
0041 #include <linux/platform_device.h>
0042 #include <linux/ioport.h>
0043 #include <linux/io.h>
0044 #include <linux/moduleparam.h>
0045 #include <sound/core.h>
0046 #include <sound/initval.h>
0047 #include <sound/rawmidi.h>
0048 #include <linux/delay.h>
0049 
0050 /*
0051  *      globals
0052  */
0053 MODULE_AUTHOR("Michael T. Mayers");
0054 MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI");
0055 MODULE_LICENSE("GPL");
0056 
0057 // io resources
0058 #define MTPAV_IOBASE        0x378
0059 #define MTPAV_IRQ       7
0060 #define MTPAV_MAX_PORTS     8
0061 
0062 static int index = SNDRV_DEFAULT_IDX1;
0063 static char *id = SNDRV_DEFAULT_STR1;
0064 static long port = MTPAV_IOBASE;    /* 0x378, 0x278 */
0065 static int irq = MTPAV_IRQ;     /* 7, 5 */
0066 static int hwports = MTPAV_MAX_PORTS;   /* use hardware ports 1-8 */
0067 
0068 module_param(index, int, 0444);
0069 MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI.");
0070 module_param(id, charp, 0444);
0071 MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI.");
0072 module_param_hw(port, long, ioport, 0444);
0073 MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI.");
0074 module_param_hw(irq, int, irq, 0444);
0075 MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
0076 module_param(hwports, int, 0444);
0077 MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
0078 
0079 static struct platform_device *device;
0080 
0081 /*
0082  *      defines
0083  */
0084 //#define USE_FAKE_MTP //       don't actually read/write to MTP device (for debugging without an actual unit) (does not work yet)
0085 
0086 // parallel port usage masks
0087 #define SIGS_BYTE 0x08
0088 #define SIGS_RFD 0x80
0089 #define SIGS_IRQ 0x40
0090 #define SIGS_IN0 0x10
0091 #define SIGS_IN1 0x20
0092 
0093 #define SIGC_WRITE 0x04
0094 #define SIGC_READ 0x08
0095 #define SIGC_INTEN 0x10
0096 
0097 #define DREG 0
0098 #define SREG 1
0099 #define CREG 2
0100 
0101 //
0102 #define MTPAV_MODE_INPUT_OPENED     0x01
0103 #define MTPAV_MODE_OUTPUT_OPENED    0x02
0104 #define MTPAV_MODE_INPUT_TRIGGERED  0x04
0105 #define MTPAV_MODE_OUTPUT_TRIGGERED 0x08
0106 
0107 #define NUMPORTS (0x12+1)
0108 
0109 
0110 /*
0111  */
0112 
0113 struct mtpav_port {
0114     u8 number;
0115     u8 hwport;
0116     u8 mode;
0117     u8 running_status;
0118     struct snd_rawmidi_substream *input;
0119     struct snd_rawmidi_substream *output;
0120 };
0121 
0122 struct mtpav {
0123     struct snd_card *card;
0124     unsigned long port;
0125     struct resource *res_port;
0126     int irq;            /* interrupt (for inputs) */
0127     spinlock_t spinlock;
0128     int share_irq;          /* number of accesses to input interrupts */
0129     int istimer;            /* number of accesses to timer interrupts */
0130     struct timer_list timer;    /* timer interrupts for outputs */
0131     struct snd_rawmidi *rmidi;
0132     int num_ports;      /* number of hw ports (1-8) */
0133     struct mtpav_port ports[NUMPORTS];  /* all ports including computer, adat and bc */
0134 
0135     u32 inmidiport;     /* selected input midi port */
0136     u32 inmidistate;    /* during midi command 0xf5 */
0137 
0138     u32 outmidihwport;  /* selected output midi hw port */
0139 };
0140 
0141 
0142 /*
0143  * possible hardware ports (selected by 0xf5 port message)
0144  *      0x00        all ports
0145  *      0x01 .. 0x08    this MTP's ports 1..8
0146  *      0x09 .. 0x10    networked MTP's ports (9..16)
0147  *      0x11            networked MTP's computer port
0148  *      0x63            to ADAT
0149  *
0150  * mappig:
0151  *  subdevice 0 - (X-1)    ports
0152  *            X - (2*X-1)  networked ports
0153  *            X            computer
0154  *            X+1          ADAT
0155  *            X+2          all ports
0156  *
0157  *  where X = chip->num_ports
0158  */
0159 
0160 #define MTPAV_PIDX_COMPUTER 0
0161 #define MTPAV_PIDX_ADAT     1
0162 #define MTPAV_PIDX_BROADCAST    2
0163 
0164 
0165 static int translate_subdevice_to_hwport(struct mtpav *chip, int subdev)
0166 {
0167     if (subdev < 0)
0168         return 0x01; /* invalid - use port 0 as default */
0169     else if (subdev < chip->num_ports)
0170         return subdev + 1; /* single mtp port */
0171     else if (subdev < chip->num_ports * 2)
0172         return subdev - chip->num_ports + 0x09; /* remote port */
0173     else if (subdev == chip->num_ports * 2 + MTPAV_PIDX_COMPUTER)
0174         return 0x11; /* computer port */
0175     else if (subdev == chip->num_ports + MTPAV_PIDX_ADAT)
0176         return 0x63;        /* ADAT */
0177     return 0; /* all ports */
0178 }
0179 
0180 static int translate_hwport_to_subdevice(struct mtpav *chip, int hwport)
0181 {
0182     int p;
0183     if (hwport <= 0x00) /* all ports */
0184         return chip->num_ports + MTPAV_PIDX_BROADCAST;
0185     else if (hwport <= 0x08) { /* single port */
0186         p = hwport - 1;
0187         if (p >= chip->num_ports)
0188             p = 0;
0189         return p;
0190     } else if (hwport <= 0x10) { /* remote port */
0191         p = hwport - 0x09 + chip->num_ports;
0192         if (p >= chip->num_ports * 2)
0193             p = chip->num_ports;
0194         return p;
0195     } else if (hwport == 0x11)  /* computer port */
0196         return chip->num_ports + MTPAV_PIDX_COMPUTER;
0197     else  /* ADAT */
0198         return chip->num_ports + MTPAV_PIDX_ADAT;
0199 }
0200 
0201 
0202 /*
0203  */
0204 
0205 static u8 snd_mtpav_getreg(struct mtpav *chip, u16 reg)
0206 {
0207     u8 rval = 0;
0208 
0209     if (reg == SREG) {
0210         rval = inb(chip->port + SREG);
0211         rval = (rval & 0xf8);
0212     } else if (reg == CREG) {
0213         rval = inb(chip->port + CREG);
0214         rval = (rval & 0x1c);
0215     }
0216 
0217     return rval;
0218 }
0219 
0220 /*
0221  */
0222 
0223 static inline void snd_mtpav_mputreg(struct mtpav *chip, u16 reg, u8 val)
0224 {
0225     if (reg == DREG || reg == CREG)
0226         outb(val, chip->port + reg);
0227 }
0228 
0229 /*
0230  */
0231 
0232 static void snd_mtpav_wait_rfdhi(struct mtpav *chip)
0233 {
0234     int counts = 10000;
0235     u8 sbyte;
0236 
0237     sbyte = snd_mtpav_getreg(chip, SREG);
0238     while (!(sbyte & SIGS_RFD) && counts--) {
0239         sbyte = snd_mtpav_getreg(chip, SREG);
0240         udelay(10);
0241     }
0242 }
0243 
0244 static void snd_mtpav_send_byte(struct mtpav *chip, u8 byte)
0245 {
0246     u8 tcbyt;
0247     u8 clrwrite;
0248     u8 setwrite;
0249 
0250     snd_mtpav_wait_rfdhi(chip);
0251 
0252     /////////////////
0253 
0254     tcbyt = snd_mtpav_getreg(chip, CREG);
0255     clrwrite = tcbyt & (SIGC_WRITE ^ 0xff);
0256     setwrite = tcbyt | SIGC_WRITE;
0257 
0258     snd_mtpav_mputreg(chip, DREG, byte);
0259     snd_mtpav_mputreg(chip, CREG, clrwrite);    // clear write bit
0260 
0261     snd_mtpav_mputreg(chip, CREG, setwrite);    // set write bit
0262 
0263 }
0264 
0265 
0266 /*
0267  */
0268 
0269 /* call this with spin lock held */
0270 static void snd_mtpav_output_port_write(struct mtpav *mtp_card,
0271                     struct mtpav_port *portp,
0272                     struct snd_rawmidi_substream *substream)
0273 {
0274     u8 outbyte;
0275 
0276     // Get the outbyte first, so we can emulate running status if
0277     // necessary
0278     if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1)
0279         return;
0280 
0281     // send port change command if necessary
0282 
0283     if (portp->hwport != mtp_card->outmidihwport) {
0284         mtp_card->outmidihwport = portp->hwport;
0285 
0286         snd_mtpav_send_byte(mtp_card, 0xf5);
0287         snd_mtpav_send_byte(mtp_card, portp->hwport);
0288         /*
0289         snd_printk(KERN_DEBUG "new outport: 0x%x\n",
0290                (unsigned int) portp->hwport);
0291         */
0292         if (!(outbyte & 0x80) && portp->running_status)
0293             snd_mtpav_send_byte(mtp_card, portp->running_status);
0294     }
0295 
0296     // send data
0297 
0298     do {
0299         if (outbyte & 0x80)
0300             portp->running_status = outbyte;
0301         
0302         snd_mtpav_send_byte(mtp_card, outbyte);
0303     } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1);
0304 }
0305 
0306 static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream)
0307 {
0308     struct mtpav *mtp_card = substream->rmidi->private_data;
0309     struct mtpav_port *portp = &mtp_card->ports[substream->number];
0310     unsigned long flags;
0311 
0312     spin_lock_irqsave(&mtp_card->spinlock, flags);
0313     snd_mtpav_output_port_write(mtp_card, portp, substream);
0314     spin_unlock_irqrestore(&mtp_card->spinlock, flags);
0315 }
0316 
0317 
0318 /*
0319  *      mtpav control
0320  */
0321 
0322 static void snd_mtpav_portscan(struct mtpav *chip)  // put mtp into smart routing mode
0323 {
0324     u8 p;
0325 
0326     for (p = 0; p < 8; p++) {
0327         snd_mtpav_send_byte(chip, 0xf5);
0328         snd_mtpav_send_byte(chip, p);
0329         snd_mtpav_send_byte(chip, 0xfe);
0330     }
0331 }
0332 
0333 /*
0334  */
0335 
0336 static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream)
0337 {
0338     struct mtpav *mtp_card = substream->rmidi->private_data;
0339     struct mtpav_port *portp = &mtp_card->ports[substream->number];
0340     unsigned long flags;
0341 
0342     spin_lock_irqsave(&mtp_card->spinlock, flags);
0343     portp->mode |= MTPAV_MODE_INPUT_OPENED;
0344     portp->input = substream;
0345     if (mtp_card->share_irq++ == 0)
0346         snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE));   // enable pport interrupts
0347     spin_unlock_irqrestore(&mtp_card->spinlock, flags);
0348     return 0;
0349 }
0350 
0351 /*
0352  */
0353 
0354 static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream)
0355 {
0356     struct mtpav *mtp_card = substream->rmidi->private_data;
0357     struct mtpav_port *portp = &mtp_card->ports[substream->number];
0358     unsigned long flags;
0359 
0360     spin_lock_irqsave(&mtp_card->spinlock, flags);
0361     portp->mode &= ~MTPAV_MODE_INPUT_OPENED;
0362     portp->input = NULL;
0363     if (--mtp_card->share_irq == 0)
0364         snd_mtpav_mputreg(mtp_card, CREG, 0);   // disable pport interrupts
0365     spin_unlock_irqrestore(&mtp_card->spinlock, flags);
0366     return 0;
0367 }
0368 
0369 /*
0370  */
0371 
0372 static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up)
0373 {
0374     struct mtpav *mtp_card = substream->rmidi->private_data;
0375     struct mtpav_port *portp = &mtp_card->ports[substream->number];
0376     unsigned long flags;
0377 
0378     spin_lock_irqsave(&mtp_card->spinlock, flags);
0379     if (up)
0380         portp->mode |= MTPAV_MODE_INPUT_TRIGGERED;
0381     else
0382         portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED;
0383     spin_unlock_irqrestore(&mtp_card->spinlock, flags);
0384 
0385 }
0386 
0387 
0388 /*
0389  * timer interrupt for outputs
0390  */
0391 
0392 static void snd_mtpav_output_timer(struct timer_list *t)
0393 {
0394     unsigned long flags;
0395     struct mtpav *chip = from_timer(chip, t, timer);
0396     int p;
0397 
0398     spin_lock_irqsave(&chip->spinlock, flags);
0399     /* reprogram timer */
0400     mod_timer(&chip->timer, 1 + jiffies);
0401     /* process each port */
0402     for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) {
0403         struct mtpav_port *portp = &chip->ports[p];
0404         if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
0405             snd_mtpav_output_port_write(chip, portp, portp->output);
0406     }
0407     spin_unlock_irqrestore(&chip->spinlock, flags);
0408 }
0409 
0410 /* spinlock held! */
0411 static void snd_mtpav_add_output_timer(struct mtpav *chip)
0412 {
0413     mod_timer(&chip->timer, 1 + jiffies);
0414 }
0415 
0416 /* spinlock held! */
0417 static void snd_mtpav_remove_output_timer(struct mtpav *chip)
0418 {
0419     del_timer(&chip->timer);
0420 }
0421 
0422 /*
0423  */
0424 
0425 static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream)
0426 {
0427     struct mtpav *mtp_card = substream->rmidi->private_data;
0428     struct mtpav_port *portp = &mtp_card->ports[substream->number];
0429     unsigned long flags;
0430 
0431     spin_lock_irqsave(&mtp_card->spinlock, flags);
0432     portp->mode |= MTPAV_MODE_OUTPUT_OPENED;
0433     portp->output = substream;
0434     spin_unlock_irqrestore(&mtp_card->spinlock, flags);
0435     return 0;
0436 };
0437 
0438 /*
0439  */
0440 
0441 static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream)
0442 {
0443     struct mtpav *mtp_card = substream->rmidi->private_data;
0444     struct mtpav_port *portp = &mtp_card->ports[substream->number];
0445     unsigned long flags;
0446 
0447     spin_lock_irqsave(&mtp_card->spinlock, flags);
0448     portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED;
0449     portp->output = NULL;
0450     spin_unlock_irqrestore(&mtp_card->spinlock, flags);
0451     return 0;
0452 };
0453 
0454 /*
0455  */
0456 
0457 static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up)
0458 {
0459     struct mtpav *mtp_card = substream->rmidi->private_data;
0460     struct mtpav_port *portp = &mtp_card->ports[substream->number];
0461     unsigned long flags;
0462 
0463     spin_lock_irqsave(&mtp_card->spinlock, flags);
0464     if (up) {
0465         if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) {
0466             if (mtp_card->istimer++ == 0)
0467                 snd_mtpav_add_output_timer(mtp_card);
0468             portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED;
0469         }
0470     } else {
0471         portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED;
0472         if (--mtp_card->istimer == 0)
0473             snd_mtpav_remove_output_timer(mtp_card);
0474     }
0475     spin_unlock_irqrestore(&mtp_card->spinlock, flags);
0476 
0477     if (up)
0478         snd_mtpav_output_write(substream);
0479 }
0480 
0481 /*
0482  * midi interrupt for inputs
0483  */
0484 
0485 static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte)
0486 {
0487     struct mtpav_port *portp;
0488 
0489     if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST)
0490         return;
0491 
0492     portp = &mcrd->ports[mcrd->inmidiport];
0493     if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED)
0494         snd_rawmidi_receive(portp->input, &inbyte, 1);
0495 }
0496 
0497 static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte)
0498 {
0499     if (inbyte >= 0xf8) {
0500         /* real-time midi code */
0501         snd_mtpav_inmidi_process(mcrd, inbyte);
0502         return;
0503     }
0504 
0505     if (mcrd->inmidistate == 0) {   // awaiting command
0506         if (inbyte == 0xf5) // MTP port #
0507             mcrd->inmidistate = 1;
0508         else
0509             snd_mtpav_inmidi_process(mcrd, inbyte);
0510     } else if (mcrd->inmidistate) {
0511         mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte);
0512         mcrd->inmidistate = 0;
0513     }
0514 }
0515 
0516 static void snd_mtpav_read_bytes(struct mtpav *mcrd)
0517 {
0518     u8 clrread, setread;
0519     u8 mtp_read_byte;
0520     u8 sr, cbyt;
0521     int i;
0522 
0523     u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
0524 
0525     /* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */
0526 
0527     if (!(sbyt & SIGS_BYTE))
0528         return;
0529 
0530     cbyt = snd_mtpav_getreg(mcrd, CREG);
0531     clrread = cbyt & (SIGC_READ ^ 0xff);
0532     setread = cbyt | SIGC_READ;
0533 
0534     do {
0535 
0536         mtp_read_byte = 0;
0537         for (i = 0; i < 4; i++) {
0538             snd_mtpav_mputreg(mcrd, CREG, setread);
0539             sr = snd_mtpav_getreg(mcrd, SREG);
0540             snd_mtpav_mputreg(mcrd, CREG, clrread);
0541 
0542             sr &= SIGS_IN0 | SIGS_IN1;
0543             sr >>= 4;
0544             mtp_read_byte |= sr << (i * 2);
0545         }
0546 
0547         snd_mtpav_inmidi_h(mcrd, mtp_read_byte);
0548 
0549         sbyt = snd_mtpav_getreg(mcrd, SREG);
0550 
0551     } while (sbyt & SIGS_BYTE);
0552 }
0553 
0554 static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
0555 {
0556     struct mtpav *mcard = dev_id;
0557 
0558     spin_lock(&mcard->spinlock);
0559     snd_mtpav_read_bytes(mcard);
0560     spin_unlock(&mcard->spinlock);
0561     return IRQ_HANDLED;
0562 }
0563 
0564 /*
0565  * get ISA resources
0566  */
0567 static int snd_mtpav_get_ISA(struct mtpav *mcard)
0568 {
0569     mcard->res_port = devm_request_region(mcard->card->dev, port, 3,
0570                           "MotuMTPAV MIDI");
0571     if (!mcard->res_port) {
0572         snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
0573         return -EBUSY;
0574     }
0575     mcard->port = port;
0576     if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0,
0577                  "MOTU MTPAV", mcard)) {
0578         snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
0579         return -EBUSY;
0580     }
0581     mcard->irq = irq;
0582     return 0;
0583 }
0584 
0585 
0586 /*
0587  */
0588 
0589 static const struct snd_rawmidi_ops snd_mtpav_output = {
0590     .open =     snd_mtpav_output_open,
0591     .close =    snd_mtpav_output_close,
0592     .trigger =  snd_mtpav_output_trigger,
0593 };
0594 
0595 static const struct snd_rawmidi_ops snd_mtpav_input = {
0596     .open =     snd_mtpav_input_open,
0597     .close =    snd_mtpav_input_close,
0598     .trigger =  snd_mtpav_input_trigger,
0599 };
0600 
0601 
0602 /*
0603  * get RAWMIDI resources
0604  */
0605 
0606 static void snd_mtpav_set_name(struct mtpav *chip,
0607                    struct snd_rawmidi_substream *substream)
0608 {
0609     if (substream->number >= 0 && substream->number < chip->num_ports)
0610         sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
0611     else if (substream->number >= 8 && substream->number < chip->num_ports * 2)
0612         sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1);
0613     else if (substream->number == chip->num_ports * 2)
0614         strcpy(substream->name, "MTP computer");
0615     else if (substream->number == chip->num_ports * 2 + 1)
0616         strcpy(substream->name, "MTP ADAT");
0617     else
0618         strcpy(substream->name, "MTP broadcast");
0619 }
0620 
0621 static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
0622 {
0623     int rval;
0624     struct snd_rawmidi *rawmidi;
0625     struct snd_rawmidi_substream *substream;
0626     struct list_head *list;
0627 
0628     if (hwports < 1)
0629         hwports = 1;
0630     else if (hwports > 8)
0631         hwports = 8;
0632     mcard->num_ports = hwports;
0633 
0634     rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0,
0635                    mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
0636                    mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
0637                    &mcard->rmidi);
0638     if (rval < 0)
0639         return rval;
0640     rawmidi = mcard->rmidi;
0641     rawmidi->private_data = mcard;
0642 
0643     list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
0644         substream = list_entry(list, struct snd_rawmidi_substream, list);
0645         snd_mtpav_set_name(mcard, substream);
0646         substream->ops = &snd_mtpav_input;
0647     }
0648     list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
0649         substream = list_entry(list, struct snd_rawmidi_substream, list);
0650         snd_mtpav_set_name(mcard, substream);
0651         substream->ops = &snd_mtpav_output;
0652         mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number);
0653     }
0654     rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
0655                    SNDRV_RAWMIDI_INFO_DUPLEX;
0656     sprintf(rawmidi->name, "MTP AV MIDI");
0657     return 0;
0658 }
0659 
0660 /*
0661  */
0662 
0663 static void snd_mtpav_free(struct snd_card *card)
0664 {
0665     struct mtpav *crd = card->private_data;
0666     unsigned long flags;
0667 
0668     spin_lock_irqsave(&crd->spinlock, flags);
0669     if (crd->istimer > 0)
0670         snd_mtpav_remove_output_timer(crd);
0671     spin_unlock_irqrestore(&crd->spinlock, flags);
0672 }
0673 
0674 /*
0675  */
0676 static int snd_mtpav_probe(struct platform_device *dev)
0677 {
0678     struct snd_card *card;
0679     int err;
0680     struct mtpav *mtp_card;
0681 
0682     err = snd_devm_card_new(&dev->dev, index, id, THIS_MODULE,
0683                 sizeof(*mtp_card), &card);
0684     if (err < 0)
0685         return err;
0686 
0687     mtp_card = card->private_data;
0688     spin_lock_init(&mtp_card->spinlock);
0689     mtp_card->card = card;
0690     mtp_card->irq = -1;
0691     mtp_card->share_irq = 0;
0692     mtp_card->inmidistate = 0;
0693     mtp_card->outmidihwport = 0xffffffff;
0694     timer_setup(&mtp_card->timer, snd_mtpav_output_timer, 0);
0695 
0696     err = snd_mtpav_get_RAWMIDI(mtp_card);
0697     if (err < 0)
0698         return err;
0699 
0700     mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST;
0701 
0702     err = snd_mtpav_get_ISA(mtp_card);
0703     if (err < 0)
0704         return err;
0705 
0706     strcpy(card->driver, "MTPAV");
0707     strcpy(card->shortname, "MTPAV on parallel port");
0708     snprintf(card->longname, sizeof(card->longname),
0709          "MTPAV on parallel port at 0x%lx", port);
0710 
0711     snd_mtpav_portscan(mtp_card);
0712 
0713     err = snd_card_register(mtp_card->card);
0714     if (err < 0)
0715         return err;
0716 
0717     card->private_free = snd_mtpav_free;
0718 
0719     platform_set_drvdata(dev, card);
0720     printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
0721     return 0;
0722 }
0723 
0724 #define SND_MTPAV_DRIVER    "snd_mtpav"
0725 
0726 static struct platform_driver snd_mtpav_driver = {
0727     .probe      = snd_mtpav_probe,
0728     .driver     = {
0729         .name   = SND_MTPAV_DRIVER,
0730     },
0731 };
0732 
0733 static int __init alsa_card_mtpav_init(void)
0734 {
0735     int err;
0736 
0737     err = platform_driver_register(&snd_mtpav_driver);
0738     if (err < 0)
0739         return err;
0740 
0741     device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);
0742     if (!IS_ERR(device)) {
0743         if (platform_get_drvdata(device))
0744             return 0;
0745         platform_device_unregister(device);
0746         err = -ENODEV;
0747     } else
0748         err = PTR_ERR(device);
0749     platform_driver_unregister(&snd_mtpav_driver);
0750     return err;
0751 }
0752 
0753 static void __exit alsa_card_mtpav_exit(void)
0754 {
0755     platform_device_unregister(device);
0756     platform_driver_unregister(&snd_mtpav_driver);
0757 }
0758 
0759 module_init(alsa_card_mtpav_init)
0760 module_exit(alsa_card_mtpav_exit)