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