xref: /openbmc/linux/sound/pci/au88x0/au88x0_mpu401.c (revision 64c70b1c)
1 /*
2  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3  *  Routines for control of MPU-401 in UART mode
4  *
5  *   Modified for the Aureal Vortex based Soundcards
6  *   by Manuel Jander (mjande@embedded.cl).
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  */
23 
24 #include <sound/driver.h>
25 #include <linux/time.h>
26 #include <linux/init.h>
27 #include <sound/core.h>
28 #include <sound/mpu401.h>
29 #include "au88x0.h"
30 
31 /* Check for mpu401 mmio support. */
32 /* MPU401 legacy support is only provided as a emergency fallback *
33  * for older versions of ALSA. Its usage is strongly discouraged. */
34 #ifndef MPU401_HW_AUREAL
35 #define VORTEX_MPU401_LEGACY
36 #endif
37 
38 /* Vortex MPU401 defines. */
39 #define MIDI_CLOCK_DIV      0x61
40 /* Standart MPU401 defines. */
41 #define MPU401_RESET		0xff
42 #define MPU401_ENTER_UART	0x3f
43 #define MPU401_ACK		    0xfe
44 
45 static int __devinit snd_vortex_midi(vortex_t * vortex)
46 {
47 	struct snd_rawmidi *rmidi;
48 	int temp, mode;
49 	struct snd_mpu401 *mpu;
50 	unsigned long port;
51 
52 #ifdef VORTEX_MPU401_LEGACY
53 	/* EnableHardCodedMPU401Port() */
54 	/* Enable Legacy MIDI Interface port. */
55 	port = (0x03 << 5);	/* FIXME: static address. 0x330 */
56 	temp =
57 	    (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) |
58 	    CTRL_MIDI_EN | port;
59 	hwwrite(vortex->mmio, VORTEX_CTRL, temp);
60 #else
61 	/* Disable Legacy MIDI Interface port. */
62 	temp =
63 	    (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) &
64 	    ~CTRL_MIDI_EN;
65 	hwwrite(vortex->mmio, VORTEX_CTRL, temp);
66 #endif
67 	/* Mpu401UartInit() */
68 	mode = 1;
69 	temp = hwread(vortex->mmio, VORTEX_CTRL2) & 0xffff00cf;
70 	temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4;
71 	hwwrite(vortex->mmio, VORTEX_CTRL2, temp);
72 	hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET);
73 
74 	/* Check if anything is OK. */
75 	temp = hwread(vortex->mmio, VORTEX_MIDI_DATA);
76 	if (temp != MPU401_ACK /*0xfe */ ) {
77 		printk(KERN_ERR "midi port doesn't acknowledge!\n");
78 		return -ENODEV;
79 	}
80 	/* Enable MPU401 interrupts. */
81 	hwwrite(vortex->mmio, VORTEX_IRQ_CTRL,
82 		hwread(vortex->mmio, VORTEX_IRQ_CTRL) | IRQ_MIDI);
83 
84 	/* Create MPU401 instance. */
85 #ifdef VORTEX_MPU401_LEGACY
86 	if ((temp =
87 	     snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330,
88 				 0, 0, 0, &rmidi)) != 0) {
89 		hwwrite(vortex->mmio, VORTEX_CTRL,
90 			(hwread(vortex->mmio, VORTEX_CTRL) &
91 			 ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
92 		return temp;
93 	}
94 #else
95 	port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA);
96 	if ((temp =
97 	     snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
98 				 MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO,
99 				 0, 0, &rmidi)) != 0) {
100 		hwwrite(vortex->mmio, VORTEX_CTRL,
101 			(hwread(vortex->mmio, VORTEX_CTRL) &
102 			 ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
103 		return temp;
104 	}
105 	mpu = rmidi->private_data;
106 	mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD);
107 #endif
108 	/* Overwrite MIDI name */
109 	snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number);
110 
111 	vortex->rmidi = rmidi;
112 	return 0;
113 }
114