mpu401_uart.c (15996B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 4 * Routines for control of MPU-401 in UART mode 5 * 6 * MPU-401 supports UART mode which is not capable generate transmit 7 * interrupts thus output is done via polling. Without interrupt, 8 * input is done also via polling. Do not expect good performance. 9 * 10 * 13-03-2003: 11 * Added support for different kind of hardware I/O. Build in choices 12 * are port and mmio. For other kind of I/O, set mpu->read and 13 * mpu->write to your own I/O functions. 14 */ 15 16#include <linux/io.h> 17#include <linux/delay.h> 18#include <linux/init.h> 19#include <linux/slab.h> 20#include <linux/ioport.h> 21#include <linux/module.h> 22#include <linux/interrupt.h> 23#include <linux/errno.h> 24#include <sound/core.h> 25#include <sound/mpu401.h> 26 27MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 28MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode"); 29MODULE_LICENSE("GPL"); 30 31static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu); 32static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu); 33 34/* 35 36 */ 37 38#define snd_mpu401_input_avail(mpu) \ 39 (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_RX_EMPTY)) 40#define snd_mpu401_output_ready(mpu) \ 41 (!(mpu->read(mpu, MPU401C(mpu)) & MPU401_TX_FULL)) 42 43/* Build in lowlevel io */ 44static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, 45 unsigned long addr) 46{ 47 outb(data, addr); 48} 49 50static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, 51 unsigned long addr) 52{ 53 return inb(addr); 54} 55 56static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, 57 unsigned long addr) 58{ 59 writeb(data, (void __iomem *)addr); 60} 61 62static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, 63 unsigned long addr) 64{ 65 return readb((void __iomem *)addr); 66} 67/* */ 68 69static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) 70{ 71 int timeout = 100000; 72 for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--) 73 mpu->read(mpu, MPU401D(mpu)); 74#ifdef CONFIG_SND_DEBUG 75 if (timeout <= 0) 76 snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", 77 mpu->read(mpu, MPU401C(mpu))); 78#endif 79} 80 81static void uart_interrupt_tx(struct snd_mpu401 *mpu) 82{ 83 unsigned long flags; 84 85 if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && 86 test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { 87 spin_lock_irqsave(&mpu->output_lock, flags); 88 snd_mpu401_uart_output_write(mpu); 89 spin_unlock_irqrestore(&mpu->output_lock, flags); 90 } 91} 92 93static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) 94{ 95 unsigned long flags; 96 97 if (mpu->info_flags & MPU401_INFO_INPUT) { 98 spin_lock_irqsave(&mpu->input_lock, flags); 99 if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) 100 snd_mpu401_uart_input_read(mpu); 101 else 102 snd_mpu401_uart_clear_rx(mpu); 103 spin_unlock_irqrestore(&mpu->input_lock, flags); 104 } 105 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) 106 /* ok. for better Tx performance try do some output 107 when input is done */ 108 uart_interrupt_tx(mpu); 109} 110 111/** 112 * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler 113 * @irq: the irq number 114 * @dev_id: mpu401 instance 115 * 116 * Processes the interrupt for MPU401-UART i/o. 117 * 118 * Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise. 119 */ 120irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id) 121{ 122 struct snd_mpu401 *mpu = dev_id; 123 124 if (!mpu) 125 return IRQ_NONE; 126 _snd_mpu401_uart_interrupt(mpu); 127 return IRQ_HANDLED; 128} 129 130EXPORT_SYMBOL(snd_mpu401_uart_interrupt); 131 132/** 133 * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler 134 * @irq: the irq number 135 * @dev_id: mpu401 instance 136 * 137 * Processes the interrupt for MPU401-UART output. 138 * 139 * Return: %IRQ_HANDLED if the interrupt was handled. %IRQ_NONE otherwise. 140 */ 141irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id) 142{ 143 struct snd_mpu401 *mpu = dev_id; 144 145 if (!mpu) 146 return IRQ_NONE; 147 uart_interrupt_tx(mpu); 148 return IRQ_HANDLED; 149} 150 151EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx); 152 153/* 154 * timer callback 155 * reprogram the timer and call the interrupt job 156 */ 157static void snd_mpu401_uart_timer(struct timer_list *t) 158{ 159 struct snd_mpu401 *mpu = from_timer(mpu, t, timer); 160 unsigned long flags; 161 162 spin_lock_irqsave(&mpu->timer_lock, flags); 163 /*mpu->mode |= MPU401_MODE_TIMER;*/ 164 mod_timer(&mpu->timer, 1 + jiffies); 165 spin_unlock_irqrestore(&mpu->timer_lock, flags); 166 if (mpu->rmidi) 167 _snd_mpu401_uart_interrupt(mpu); 168} 169 170/* 171 * initialize the timer callback if not programmed yet 172 */ 173static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) 174{ 175 unsigned long flags; 176 177 spin_lock_irqsave (&mpu->timer_lock, flags); 178 if (mpu->timer_invoked == 0) { 179 timer_setup(&mpu->timer, snd_mpu401_uart_timer, 0); 180 mod_timer(&mpu->timer, 1 + jiffies); 181 } 182 mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : 183 MPU401_MODE_OUTPUT_TIMER; 184 spin_unlock_irqrestore (&mpu->timer_lock, flags); 185} 186 187/* 188 * remove the timer callback if still active 189 */ 190static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) 191{ 192 unsigned long flags; 193 194 spin_lock_irqsave (&mpu->timer_lock, flags); 195 if (mpu->timer_invoked) { 196 mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : 197 ~MPU401_MODE_OUTPUT_TIMER; 198 if (! mpu->timer_invoked) 199 del_timer(&mpu->timer); 200 } 201 spin_unlock_irqrestore (&mpu->timer_lock, flags); 202} 203 204/* 205 * send a UART command 206 * return zero if successful, non-zero for some errors 207 */ 208 209static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, 210 int ack) 211{ 212 unsigned long flags; 213 int timeout, ok; 214 215 spin_lock_irqsave(&mpu->input_lock, flags); 216 if (mpu->hardware != MPU401_HW_TRID4DWAVE) { 217 mpu->write(mpu, 0x00, MPU401D(mpu)); 218 /*snd_mpu401_uart_clear_rx(mpu);*/ 219 } 220 /* ok. standard MPU-401 initialization */ 221 if (mpu->hardware != MPU401_HW_SB) { 222 for (timeout = 1000; timeout > 0 && 223 !snd_mpu401_output_ready(mpu); timeout--) 224 udelay(10); 225#ifdef CONFIG_SND_DEBUG 226 if (!timeout) 227 snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n", 228 mpu->read(mpu, MPU401C(mpu))); 229#endif 230 } 231 mpu->write(mpu, cmd, MPU401C(mpu)); 232 if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) { 233 ok = 0; 234 timeout = 10000; 235 while (!ok && timeout-- > 0) { 236 if (snd_mpu401_input_avail(mpu)) { 237 if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) 238 ok = 1; 239 } 240 } 241 if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) 242 ok = 1; 243 } else 244 ok = 1; 245 spin_unlock_irqrestore(&mpu->input_lock, flags); 246 if (!ok) { 247 snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx " 248 "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port, 249 mpu->read(mpu, MPU401C(mpu)), 250 mpu->read(mpu, MPU401D(mpu))); 251 return 1; 252 } 253 return 0; 254} 255 256static int snd_mpu401_do_reset(struct snd_mpu401 *mpu) 257{ 258 if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1)) 259 return -EIO; 260 if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 0)) 261 return -EIO; 262 return 0; 263} 264 265/* 266 * input/output open/close - protected by open_mutex in rawmidi.c 267 */ 268static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream) 269{ 270 struct snd_mpu401 *mpu; 271 int err; 272 273 mpu = substream->rmidi->private_data; 274 if (mpu->open_input) { 275 err = mpu->open_input(mpu); 276 if (err < 0) 277 return err; 278 } 279 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { 280 if (snd_mpu401_do_reset(mpu) < 0) 281 goto error_out; 282 } 283 mpu->substream_input = substream; 284 set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); 285 return 0; 286 287error_out: 288 if (mpu->open_input && mpu->close_input) 289 mpu->close_input(mpu); 290 return -EIO; 291} 292 293static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) 294{ 295 struct snd_mpu401 *mpu; 296 int err; 297 298 mpu = substream->rmidi->private_data; 299 if (mpu->open_output) { 300 err = mpu->open_output(mpu); 301 if (err < 0) 302 return err; 303 } 304 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { 305 if (snd_mpu401_do_reset(mpu) < 0) 306 goto error_out; 307 } 308 mpu->substream_output = substream; 309 set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); 310 return 0; 311 312error_out: 313 if (mpu->open_output && mpu->close_output) 314 mpu->close_output(mpu); 315 return -EIO; 316} 317 318static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream) 319{ 320 struct snd_mpu401 *mpu; 321 int err = 0; 322 323 mpu = substream->rmidi->private_data; 324 clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode); 325 mpu->substream_input = NULL; 326 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) 327 err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); 328 if (mpu->close_input) 329 mpu->close_input(mpu); 330 if (err) 331 return -EIO; 332 return 0; 333} 334 335static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) 336{ 337 struct snd_mpu401 *mpu; 338 int err = 0; 339 340 mpu = substream->rmidi->private_data; 341 clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode); 342 mpu->substream_output = NULL; 343 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) 344 err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0); 345 if (mpu->close_output) 346 mpu->close_output(mpu); 347 if (err) 348 return -EIO; 349 return 0; 350} 351 352/* 353 * trigger input callback 354 */ 355static void 356snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) 357{ 358 unsigned long flags; 359 struct snd_mpu401 *mpu; 360 int max = 64; 361 362 mpu = substream->rmidi->private_data; 363 if (up) { 364 if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, 365 &mpu->mode)) { 366 /* first time - flush FIFO */ 367 while (max-- > 0) 368 mpu->read(mpu, MPU401D(mpu)); 369 if (mpu->info_flags & MPU401_INFO_USE_TIMER) 370 snd_mpu401_uart_add_timer(mpu, 1); 371 } 372 373 /* read data in advance */ 374 spin_lock_irqsave(&mpu->input_lock, flags); 375 snd_mpu401_uart_input_read(mpu); 376 spin_unlock_irqrestore(&mpu->input_lock, flags); 377 } else { 378 if (mpu->info_flags & MPU401_INFO_USE_TIMER) 379 snd_mpu401_uart_remove_timer(mpu, 1); 380 clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode); 381 } 382 383} 384 385/* 386 * transfer input pending data 387 * call with input_lock spinlock held 388 */ 389static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu) 390{ 391 int max = 128; 392 unsigned char byte; 393 394 while (max-- > 0) { 395 if (! snd_mpu401_input_avail(mpu)) 396 break; /* input not available */ 397 byte = mpu->read(mpu, MPU401D(mpu)); 398 if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) 399 snd_rawmidi_receive(mpu->substream_input, &byte, 1); 400 } 401} 402 403/* 404 * Tx FIFO sizes: 405 * CS4237B - 16 bytes 406 * AudioDrive ES1688 - 12 bytes 407 * S3 SonicVibes - 8 bytes 408 * SoundBlaster AWE 64 - 2 bytes (ugly hardware) 409 */ 410 411/* 412 * write output pending bytes 413 * call with output_lock spinlock held 414 */ 415static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) 416{ 417 unsigned char byte; 418 int max = 256; 419 420 do { 421 if (snd_rawmidi_transmit_peek(mpu->substream_output, 422 &byte, 1) == 1) { 423 /* 424 * Try twice because there is hardware that insists on 425 * setting the output busy bit after each write. 426 */ 427 if (!snd_mpu401_output_ready(mpu) && 428 !snd_mpu401_output_ready(mpu)) 429 break; /* Tx FIFO full - try again later */ 430 mpu->write(mpu, byte, MPU401D(mpu)); 431 snd_rawmidi_transmit_ack(mpu->substream_output, 1); 432 } else { 433 snd_mpu401_uart_remove_timer (mpu, 0); 434 break; /* no other data - leave the tx loop */ 435 } 436 } while (--max > 0); 437} 438 439/* 440 * output trigger callback 441 */ 442static void 443snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) 444{ 445 unsigned long flags; 446 struct snd_mpu401 *mpu; 447 448 mpu = substream->rmidi->private_data; 449 if (up) { 450 set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); 451 452 /* try to add the timer at each output trigger, 453 * since the output timer might have been removed in 454 * snd_mpu401_uart_output_write(). 455 */ 456 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) 457 snd_mpu401_uart_add_timer(mpu, 0); 458 459 /* output pending data */ 460 spin_lock_irqsave(&mpu->output_lock, flags); 461 snd_mpu401_uart_output_write(mpu); 462 spin_unlock_irqrestore(&mpu->output_lock, flags); 463 } else { 464 if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) 465 snd_mpu401_uart_remove_timer(mpu, 0); 466 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); 467 } 468} 469 470/* 471 472 */ 473 474static const struct snd_rawmidi_ops snd_mpu401_uart_output = 475{ 476 .open = snd_mpu401_uart_output_open, 477 .close = snd_mpu401_uart_output_close, 478 .trigger = snd_mpu401_uart_output_trigger, 479}; 480 481static const struct snd_rawmidi_ops snd_mpu401_uart_input = 482{ 483 .open = snd_mpu401_uart_input_open, 484 .close = snd_mpu401_uart_input_close, 485 .trigger = snd_mpu401_uart_input_trigger, 486}; 487 488static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) 489{ 490 struct snd_mpu401 *mpu = rmidi->private_data; 491 if (mpu->irq >= 0) 492 free_irq(mpu->irq, (void *) mpu); 493 release_and_free_resource(mpu->res); 494 kfree(mpu); 495} 496 497/** 498 * snd_mpu401_uart_new - create an MPU401-UART instance 499 * @card: the card instance 500 * @device: the device index, zero-based 501 * @hardware: the hardware type, MPU401_HW_XXXX 502 * @port: the base address of MPU401 port 503 * @info_flags: bitflags MPU401_INFO_XXX 504 * @irq: the ISA irq number, -1 if not to be allocated 505 * @rrawmidi: the pointer to store the new rawmidi instance 506 * 507 * Creates a new MPU-401 instance. 508 * 509 * Note that the rawmidi instance is returned on the rrawmidi argument, 510 * not the mpu401 instance itself. To access to the mpu401 instance, 511 * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast). 512 * 513 * Return: Zero if successful, or a negative error code. 514 */ 515int snd_mpu401_uart_new(struct snd_card *card, int device, 516 unsigned short hardware, 517 unsigned long port, 518 unsigned int info_flags, 519 int irq, 520 struct snd_rawmidi ** rrawmidi) 521{ 522 struct snd_mpu401 *mpu; 523 struct snd_rawmidi *rmidi; 524 int in_enable, out_enable; 525 int err; 526 527 if (rrawmidi) 528 *rrawmidi = NULL; 529 if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT))) 530 info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT; 531 in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0; 532 out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0; 533 err = snd_rawmidi_new(card, "MPU-401U", device, 534 out_enable, in_enable, &rmidi); 535 if (err < 0) 536 return err; 537 mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); 538 if (!mpu) { 539 err = -ENOMEM; 540 goto free_device; 541 } 542 rmidi->private_data = mpu; 543 rmidi->private_free = snd_mpu401_uart_free; 544 spin_lock_init(&mpu->input_lock); 545 spin_lock_init(&mpu->output_lock); 546 spin_lock_init(&mpu->timer_lock); 547 mpu->hardware = hardware; 548 mpu->irq = -1; 549 if (! (info_flags & MPU401_INFO_INTEGRATED)) { 550 int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; 551 mpu->res = request_region(port, res_size, "MPU401 UART"); 552 if (!mpu->res) { 553 snd_printk(KERN_ERR "mpu401_uart: " 554 "unable to grab port 0x%lx size %d\n", 555 port, res_size); 556 err = -EBUSY; 557 goto free_device; 558 } 559 } 560 if (info_flags & MPU401_INFO_MMIO) { 561 mpu->write = mpu401_write_mmio; 562 mpu->read = mpu401_read_mmio; 563 } else { 564 mpu->write = mpu401_write_port; 565 mpu->read = mpu401_read_port; 566 } 567 mpu->port = port; 568 if (hardware == MPU401_HW_PC98II) 569 mpu->cport = port + 2; 570 else 571 mpu->cport = port + 1; 572 if (irq >= 0) { 573 if (request_irq(irq, snd_mpu401_uart_interrupt, 0, 574 "MPU401 UART", (void *) mpu)) { 575 snd_printk(KERN_ERR "mpu401_uart: " 576 "unable to grab IRQ %d\n", irq); 577 err = -EBUSY; 578 goto free_device; 579 } 580 } 581 if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK)) 582 info_flags |= MPU401_INFO_USE_TIMER; 583 mpu->info_flags = info_flags; 584 mpu->irq = irq; 585 if (card->shortname[0]) 586 snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", 587 card->shortname); 588 else 589 sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); 590 if (out_enable) { 591 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 592 &snd_mpu401_uart_output); 593 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; 594 } 595 if (in_enable) { 596 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 597 &snd_mpu401_uart_input); 598 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; 599 if (out_enable) 600 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; 601 } 602 mpu->rmidi = rmidi; 603 if (rrawmidi) 604 *rrawmidi = rmidi; 605 return 0; 606free_device: 607 snd_device_free(card, rmidi); 608 return err; 609} 610 611EXPORT_SYMBOL(snd_mpu401_uart_new);