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-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * motu-stream.c - a part of driver for MOTU FireWire series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "motu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #define	CALLBACK_TIMEOUT	200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #define ISOC_COMM_CONTROL_OFFSET		0x0b00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #define  ISOC_COMM_CONTROL_MASK			0xffff0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #define  CHANGE_RX_ISOC_COMM_STATE		0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define  RX_ISOC_COMM_IS_ACTIVATED		0x40000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define  RX_ISOC_COMM_CHANNEL_MASK		0x3f000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define  RX_ISOC_COMM_CHANNEL_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define  CHANGE_TX_ISOC_COMM_STATE		0x00800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define  TX_ISOC_COMM_IS_ACTIVATED		0x00400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define  TX_ISOC_COMM_CHANNEL_MASK		0x003f0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define  TX_ISOC_COMM_CHANNEL_SHIFT		16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define PACKET_FORMAT_OFFSET			0x0b10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define  TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS	0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define  RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS	0x00000040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define  TX_PACKET_TRANSMISSION_SPEED_MASK	0x0000000f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static int keep_resources(struct snd_motu *motu, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 			  struct amdtp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	struct snd_motu_packet_format *packet_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	unsigned int midi_ports = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	if (stream == &motu->rx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		resources = &motu->rx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		packet_format = &motu->rx_packet_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		    (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 			midi_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		resources = &motu->tx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		packet_format = &motu->tx_packet_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		if ((motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		    (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			midi_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	err = amdtp_motu_set_parameters(stream, rate, midi_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 					packet_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	return fw_iso_resources_allocate(resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 				amdtp_stream_get_max_payload(stream),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 				fw_parent_device(motu->unit)->max_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static int begin_session(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	__be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	// Configure the unit to start isochronous communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 					sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	data = be32_to_cpu(reg) & ~ISOC_COMM_CONTROL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	data |= CHANGE_RX_ISOC_COMM_STATE | RX_ISOC_COMM_IS_ACTIVATED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		(motu->rx_resources.channel << RX_ISOC_COMM_CHANNEL_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		CHANGE_TX_ISOC_COMM_STATE | TX_ISOC_COMM_IS_ACTIVATED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		(motu->tx_resources.channel << TX_ISOC_COMM_CHANNEL_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	return snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 					  sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) static void finish_session(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	__be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	err = snd_motu_protocol_switch_fetching_mode(motu, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	err = snd_motu_transaction_read(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 					sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	data &= ~(RX_ISOC_COMM_IS_ACTIVATED | TX_ISOC_COMM_IS_ACTIVATED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	data |= CHANGE_RX_ISOC_COMM_STATE | CHANGE_TX_ISOC_COMM_STATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	snd_motu_transaction_write(motu, ISOC_COMM_CONTROL_OFFSET, &reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 				   sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int snd_motu_stream_cache_packet_formats(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	err = snd_motu_protocol_cache_packet_formats(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		motu->tx_packet_formats.midi_flag_offset = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		motu->tx_packet_formats.midi_byte_offset = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	} else if (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		motu->tx_packet_formats.midi_flag_offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		motu->tx_packet_formats.midi_byte_offset = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		motu->rx_packet_formats.midi_flag_offset = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		motu->rx_packet_formats.midi_byte_offset = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	} else if (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		motu->rx_packet_formats.midi_flag_offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		motu->rx_packet_formats.midi_byte_offset = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 				   unsigned int frames_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 				   unsigned int frames_per_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	unsigned int curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	err = snd_motu_protocol_get_clock_rate(motu, &curr_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		rate = curr_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (motu->substreams_counter == 0 || curr_rate != rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		fw_iso_resources_free(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		fw_iso_resources_free(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		err = snd_motu_protocol_set_clock_rate(motu, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			dev_err(&motu->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 				"fail to set sampling rate: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		err = snd_motu_stream_cache_packet_formats(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		err = keep_resources(motu, rate, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		err = keep_resources(motu, rate, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			fw_iso_resources_free(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		err = amdtp_domain_set_events_per_period(&motu->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 					frames_per_period, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			fw_iso_resources_free(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			fw_iso_resources_free(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int ensure_packet_formats(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	__be32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, &reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 					sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	data = be32_to_cpu(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		  RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		  TX_PACKET_TRANSMISSION_SPEED_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (motu->spec->tx_fixed_pcm_chunks[0] == motu->tx_packet_formats.pcm_chunks[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	if (motu->spec->rx_fixed_pcm_chunks[0] == motu->rx_packet_formats.pcm_chunks[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	data |= fw_parent_device(motu->unit)->max_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	reg = cpu_to_be32(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 					  sizeof(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int snd_motu_stream_start_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	unsigned int generation = motu->rx_resources.generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	if (motu->substreams_counter == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	if (amdtp_streaming_error(&motu->rx_stream) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	    amdtp_streaming_error(&motu->tx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	if (generation != fw_parent_device(motu->unit)->card->generation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		err = fw_iso_resources_update(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		err = fw_iso_resources_update(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	if (!amdtp_stream_running(&motu->rx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		int spd = fw_parent_device(motu->unit)->max_speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		err = ensure_packet_formats(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		err = begin_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			dev_err(&motu->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 				"fail to start isochronous comm: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		err = amdtp_domain_add_stream(&motu->domain, &motu->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 					      motu->tx_resources.channel, spd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 			goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		err = amdtp_domain_add_stream(&motu->domain, &motu->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 					      motu->rx_resources.channel, spd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		err = amdtp_domain_start(&motu->domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		if (!amdtp_stream_wait_callback(&motu->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 						CALLBACK_TIMEOUT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		    !amdtp_stream_wait_callback(&motu->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 						CALLBACK_TIMEOUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			err = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		err = snd_motu_protocol_switch_fetching_mode(motu, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 			dev_err(&motu->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 				"fail to enable frame fetching: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			goto stop_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) stop_streams:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) void snd_motu_stream_stop_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (motu->substreams_counter == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		amdtp_domain_stop(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		finish_session(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		fw_iso_resources_free(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		fw_iso_resources_free(&motu->rx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int init_stream(struct snd_motu *motu, struct amdtp_stream *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	struct fw_iso_resources *resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	enum amdtp_stream_direction dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	if (s == &motu->tx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		resources = &motu->tx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		dir = AMDTP_IN_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		resources = &motu->rx_resources;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		dir = AMDTP_OUT_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	err = fw_iso_resources_init(resources, motu->unit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	err = amdtp_motu_init(s, motu->unit, dir, motu->spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		fw_iso_resources_destroy(resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static void destroy_stream(struct snd_motu *motu, struct amdtp_stream *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	amdtp_stream_destroy(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (s == &motu->tx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		fw_iso_resources_destroy(&motu->tx_resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		fw_iso_resources_destroy(&motu->rx_resources);
^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) int snd_motu_stream_init_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	err = init_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	err = init_stream(motu, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		destroy_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	err = amdtp_domain_init(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		destroy_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		destroy_stream(motu, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) // This function should be called before starting streams or after stopping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) // streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) void snd_motu_stream_destroy_duplex(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	amdtp_domain_destroy(&motu->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	destroy_stream(motu, &motu->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	destroy_stream(motu, &motu->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	motu->substreams_counter = 0;
^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) static void motu_lock_changed(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	motu->dev_lock_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	wake_up(&motu->hwdep_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int snd_motu_stream_lock_try(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	spin_lock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	if (motu->dev_lock_count < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		goto out;
^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) 	if (motu->dev_lock_count++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		motu_lock_changed(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	spin_unlock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) void snd_motu_stream_lock_release(struct snd_motu *motu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	spin_lock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	if (WARN_ON(motu->dev_lock_count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	if (--motu->dev_lock_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		motu_lock_changed(motu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	spin_unlock_irq(&motu->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }