linux/sound/pci/au88x0/au88x0_mpu401.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   4 *  Routines for control of MPU-401 in UART mode
   5 *
   6 *   Modified for the Aureal Vortex based Soundcards
   7 *   by Manuel Jander (mjande@embedded.cl).
   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
  30static 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        if ((temp =
  72             snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330,
  73                                 MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) {
  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        if ((temp =
  82             snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
  83                                 MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO |
  84                                 MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) {
  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