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