Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)