Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/au88x0/au88x0_mpu401.c
26451 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) by Jaroslav Kysela <[email protected]>
4
* Routines for control of MPU-401 in UART mode
5
*
6
* Modified for the Aureal Vortex based Soundcards
7
* by Manuel Jander ([email protected]).
8
*/
9
10
#include <linux/time.h>
11
#include <linux/init.h>
12
#include <sound/core.h>
13
#include <sound/mpu401.h>
14
#include "au88x0.h"
15
16
/* Check for mpu401 mmio support. */
17
/* MPU401 legacy support is only provided as a emergency fallback *
18
* for older versions of ALSA. Its usage is strongly discouraged. */
19
#ifndef MPU401_HW_AUREAL
20
#define VORTEX_MPU401_LEGACY
21
#endif
22
23
/* Vortex MPU401 defines. */
24
#define MIDI_CLOCK_DIV 0x61
25
/* Standart MPU401 defines. */
26
#define MPU401_RESET 0xff
27
#define MPU401_ENTER_UART 0x3f
28
#define MPU401_ACK 0xfe
29
30
static int snd_vortex_midi(vortex_t *vortex)
31
{
32
struct snd_rawmidi *rmidi;
33
int temp, mode;
34
struct snd_mpu401 *mpu;
35
unsigned long port;
36
37
#ifdef VORTEX_MPU401_LEGACY
38
/* EnableHardCodedMPU401Port() */
39
/* Enable Legacy MIDI Interface port. */
40
port = (0x03 << 5); /* FIXME: static address. 0x330 */
41
temp =
42
(hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) |
43
CTRL_MIDI_EN | port;
44
hwwrite(vortex->mmio, VORTEX_CTRL, temp);
45
#else
46
/* Disable Legacy MIDI Interface port. */
47
temp =
48
(hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) &
49
~CTRL_MIDI_EN;
50
hwwrite(vortex->mmio, VORTEX_CTRL, temp);
51
#endif
52
/* Mpu401UartInit() */
53
mode = 1;
54
temp = hwread(vortex->mmio, VORTEX_CTRL2) & 0xffff00cf;
55
temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4;
56
hwwrite(vortex->mmio, VORTEX_CTRL2, temp);
57
hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET);
58
59
/* Check if anything is OK. */
60
temp = hwread(vortex->mmio, VORTEX_MIDI_DATA);
61
if (temp != MPU401_ACK /*0xfe */ ) {
62
dev_err(vortex->card->dev, "midi port doesn't acknowledge!\n");
63
return -ENODEV;
64
}
65
/* Enable MPU401 interrupts. */
66
hwwrite(vortex->mmio, VORTEX_IRQ_CTRL,
67
hwread(vortex->mmio, VORTEX_IRQ_CTRL) | IRQ_MIDI);
68
69
/* Create MPU401 instance. */
70
#ifdef VORTEX_MPU401_LEGACY
71
temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330,
72
MPU401_INFO_IRQ_HOOK, -1, &rmidi);
73
if (temp) {
74
hwwrite(vortex->mmio, VORTEX_CTRL,
75
(hwread(vortex->mmio, VORTEX_CTRL) &
76
~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
77
return temp;
78
}
79
#else
80
port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA);
81
temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
82
MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO |
83
MPU401_INFO_IRQ_HOOK, -1, &rmidi);
84
if (temp) {
85
hwwrite(vortex->mmio, VORTEX_CTRL,
86
(hwread(vortex->mmio, VORTEX_CTRL) &
87
~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
88
return temp;
89
}
90
mpu = rmidi->private_data;
91
mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD);
92
#endif
93
/* Overwrite MIDI name */
94
snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number);
95
96
vortex->rmidi = rmidi;
97
return 0;
98
}
99
100