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 #include <linux/string.h> 50 51 /* 52 * globals 53 */ 54 MODULE_AUTHOR("Michael T. Mayers"); 55 MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI"); 56 MODULE_LICENSE("GPL"); 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 if (!(outbyte & 0x80) && portp->running_status) 290 snd_mtpav_send_byte(mtp_card, portp->running_status); 291 } 292 293 // send data 294 295 do { 296 if (outbyte & 0x80) 297 portp->running_status = outbyte; 298 299 snd_mtpav_send_byte(mtp_card, outbyte); 300 } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1); 301 } 302 303 static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream) 304 { 305 struct mtpav *mtp_card = substream->rmidi->private_data; 306 struct mtpav_port *portp = &mtp_card->ports[substream->number]; 307 308 guard(spinlock_irqsave)(&mtp_card->spinlock); 309 snd_mtpav_output_port_write(mtp_card, portp, substream); 310 } 311 312 313 /* 314 * mtpav control 315 */ 316 317 static void snd_mtpav_portscan(struct mtpav *chip) // put mtp into smart routing mode 318 { 319 u8 p; 320 321 for (p = 0; p < 8; p++) { 322 snd_mtpav_send_byte(chip, 0xf5); 323 snd_mtpav_send_byte(chip, p); 324 snd_mtpav_send_byte(chip, 0xfe); 325 } 326 } 327 328 /* 329 */ 330 331 static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream) 332 { 333 struct mtpav *mtp_card = substream->rmidi->private_data; 334 struct mtpav_port *portp = &mtp_card->ports[substream->number]; 335 336 guard(spinlock_irqsave)(&mtp_card->spinlock); 337 portp->mode |= MTPAV_MODE_INPUT_OPENED; 338 portp->input = substream; 339 if (mtp_card->share_irq++ == 0) 340 snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE)); // enable pport interrupts 341 return 0; 342 } 343 344 /* 345 */ 346 347 static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream) 348 { 349 struct mtpav *mtp_card = substream->rmidi->private_data; 350 struct mtpav_port *portp = &mtp_card->ports[substream->number]; 351 352 guard(spinlock_irqsave)(&mtp_card->spinlock); 353 portp->mode &= ~MTPAV_MODE_INPUT_OPENED; 354 portp->input = NULL; 355 if (--mtp_card->share_irq == 0) 356 snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts 357 return 0; 358 } 359 360 /* 361 */ 362 363 static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up) 364 { 365 struct mtpav *mtp_card = substream->rmidi->private_data; 366 struct mtpav_port *portp = &mtp_card->ports[substream->number]; 367 368 guard(spinlock_irqsave)(&mtp_card->spinlock); 369 if (up) 370 portp->mode |= MTPAV_MODE_INPUT_TRIGGERED; 371 else 372 portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED; 373 } 374 375 376 /* 377 * timer interrupt for outputs 378 */ 379 380 static void snd_mtpav_output_timer(struct timer_list *t) 381 { 382 struct mtpav *chip = timer_container_of(chip, t, timer); 383 int p; 384 385 guard(spinlock_irqsave)(&chip->spinlock); 386 /* reprogram timer */ 387 mod_timer(&chip->timer, 1 + jiffies); 388 /* process each port */ 389 for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) { 390 struct mtpav_port *portp = &chip->ports[p]; 391 if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output) 392 snd_mtpav_output_port_write(chip, portp, portp->output); 393 } 394 } 395 396 /* spinlock held! */ 397 static void snd_mtpav_add_output_timer(struct mtpav *chip) 398 { 399 mod_timer(&chip->timer, 1 + jiffies); 400 } 401 402 /* spinlock held! */ 403 static void snd_mtpav_remove_output_timer(struct mtpav *chip) 404 { 405 timer_delete(&chip->timer); 406 } 407 408 /* 409 */ 410 411 static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream) 412 { 413 struct mtpav *mtp_card = substream->rmidi->private_data; 414 struct mtpav_port *portp = &mtp_card->ports[substream->number]; 415 416 guard(spinlock_irqsave)(&mtp_card->spinlock); 417 portp->mode |= MTPAV_MODE_OUTPUT_OPENED; 418 portp->output = substream; 419 return 0; 420 }; 421 422 /* 423 */ 424 425 static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream) 426 { 427 struct mtpav *mtp_card = substream->rmidi->private_data; 428 struct mtpav_port *portp = &mtp_card->ports[substream->number]; 429 430 guard(spinlock_irqsave)(&mtp_card->spinlock); 431 portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED; 432 portp->output = NULL; 433 return 0; 434 }; 435 436 /* 437 */ 438 439 static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up) 440 { 441 struct mtpav *mtp_card = substream->rmidi->private_data; 442 struct mtpav_port *portp = &mtp_card->ports[substream->number]; 443 444 scoped_guard(spinlock_irqsave, &mtp_card->spinlock) { 445 if (up) { 446 if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) { 447 if (mtp_card->istimer++ == 0) 448 snd_mtpav_add_output_timer(mtp_card); 449 portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED; 450 } 451 } else { 452 portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED; 453 if (--mtp_card->istimer == 0) 454 snd_mtpav_remove_output_timer(mtp_card); 455 } 456 } 457 458 if (up) 459 snd_mtpav_output_write(substream); 460 } 461 462 /* 463 * midi interrupt for inputs 464 */ 465 466 static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte) 467 { 468 struct mtpav_port *portp; 469 470 if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST) 471 return; 472 473 portp = &mcrd->ports[mcrd->inmidiport]; 474 if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) 475 snd_rawmidi_receive(portp->input, &inbyte, 1); 476 } 477 478 static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte) 479 { 480 if (inbyte >= 0xf8) { 481 /* real-time midi code */ 482 snd_mtpav_inmidi_process(mcrd, inbyte); 483 return; 484 } 485 486 if (mcrd->inmidistate == 0) { // awaiting command 487 if (inbyte == 0xf5) // MTP port # 488 mcrd->inmidistate = 1; 489 else 490 snd_mtpav_inmidi_process(mcrd, inbyte); 491 } else if (mcrd->inmidistate) { 492 mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte); 493 mcrd->inmidistate = 0; 494 } 495 } 496 497 static void snd_mtpav_read_bytes(struct mtpav *mcrd) 498 { 499 u8 clrread, setread; 500 u8 mtp_read_byte; 501 u8 sr, cbyt; 502 int i; 503 504 u8 sbyt = snd_mtpav_getreg(mcrd, SREG); 505 506 if (!(sbyt & SIGS_BYTE)) 507 return; 508 509 cbyt = snd_mtpav_getreg(mcrd, CREG); 510 clrread = cbyt & (SIGC_READ ^ 0xff); 511 setread = cbyt | SIGC_READ; 512 513 do { 514 515 mtp_read_byte = 0; 516 for (i = 0; i < 4; i++) { 517 snd_mtpav_mputreg(mcrd, CREG, setread); 518 sr = snd_mtpav_getreg(mcrd, SREG); 519 snd_mtpav_mputreg(mcrd, CREG, clrread); 520 521 sr &= SIGS_IN0 | SIGS_IN1; 522 sr >>= 4; 523 mtp_read_byte |= sr << (i * 2); 524 } 525 526 snd_mtpav_inmidi_h(mcrd, mtp_read_byte); 527 528 sbyt = snd_mtpav_getreg(mcrd, SREG); 529 530 } while (sbyt & SIGS_BYTE); 531 } 532 533 static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) 534 { 535 struct mtpav *mcard = dev_id; 536 537 guard(spinlock)(&mcard->spinlock); 538 snd_mtpav_read_bytes(mcard); 539 return IRQ_HANDLED; 540 } 541 542 /* 543 * get ISA resources 544 */ 545 static int snd_mtpav_get_ISA(struct mtpav *mcard) 546 { 547 mcard->res_port = devm_request_region(mcard->card->dev, port, 3, 548 "MotuMTPAV MIDI"); 549 if (!mcard->res_port) { 550 dev_err(mcard->card->dev, "MTVAP port 0x%lx is busy\n", port); 551 return -EBUSY; 552 } 553 mcard->port = port; 554 if (devm_request_irq(mcard->card->dev, irq, snd_mtpav_irqh, 0, 555 "MOTU MTPAV", mcard)) { 556 dev_err(mcard->card->dev, "MTVAP IRQ %d busy\n", irq); 557 return -EBUSY; 558 } 559 mcard->irq = irq; 560 return 0; 561 } 562 563 564 /* 565 */ 566 567 static const struct snd_rawmidi_ops snd_mtpav_output = { 568 .open = snd_mtpav_output_open, 569 .close = snd_mtpav_output_close, 570 .trigger = snd_mtpav_output_trigger, 571 }; 572 573 static const struct snd_rawmidi_ops snd_mtpav_input = { 574 .open = snd_mtpav_input_open, 575 .close = snd_mtpav_input_close, 576 .trigger = snd_mtpav_input_trigger, 577 }; 578 579 580 /* 581 * get RAWMIDI resources 582 */ 583 584 static void snd_mtpav_set_name(struct mtpav *chip, 585 struct snd_rawmidi_substream *substream) 586 { 587 if (substream->number >= 0 && substream->number < chip->num_ports) 588 sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1); 589 else if (substream->number >= 8 && substream->number < chip->num_ports * 2) 590 sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1); 591 else if (substream->number == chip->num_ports * 2) 592 strscpy(substream->name, "MTP computer"); 593 else if (substream->number == chip->num_ports * 2 + 1) 594 strscpy(substream->name, "MTP ADAT"); 595 else 596 strscpy(substream->name, "MTP broadcast"); 597 } 598 599 static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard) 600 { 601 int rval; 602 struct snd_rawmidi *rawmidi; 603 struct snd_rawmidi_substream *substream; 604 struct list_head *list; 605 606 if (hwports < 1) 607 hwports = 1; 608 else if (hwports > 8) 609 hwports = 8; 610 mcard->num_ports = hwports; 611 612 rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, 613 mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, 614 mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, 615 &mcard->rmidi); 616 if (rval < 0) 617 return rval; 618 rawmidi = mcard->rmidi; 619 rawmidi->private_data = mcard; 620 621 list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { 622 substream = list_entry(list, struct snd_rawmidi_substream, list); 623 snd_mtpav_set_name(mcard, substream); 624 substream->ops = &snd_mtpav_input; 625 } 626 list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { 627 substream = list_entry(list, struct snd_rawmidi_substream, list); 628 snd_mtpav_set_name(mcard, substream); 629 substream->ops = &snd_mtpav_output; 630 mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number); 631 } 632 rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | 633 SNDRV_RAWMIDI_INFO_DUPLEX; 634 sprintf(rawmidi->name, "MTP AV MIDI"); 635 return 0; 636 } 637 638 /* 639 */ 640 641 static void snd_mtpav_free(struct snd_card *card) 642 { 643 struct mtpav *crd = card->private_data; 644 645 guard(spinlock_irqsave)(&crd->spinlock); 646 if (crd->istimer > 0) 647 snd_mtpav_remove_output_timer(crd); 648 } 649 650 /* 651 */ 652 static int snd_mtpav_probe(struct platform_device *dev) 653 { 654 struct snd_card *card; 655 int err; 656 struct mtpav *mtp_card; 657 658 err = snd_devm_card_new(&dev->dev, index, id, THIS_MODULE, 659 sizeof(*mtp_card), &card); 660 if (err < 0) 661 return err; 662 663 mtp_card = card->private_data; 664 spin_lock_init(&mtp_card->spinlock); 665 mtp_card->card = card; 666 mtp_card->irq = -1; 667 mtp_card->share_irq = 0; 668 mtp_card->inmidistate = 0; 669 mtp_card->outmidihwport = 0xffffffff; 670 timer_setup(&mtp_card->timer, snd_mtpav_output_timer, 0); 671 672 err = snd_mtpav_get_RAWMIDI(mtp_card); 673 if (err < 0) 674 return err; 675 676 mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST; 677 678 err = snd_mtpav_get_ISA(mtp_card); 679 if (err < 0) 680 return err; 681 682 strscpy(card->driver, "MTPAV"); 683 strscpy(card->shortname, "MTPAV on parallel port"); 684 snprintf(card->longname, sizeof(card->longname), 685 "MTPAV on parallel port at 0x%lx", port); 686 687 snd_mtpav_portscan(mtp_card); 688 689 err = snd_card_register(mtp_card->card); 690 if (err < 0) 691 return err; 692 693 card->private_free = snd_mtpav_free; 694 695 platform_set_drvdata(dev, card); 696 dev_info(card->dev, 697 "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", 698 irq, port); 699 return 0; 700 } 701 702 #define SND_MTPAV_DRIVER "snd_mtpav" 703 704 static struct platform_driver snd_mtpav_driver = { 705 .probe = snd_mtpav_probe, 706 .driver = { 707 .name = SND_MTPAV_DRIVER, 708 }, 709 }; 710 711 static int __init alsa_card_mtpav_init(void) 712 { 713 int err; 714 715 err = platform_driver_register(&snd_mtpav_driver); 716 if (err < 0) 717 return err; 718 719 device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); 720 if (!IS_ERR(device)) { 721 if (platform_get_drvdata(device)) 722 return 0; 723 platform_device_unregister(device); 724 err = -ENODEV; 725 } else 726 err = PTR_ERR(device); 727 platform_driver_unregister(&snd_mtpav_driver); 728 return err; 729 } 730 731 static void __exit alsa_card_mtpav_exit(void) 732 { 733 platform_device_unregister(device); 734 platform_driver_unregister(&snd_mtpav_driver); 735 } 736 737 module_init(alsa_card_mtpav_init) 738 module_exit(alsa_card_mtpav_exit) 739