linux/sound/drivers/mpu401/mpu401_uart.c
<<
>>
Prefs
   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);
 612