^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * MOTU Midi Timepiece ALSA Main routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright by Michael T. Mayers (c) Jan 09, 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * mail: michael@tweakoz.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Thanks to John Galbraith
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This driver is for the 'Mark Of The Unicorn' (MOTU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * MidiTimePiece AV multiport MIDI interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * IOPORTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * -------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 8 MIDI Ins and 8 MIDI outs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Video Sync In (BNC), Word Sync Out (BNC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * ADAT Sync Out (DB9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * SMPTE in/out (1/4")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * 2 programmable pedal/footswitch inputs and 4 programmable MIDI controller knobs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Macintosh RS422 serial port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * RS422 "network" port for ganging multiple MTP's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * PC Parallel Port ( which this driver currently uses )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * MISC FEATURES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * -------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Hardware MIDI routing, merging, and filtering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * MIDI Synchronization to Video, ADAT, SMPTE and other Clock sources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * 128 'scene' memories, recallable from MIDI program change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * ChangeLog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Jun 11 2001 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - Recoded & debugged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * - Added timer interrupt for midi outputs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * - hwports is between 1 and 8, which specifies the number of hardware ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * The three global ports, computer, adat and broadcast ports, are created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * always after h/w and remote ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <sound/rawmidi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * globals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MODULE_AUTHOR("Michael T. Mayers");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) MODULE_SUPPORTED_DEVICE("{{MOTU,MidiTimePiece AV multiport MIDI}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) // io resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define MTPAV_IOBASE 0x378
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define MTPAV_IRQ 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define MTPAV_MAX_PORTS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int index = SNDRV_DEFAULT_IDX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static char *id = SNDRV_DEFAULT_STR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static long port = MTPAV_IOBASE; /* 0x378, 0x278 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static int irq = MTPAV_IRQ; /* 7, 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int hwports = MTPAV_MAX_PORTS; /* use hardware ports 1-8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) module_param(index, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) module_param(id, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) module_param_hw(port, long, ioport, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) module_param_hw(irq, int, irq, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) module_param(hwports, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static struct platform_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * defines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) //#define USE_FAKE_MTP // don't actually read/write to MTP device (for debugging without an actual unit) (does not work yet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) // parallel port usage masks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define SIGS_BYTE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SIGS_RFD 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define SIGS_IRQ 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define SIGS_IN0 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define SIGS_IN1 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define SIGC_WRITE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define SIGC_READ 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define SIGC_INTEN 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define DREG 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SREG 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CREG 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define MTPAV_MODE_INPUT_OPENED 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define MTPAV_MODE_OUTPUT_OPENED 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define MTPAV_MODE_INPUT_TRIGGERED 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define MTPAV_MODE_OUTPUT_TRIGGERED 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define NUMPORTS (0x12+1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct mtpav_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u8 number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u8 hwport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u8 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u8 running_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct snd_rawmidi_substream *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct snd_rawmidi_substream *output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct mtpav {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct resource *res_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int irq; /* interrupt (for inputs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) spinlock_t spinlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int share_irq; /* number of accesses to input interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int istimer; /* number of accesses to timer interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct timer_list timer; /* timer interrupts for outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct snd_rawmidi *rmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int num_ports; /* number of hw ports (1-8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct mtpav_port ports[NUMPORTS]; /* all ports including computer, adat and bc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u32 inmidiport; /* selected input midi port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u32 inmidistate; /* during midi command 0xf5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) u32 outmidihwport; /* selected output midi hw port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * possible hardware ports (selected by 0xf5 port message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * 0x00 all ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * 0x01 .. 0x08 this MTP's ports 1..8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * 0x09 .. 0x10 networked MTP's ports (9..16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * 0x11 networked MTP's computer port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * 0x63 to ADAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * mappig:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * subdevice 0 - (X-1) ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * X - (2*X-1) networked ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * X computer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * X+1 ADAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * X+2 all ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * where X = chip->num_ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define MTPAV_PIDX_COMPUTER 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define MTPAV_PIDX_ADAT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #define MTPAV_PIDX_BROADCAST 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int translate_subdevice_to_hwport(struct mtpav *chip, int subdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (subdev < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0x01; /* invalid - use port 0 as default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) else if (subdev < chip->num_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return subdev + 1; /* single mtp port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) else if (subdev < chip->num_ports * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return subdev - chip->num_ports + 0x09; /* remote port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) else if (subdev == chip->num_ports * 2 + MTPAV_PIDX_COMPUTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0x11; /* computer port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) else if (subdev == chip->num_ports + MTPAV_PIDX_ADAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 0x63; /* ADAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0; /* all ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int translate_hwport_to_subdevice(struct mtpav *chip, int hwport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (hwport <= 0x00) /* all ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return chip->num_ports + MTPAV_PIDX_BROADCAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) else if (hwport <= 0x08) { /* single port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) p = hwport - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (p >= chip->num_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) } else if (hwport <= 0x10) { /* remote port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) p = hwport - 0x09 + chip->num_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (p >= chip->num_ports * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) p = chip->num_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) } else if (hwport == 0x11) /* computer port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return chip->num_ports + MTPAV_PIDX_COMPUTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) else /* ADAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return chip->num_ports + MTPAV_PIDX_ADAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static u8 snd_mtpav_getreg(struct mtpav *chip, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) u8 rval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (reg == SREG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) rval = inb(chip->port + SREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) rval = (rval & 0xf8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) } else if (reg == CREG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) rval = inb(chip->port + CREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) rval = (rval & 0x1c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static inline void snd_mtpav_mputreg(struct mtpav *chip, u16 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (reg == DREG || reg == CREG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) outb(val, chip->port + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static void snd_mtpav_wait_rfdhi(struct mtpav *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int counts = 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u8 sbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) sbyte = snd_mtpav_getreg(chip, SREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) while (!(sbyte & SIGS_RFD) && counts--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) sbyte = snd_mtpav_getreg(chip, SREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void snd_mtpav_send_byte(struct mtpav *chip, u8 byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) u8 tcbyt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) u8 clrwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) u8 setwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) snd_mtpav_wait_rfdhi(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /////////////////
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) tcbyt = snd_mtpav_getreg(chip, CREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) clrwrite = tcbyt & (SIGC_WRITE ^ 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) setwrite = tcbyt | SIGC_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) snd_mtpav_mputreg(chip, DREG, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) snd_mtpav_mputreg(chip, CREG, clrwrite); // clear write bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) snd_mtpav_mputreg(chip, CREG, setwrite); // set write bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* call this with spin lock held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static void snd_mtpav_output_port_write(struct mtpav *mtp_card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct mtpav_port *portp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u8 outbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) // Get the outbyte first, so we can emulate running status if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) // necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) // send port change command if necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (portp->hwport != mtp_card->outmidihwport) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) mtp_card->outmidihwport = portp->hwport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) snd_mtpav_send_byte(mtp_card, 0xf5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) snd_mtpav_send_byte(mtp_card, portp->hwport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) snd_printk(KERN_DEBUG "new outport: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) (unsigned int) portp->hwport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!(outbyte & 0x80) && portp->running_status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) snd_mtpav_send_byte(mtp_card, portp->running_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) // send data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (outbyte & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) portp->running_status = outbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) snd_mtpav_send_byte(mtp_card, outbyte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct mtpav *mtp_card = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct mtpav_port *portp = &mtp_card->ports[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) spin_lock_irqsave(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) snd_mtpav_output_port_write(mtp_card, portp, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) spin_unlock_irqrestore(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * mtpav control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void snd_mtpav_portscan(struct mtpav *chip) // put mtp into smart routing mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u8 p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) for (p = 0; p < 8; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) snd_mtpav_send_byte(chip, 0xf5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) snd_mtpav_send_byte(chip, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) snd_mtpav_send_byte(chip, 0xfe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct mtpav *mtp_card = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct mtpav_port *portp = &mtp_card->ports[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) spin_lock_irqsave(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) portp->mode |= MTPAV_MODE_INPUT_OPENED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) portp->input = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (mtp_card->share_irq++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE)); // enable pport interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) spin_unlock_irqrestore(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct mtpav *mtp_card = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct mtpav_port *portp = &mtp_card->ports[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) spin_lock_irqsave(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) portp->mode &= ~MTPAV_MODE_INPUT_OPENED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) portp->input = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (--mtp_card->share_irq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) spin_unlock_irqrestore(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct mtpav *mtp_card = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct mtpav_port *portp = &mtp_card->ports[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) spin_lock_irqsave(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) portp->mode |= MTPAV_MODE_INPUT_TRIGGERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) spin_unlock_irqrestore(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * timer interrupt for outputs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static void snd_mtpav_output_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct mtpav *chip = from_timer(chip, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) spin_lock_irqsave(&chip->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* reprogram timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) mod_timer(&chip->timer, 1 + jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* process each port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct mtpav_port *portp = &chip->ports[p];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) snd_mtpav_output_port_write(chip, portp, portp->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) spin_unlock_irqrestore(&chip->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* spinlock held! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static void snd_mtpav_add_output_timer(struct mtpav *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) mod_timer(&chip->timer, 1 + jiffies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* spinlock held! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static void snd_mtpav_remove_output_timer(struct mtpav *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) del_timer(&chip->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct mtpav *mtp_card = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct mtpav_port *portp = &mtp_card->ports[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) spin_lock_irqsave(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) portp->mode |= MTPAV_MODE_OUTPUT_OPENED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) portp->output = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) spin_unlock_irqrestore(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct mtpav *mtp_card = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct mtpav_port *portp = &mtp_card->ports[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) spin_lock_irqsave(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) portp->output = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) spin_unlock_irqrestore(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct mtpav *mtp_card = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) struct mtpav_port *portp = &mtp_card->ports[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) spin_lock_irqsave(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (mtp_card->istimer++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) snd_mtpav_add_output_timer(mtp_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (--mtp_card->istimer == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) snd_mtpav_remove_output_timer(mtp_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) spin_unlock_irqrestore(&mtp_card->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) snd_mtpav_output_write(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * midi interrupt for inputs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct mtpav_port *portp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) portp = &mcrd->ports[mcrd->inmidiport];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) snd_rawmidi_receive(portp->input, &inbyte, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (inbyte >= 0xf8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* real-time midi code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) snd_mtpav_inmidi_process(mcrd, inbyte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (mcrd->inmidistate == 0) { // awaiting command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (inbyte == 0xf5) // MTP port #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) mcrd->inmidistate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) snd_mtpav_inmidi_process(mcrd, inbyte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) } else if (mcrd->inmidistate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) mcrd->inmidistate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static void snd_mtpav_read_bytes(struct mtpav *mcrd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u8 clrread, setread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) u8 mtp_read_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) u8 sr, cbyt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (!(sbyt & SIGS_BYTE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) cbyt = snd_mtpav_getreg(mcrd, CREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) clrread = cbyt & (SIGC_READ ^ 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) setread = cbyt | SIGC_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) mtp_read_byte = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) snd_mtpav_mputreg(mcrd, CREG, setread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) sr = snd_mtpav_getreg(mcrd, SREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) snd_mtpav_mputreg(mcrd, CREG, clrread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) sr &= SIGS_IN0 | SIGS_IN1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) sr >>= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) mtp_read_byte |= sr << (i * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) snd_mtpav_inmidi_h(mcrd, mtp_read_byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) sbyt = snd_mtpav_getreg(mcrd, SREG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) } while (sbyt & SIGS_BYTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct mtpav *mcard = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) spin_lock(&mcard->spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) snd_mtpav_read_bytes(mcard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) spin_unlock(&mcard->spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * get ISA resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) static int snd_mtpav_get_ISA(struct mtpav *mcard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mcard->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) mcard->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static const struct snd_rawmidi_ops snd_mtpav_output = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .open = snd_mtpav_output_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .close = snd_mtpav_output_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .trigger = snd_mtpav_output_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static const struct snd_rawmidi_ops snd_mtpav_input = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .open = snd_mtpav_input_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) .close = snd_mtpav_input_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .trigger = snd_mtpav_input_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * get RAWMIDI resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) static void snd_mtpav_set_name(struct mtpav *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (substream->number >= 0 && substream->number < chip->num_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) else if (substream->number >= 8 && substream->number < chip->num_ports * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) else if (substream->number == chip->num_ports * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) strcpy(substream->name, "MTP computer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) else if (substream->number == chip->num_ports * 2 + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) strcpy(substream->name, "MTP ADAT");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) strcpy(substream->name, "MTP broadcast");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct snd_rawmidi *rawmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct snd_rawmidi_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct list_head *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (hwports < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) hwports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) else if (hwports > 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) hwports = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) mcard->num_ports = hwports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) &mcard->rmidi)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) rawmidi = mcard->rmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) rawmidi->private_data = mcard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) substream = list_entry(list, struct snd_rawmidi_substream, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) snd_mtpav_set_name(mcard, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) substream->ops = &snd_mtpav_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) substream = list_entry(list, struct snd_rawmidi_substream, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) snd_mtpav_set_name(mcard, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) substream->ops = &snd_mtpav_output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) SNDRV_RAWMIDI_INFO_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) sprintf(rawmidi->name, "MTP AV MIDI");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static void snd_mtpav_free(struct snd_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct mtpav *crd = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) spin_lock_irqsave(&crd->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (crd->istimer > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) snd_mtpav_remove_output_timer(crd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) spin_unlock_irqrestore(&crd->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (crd->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) free_irq(crd->irq, (void *)crd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) release_and_free_resource(crd->res_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static int snd_mtpav_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) struct mtpav *mtp_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) err = snd_card_new(&dev->dev, index, id, THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) sizeof(*mtp_card), &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) mtp_card = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) spin_lock_init(&mtp_card->spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) mtp_card->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) mtp_card->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) mtp_card->share_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) mtp_card->inmidistate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) mtp_card->outmidihwport = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) timer_setup(&mtp_card->timer, snd_mtpav_output_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) card->private_free = snd_mtpav_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) err = snd_mtpav_get_RAWMIDI(mtp_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) mtp_card->inmidiport = mtp_card->num_ports + MTPAV_PIDX_BROADCAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) err = snd_mtpav_get_ISA(mtp_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) strcpy(card->driver, "MTPAV");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) strcpy(card->shortname, "MTPAV on parallel port");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) snprintf(card->longname, sizeof(card->longname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) "MTPAV on parallel port at 0x%lx", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) snd_mtpav_portscan(mtp_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) err = snd_card_register(mtp_card->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) goto __error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) platform_set_drvdata(dev, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) __error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static int snd_mtpav_remove(struct platform_device *devptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) snd_card_free(platform_get_drvdata(devptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) #define SND_MTPAV_DRIVER "snd_mtpav"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static struct platform_driver snd_mtpav_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) .probe = snd_mtpav_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) .remove = snd_mtpav_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .name = SND_MTPAV_DRIVER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static int __init alsa_card_mtpav_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if ((err = platform_driver_register(&snd_mtpav_driver)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (!IS_ERR(device)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (platform_get_drvdata(device))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) platform_device_unregister(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) err = PTR_ERR(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) platform_driver_unregister(&snd_mtpav_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static void __exit alsa_card_mtpav_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) platform_device_unregister(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) platform_driver_unregister(&snd_mtpav_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) module_init(alsa_card_mtpav_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) module_exit(alsa_card_mtpav_exit)