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) 771