Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | { |
Takashi Iwai | 2fd1687 | 2005-11-17 14:55:19 +0100 | [diff] [blame] | 47 | struct snd_rawmidi *rmidi; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 48 | int temp, mode; |
Takashi Iwai | 2fd1687 | 2005-11-17 14:55:19 +0100 | [diff] [blame] | 49 | struct snd_mpu401 *mpu; |
Takashi Iwai | d5a31b8 | 2006-05-23 13:30:59 +0200 | [diff] [blame] | 50 | unsigned long port; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |
Takashi Iwai | 97c67b6 | 2006-01-13 17:16:29 +0100 | [diff] [blame] | 95 | port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 | if ((temp = |
| 97 | snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, |
Takashi Iwai | 302e4c2 | 2006-05-23 13:24:30 +0200 | [diff] [blame] | 98 | MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO, |
| 99 | 0, 0, &rmidi)) != 0) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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; |
Takashi Iwai | 97c67b6 | 2006-01-13 17:16:29 +0100 | [diff] [blame] | 106 | mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 107 | #endif |
Alan Horstmann | 520290e | 2006-05-03 17:07:29 +0200 | [diff] [blame] | 108 | /* Overwrite MIDI name */ |
| 109 | snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number); |
| 110 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | vortex->rmidi = rmidi; |
| 112 | return 0; |
| 113 | } |