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