OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [sound/] [drivers/] [mpu401/] [mpu401_uart.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.