au88x0_mpu401.c 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. #include <linux/time.h>
  10. #include <linux/init.h>
  11. #include <sound/core.h>
  12. #include <sound/mpu401.h>
  13. #include "au88x0.h"
  14. /* Check for mpu401 mmio support. */
  15. /* MPU401 legacy support is only provided as a emergency fallback *
  16. * for older versions of ALSA. Its usage is strongly discouraged. */
  17. #ifndef MPU401_HW_AUREAL
  18. #define VORTEX_MPU401_LEGACY
  19. #endif
  20. /* Vortex MPU401 defines. */
  21. #define MIDI_CLOCK_DIV 0x61
  22. /* Standart MPU401 defines. */
  23. #define MPU401_RESET 0xff
  24. #define MPU401_ENTER_UART 0x3f
  25. #define MPU401_ACK 0xfe
  26. static int snd_vortex_midi(vortex_t *vortex)
  27. {
  28. struct snd_rawmidi *rmidi;
  29. int temp, mode;
  30. struct snd_mpu401 *mpu;
  31. unsigned long port;
  32. #ifdef VORTEX_MPU401_LEGACY
  33. /* EnableHardCodedMPU401Port() */
  34. /* Enable Legacy MIDI Interface port. */
  35. port = (0x03 << 5); /* FIXME: static address. 0x330 */
  36. temp =
  37. (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) |
  38. CTRL_MIDI_EN | port;
  39. hwwrite(vortex->mmio, VORTEX_CTRL, temp);
  40. #else
  41. /* Disable Legacy MIDI Interface port. */
  42. temp =
  43. (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) &
  44. ~CTRL_MIDI_EN;
  45. hwwrite(vortex->mmio, VORTEX_CTRL, temp);
  46. #endif
  47. /* Mpu401UartInit() */
  48. mode = 1;
  49. temp = hwread(vortex->mmio, VORTEX_CTRL2) & 0xffff00cf;
  50. temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4;
  51. hwwrite(vortex->mmio, VORTEX_CTRL2, temp);
  52. hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET);
  53. /* Check if anything is OK. */
  54. temp = hwread(vortex->mmio, VORTEX_MIDI_DATA);
  55. if (temp != MPU401_ACK /*0xfe */ ) {
  56. dev_err(vortex->card->dev, "midi port doesn't acknowledge!\n");
  57. return -ENODEV;
  58. }
  59. /* Enable MPU401 interrupts. */
  60. hwwrite(vortex->mmio, VORTEX_IRQ_CTRL,
  61. hwread(vortex->mmio, VORTEX_IRQ_CTRL) | IRQ_MIDI);
  62. /* Create MPU401 instance. */
  63. #ifdef VORTEX_MPU401_LEGACY
  64. temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330,
  65. MPU401_INFO_IRQ_HOOK, -1, &rmidi);
  66. if (temp) {
  67. hwwrite(vortex->mmio, VORTEX_CTRL,
  68. (hwread(vortex->mmio, VORTEX_CTRL) &
  69. ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
  70. return temp;
  71. }
  72. #else
  73. port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA);
  74. temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
  75. MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO |
  76. MPU401_INFO_IRQ_HOOK, -1, &rmidi);
  77. if (temp) {
  78. hwwrite(vortex->mmio, VORTEX_CTRL,
  79. (hwread(vortex->mmio, VORTEX_CTRL) &
  80. ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
  81. return temp;
  82. }
  83. mpu = rmidi->private_data;
  84. mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD);
  85. #endif
  86. /* Overwrite MIDI name */
  87. snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number);
  88. vortex->rmidi = rmidi;
  89. return 0;
  90. }