]> err.no Git - linux-2.6/blob - sound/drivers/mpu401/mpu401_uart.c
[ALSA] mpu401_uart - Fix coding style and code clean up
[linux-2.6] / sound / drivers / mpu401 / mpu401_uart.c
1 /*
2  *  Copyright (c) by Jaroslav Kysela <perex@suse.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@suse.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 _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
99 {
100         spin_lock(&mpu->input_lock);
101         if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
102                 snd_mpu401_uart_input_read(mpu);
103         else
104                 snd_mpu401_uart_clear_rx(mpu);
105         spin_unlock(&mpu->input_lock);
106         /* ok. for better Tx performance try do some output when
107          * input is done
108          */
109         if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
110             test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
111                 spin_lock(&mpu->output_lock);
112                 snd_mpu401_uart_output_write(mpu);
113                 spin_unlock(&mpu->output_lock);
114         }
115 }
116
117 /**
118  * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
119  * @irq: the irq number
120  * @dev_id: mpu401 instance
121  * @regs: the reigster
122  *
123  * Processes the interrupt for MPU401-UART i/o.
124  */
125 irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id,
126                                       struct pt_regs *regs)
127 {
128         struct snd_mpu401 *mpu = dev_id;
129         
130         if (mpu == NULL)
131                 return IRQ_NONE;
132         _snd_mpu401_uart_interrupt(mpu);
133         return IRQ_HANDLED;
134 }
135
136 EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
137
138 /*
139  * timer callback
140  * reprogram the timer and call the interrupt job
141  */
142 static void snd_mpu401_uart_timer(unsigned long data)
143 {
144         struct snd_mpu401 *mpu = (struct snd_mpu401 *)data;
145         unsigned long flags;
146
147         spin_lock_irqsave(&mpu->timer_lock, flags);
148         /*mpu->mode |= MPU401_MODE_TIMER;*/
149         mpu->timer.expires = 1 + jiffies;
150         add_timer(&mpu->timer);
151         spin_unlock_irqrestore(&mpu->timer_lock, flags);
152         if (mpu->rmidi)
153                 _snd_mpu401_uart_interrupt(mpu);
154 }
155
156 /*
157  * initialize the timer callback if not programmed yet
158  */
159 static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input)
160 {
161         unsigned long flags;
162
163         spin_lock_irqsave (&mpu->timer_lock, flags);
164         if (mpu->timer_invoked == 0) {
165                 init_timer(&mpu->timer);
166                 mpu->timer.data = (unsigned long)mpu;
167                 mpu->timer.function = snd_mpu401_uart_timer;
168                 mpu->timer.expires = 1 + jiffies;
169                 add_timer(&mpu->timer);
170         } 
171         mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER :
172                 MPU401_MODE_OUTPUT_TIMER;
173         spin_unlock_irqrestore (&mpu->timer_lock, flags);
174 }
175
176 /*
177  * remove the timer callback if still active
178  */
179 static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
180 {
181         unsigned long flags;
182
183         spin_lock_irqsave (&mpu->timer_lock, flags);
184         if (mpu->timer_invoked) {
185                 mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER :
186                         ~MPU401_MODE_OUTPUT_TIMER;
187                 if (! mpu->timer_invoked)
188                         del_timer(&mpu->timer);
189         }
190         spin_unlock_irqrestore (&mpu->timer_lock, flags);
191 }
192
193 /*
194  * send a UART command
195  * return zero if successful, non-zero for some errors
196  */
197
198 static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
199                                int ack)
200 {
201         unsigned long flags;
202         int timeout, ok;
203
204         spin_lock_irqsave(&mpu->input_lock, flags);
205         if (mpu->hardware != MPU401_HW_TRID4DWAVE) {
206                 mpu->write(mpu, 0x00, MPU401D(mpu));
207                 /*snd_mpu401_uart_clear_rx(mpu);*/
208         }
209         /* ok. standard MPU-401 initialization */
210         if (mpu->hardware != MPU401_HW_SB) {
211                 for (timeout = 1000; timeout > 0 &&
212                              !snd_mpu401_output_ready(mpu); timeout--)
213                         udelay(10);
214 #ifdef CONFIG_SND_DEBUG
215                 if (!timeout)
216                         snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n",
217                                    mpu->read(mpu, MPU401C(mpu)));
218 #endif
219         }
220         mpu->write(mpu, cmd, MPU401C(mpu));
221         if (ack) {
222                 ok = 0;
223                 timeout = 10000;
224                 while (!ok && timeout-- > 0) {
225                         if (snd_mpu401_input_avail(mpu)) {
226                                 if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
227                                         ok = 1;
228                         }
229                 }
230                 if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
231                         ok = 1;
232         } else
233                 ok = 1;
234         spin_unlock_irqrestore(&mpu->input_lock, flags);
235         if (!ok) {
236                 snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx "
237                            "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port,
238                            mpu->read(mpu, MPU401C(mpu)),
239                            mpu->read(mpu, MPU401D(mpu)));
240                 return 1;
241         }
242         return 0;
243 }
244
245 /*
246  * input/output open/close - protected by open_mutex in rawmidi.c
247  */
248 static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
249 {
250         struct snd_mpu401 *mpu;
251         int err;
252
253         mpu = substream->rmidi->private_data;
254         if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
255                 return err;
256         if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
257                 if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
258                         goto error_out;
259                 if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
260                         goto error_out;
261         }
262         mpu->substream_input = substream;
263         set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
264         return 0;
265
266 error_out:
267         if (mpu->open_input && mpu->close_input)
268                 mpu->close_input(mpu);
269         return -EIO;
270 }
271
272 static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
273 {
274         struct snd_mpu401 *mpu;
275         int err;
276
277         mpu = substream->rmidi->private_data;
278         if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
279                 return err;
280         if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
281                 if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
282                         goto error_out;
283                 if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
284                         goto error_out;
285         }
286         mpu->substream_output = substream;
287         set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
288         return 0;
289
290 error_out:
291         if (mpu->open_output && mpu->close_output)
292                 mpu->close_output(mpu);
293         return -EIO;
294 }
295
296 static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
297 {
298         struct snd_mpu401 *mpu;
299         int err = 0;
300
301         mpu = substream->rmidi->private_data;
302         clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
303         mpu->substream_input = NULL;
304         if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
305                 err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
306         if (mpu->close_input)
307                 mpu->close_input(mpu);
308         if (err)
309                 return -EIO;
310         return 0;
311 }
312
313 static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
314 {
315         struct snd_mpu401 *mpu;
316         int err = 0;
317
318         mpu = substream->rmidi->private_data;
319         clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
320         mpu->substream_output = NULL;
321         if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
322                 err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
323         if (mpu->close_output)
324                 mpu->close_output(mpu);
325         if (err)
326                 return -EIO;
327         return 0;
328 }
329
330 /*
331  * trigger input callback
332  */
333 static void
334 snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
335 {
336         unsigned long flags;
337         struct snd_mpu401 *mpu;
338         int max = 64;
339
340         mpu = substream->rmidi->private_data;
341         if (up) {
342                 if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER,
343                                        &mpu->mode)) {
344                         /* first time - flush FIFO */
345                         while (max-- > 0)
346                                 mpu->read(mpu, MPU401D(mpu));
347                         if (mpu->irq < 0)
348                                 snd_mpu401_uart_add_timer(mpu, 1);
349                 }
350                 
351                 /* read data in advance */
352                 spin_lock_irqsave(&mpu->input_lock, flags);
353                 snd_mpu401_uart_input_read(mpu);
354                 spin_unlock_irqrestore(&mpu->input_lock, flags);
355         } else {
356                 if (mpu->irq < 0)
357                         snd_mpu401_uart_remove_timer(mpu, 1);
358                 clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
359         }
360
361 }
362
363 /*
364  * transfer input pending data
365  * call with input_lock spinlock held
366  */
367 static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
368 {
369         int max = 128;
370         unsigned char byte;
371
372         while (max-- > 0) {
373                 if (! snd_mpu401_input_avail(mpu))
374                         break; /* input not available */
375                 byte = mpu->read(mpu, MPU401D(mpu));
376                 if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
377                         snd_rawmidi_receive(mpu->substream_input, &byte, 1);
378         }
379 }
380
381 /*
382  *  Tx FIFO sizes:
383  *    CS4237B                   - 16 bytes
384  *    AudioDrive ES1688         - 12 bytes
385  *    S3 SonicVibes             -  8 bytes
386  *    SoundBlaster AWE 64       -  2 bytes (ugly hardware)
387  */
388
389 /*
390  * write output pending bytes
391  * call with output_lock spinlock held
392  */
393 static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
394 {
395         unsigned char byte;
396         int max = 256, timeout;
397
398         do {
399                 if (snd_rawmidi_transmit_peek(mpu->substream_output,
400                                               &byte, 1) == 1) {
401                         for (timeout = 100; timeout > 0; timeout--) {
402                                 if (snd_mpu401_output_ready(mpu))
403                                         break;
404                         }
405                         if (timeout == 0)
406                                 break;  /* Tx FIFO full - try again later */
407                         mpu->write(mpu, byte, MPU401D(mpu));
408                         snd_rawmidi_transmit_ack(mpu->substream_output, 1);
409                 } else {
410                         snd_mpu401_uart_remove_timer (mpu, 0);
411                         break;  /* no other data - leave the tx loop */
412                 }
413         } while (--max > 0);
414 }
415
416 /*
417  * output trigger callback
418  */
419 static void
420 snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
421 {
422         unsigned long flags;
423         struct snd_mpu401 *mpu;
424
425         mpu = substream->rmidi->private_data;
426         if (up) {
427                 set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
428
429                 /* try to add the timer at each output trigger,
430                  * since the output timer might have been removed in
431                  * snd_mpu401_uart_output_write().
432                  */
433                 snd_mpu401_uart_add_timer(mpu, 0);
434
435                 /* output pending data */
436                 spin_lock_irqsave(&mpu->output_lock, flags);
437                 snd_mpu401_uart_output_write(mpu);
438                 spin_unlock_irqrestore(&mpu->output_lock, flags);
439         } else {
440                 snd_mpu401_uart_remove_timer(mpu, 0);
441                 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
442         }
443 }
444
445 /*
446
447  */
448
449 static struct snd_rawmidi_ops snd_mpu401_uart_output =
450 {
451         .open =         snd_mpu401_uart_output_open,
452         .close =        snd_mpu401_uart_output_close,
453         .trigger =      snd_mpu401_uart_output_trigger,
454 };
455
456 static struct snd_rawmidi_ops snd_mpu401_uart_input =
457 {
458         .open =         snd_mpu401_uart_input_open,
459         .close =        snd_mpu401_uart_input_close,
460         .trigger =      snd_mpu401_uart_input_trigger,
461 };
462
463 static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
464 {
465         struct snd_mpu401 *mpu = rmidi->private_data;
466         if (mpu->irq_flags && mpu->irq >= 0)
467                 free_irq(mpu->irq, (void *) mpu);
468         release_and_free_resource(mpu->res);
469         kfree(mpu);
470 }
471
472 /**
473  * snd_mpu401_uart_new - create an MPU401-UART instance
474  * @card: the card instance
475  * @device: the device index, zero-based
476  * @hardware: the hardware type, MPU401_HW_XXXX
477  * @port: the base address of MPU401 port
478  * @integrated: non-zero if the port was already reserved by the chip
479  * @irq: the irq number, -1 if no interrupt for mpu
480  * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
481  * @rrawmidi: the pointer to store the new rawmidi instance
482  *
483  * Creates a new MPU-401 instance.
484  *
485  * Note that the rawmidi instance is returned on the rrawmidi argument,
486  * not the mpu401 instance itself.  To access to the mpu401 instance,
487  * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
488  *
489  * Returns zero if successful, or a negative error code.
490  */
491 int snd_mpu401_uart_new(struct snd_card *card, int device,
492                         unsigned short hardware,
493                         unsigned long port, int integrated,
494                         int irq, int irq_flags,
495                         struct snd_rawmidi ** rrawmidi)
496 {
497         struct snd_mpu401 *mpu;
498         struct snd_rawmidi *rmidi;
499         int err;
500
501         if (rrawmidi)
502                 *rrawmidi = NULL;
503         if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
504                 return err;
505         mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
506         if (mpu == NULL) {
507                 snd_printk(KERN_ERR "mpu401_uart: cannot allocate\n");
508                 snd_device_free(card, rmidi);
509                 return -ENOMEM;
510         }
511         rmidi->private_data = mpu;
512         rmidi->private_free = snd_mpu401_uart_free;
513         spin_lock_init(&mpu->input_lock);
514         spin_lock_init(&mpu->output_lock);
515         spin_lock_init(&mpu->timer_lock);
516         mpu->hardware = hardware;
517         if (!integrated) {
518                 int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
519                 mpu->res = request_region(port, res_size, "MPU401 UART");
520                 if (mpu->res == NULL) {
521                         snd_printk(KERN_ERR "mpu401_uart: "
522                                    "unable to grab port 0x%lx size %d\n",
523                                    port, res_size);
524                         snd_device_free(card, rmidi);
525                         return -EBUSY;
526                 }
527         }
528         switch (hardware) {
529         case MPU401_HW_AUREAL:
530                 mpu->write = mpu401_write_mmio;
531                 mpu->read = mpu401_read_mmio;
532                 break;
533         default:
534                 mpu->write = mpu401_write_port;
535                 mpu->read = mpu401_read_port;
536                 break;
537         }
538         mpu->port = port;
539         if (hardware == MPU401_HW_PC98II)
540                 mpu->cport = port + 2;
541         else
542                 mpu->cport = port + 1;
543         if (irq >= 0 && irq_flags) {
544                 if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags,
545                                 "MPU401 UART", (void *) mpu)) {
546                         snd_printk(KERN_ERR "mpu401_uart: "
547                                    "unable to grab IRQ %d\n", irq);
548                         snd_device_free(card, rmidi);
549                         return -EBUSY;
550                 }
551         }
552         mpu->irq = irq;
553         mpu->irq_flags = irq_flags;
554         if (card->shortname[0])
555                 snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI",
556                          card->shortname);
557         else
558                 sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device);
559         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
560                             &snd_mpu401_uart_output);
561         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
562                             &snd_mpu401_uart_input);
563         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
564                              SNDRV_RAWMIDI_INFO_INPUT |
565                              SNDRV_RAWMIDI_INFO_DUPLEX;
566         mpu->rmidi = rmidi;
567         if (rrawmidi)
568                 *rrawmidi = rmidi;
569         return 0;
570 }
571
572 EXPORT_SYMBOL(snd_mpu401_uart_new);
573
574 /*
575  *  INIT part
576  */
577
578 static int __init alsa_mpu401_uart_init(void)
579 {
580         return 0;
581 }
582
583 static void __exit alsa_mpu401_uart_exit(void)
584 {
585 }
586
587 module_init(alsa_mpu401_uart_init)
588 module_exit(alsa_mpu401_uart_exit)