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)  * oxfw_stream.c - a part of driver for OXFW970/971 based devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (c) 2014 Takashi Sakamoto
^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 "oxfw.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #define AVC_GENERIC_FRAME_MAXIMUM_BYTES	512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #define CALLBACK_TIMEOUT	200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * According to datasheet of Oxford Semiconductor:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *  OXFW970: 32.0/44.1/48.0/96.0 Khz, 8 audio channels I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *  OXFW971: 32.0/44.1/48.0/88.2/96.0/192.0 kHz, 16 audio channels I/O, MIDI I/O
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) static const unsigned int oxfw_rate_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	[0] = 32000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	[1] = 44100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	[2] = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	[3] = 88200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	[4] = 96000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	[5] = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * See Table 5.7 – Sampling frequency for Multi-bit Audio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static const unsigned int avc_stream_rate_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	[0] = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	[1] = 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	[2] = 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	[3] = 0x0a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	[4] = 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	[5] = 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static int set_rate(struct snd_oxfw *oxfw, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	err = avc_general_set_sig_fmt(oxfw->unit, rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 				      AVC_GENERAL_PLUG_DIR_IN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	if (oxfw->has_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		err = avc_general_set_sig_fmt(oxfw->unit, rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 					      AVC_GENERAL_PLUG_DIR_OUT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) static int set_stream_format(struct snd_oxfw *oxfw, struct amdtp_stream *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			     unsigned int rate, unsigned int pcm_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	u8 **formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	enum avc_general_plug_dir dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	if (s == &oxfw->tx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		formats = oxfw->tx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		dir = AVC_GENERAL_PLUG_DIR_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		formats = oxfw->rx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		dir = AVC_GENERAL_PLUG_DIR_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	/* Seek stream format for requirements. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		err = snd_oxfw_stream_parse_format(formats[i], &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		if ((formation.rate == rate) && (formation.pcm == pcm_channels))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	/* If assumed, just change rate. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	if (oxfw->assumed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		return set_rate(oxfw, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	/* Calculate format length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	len = 5 + formats[i][4] * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	err = avc_stream_set_format(oxfw->unit, dir, 0, formats[i], len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	/* Some requests just after changing format causes freezing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return 0;
^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) static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct cmp_connection *conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (stream == &oxfw->rx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		conn = &oxfw->in_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		conn = &oxfw->out_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	err = cmp_connection_establish(conn);
^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) 	err = amdtp_domain_add_stream(&oxfw->domain, stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 				      conn->resources.channel, conn->speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		cmp_connection_break(conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static int check_connection_used_by_others(struct snd_oxfw *oxfw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 					   struct amdtp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	struct cmp_connection *conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	bool used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	if (stream == &oxfw->tx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		conn = &oxfw->out_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		conn = &oxfw->in_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	err = cmp_connection_check_used(conn, &used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if ((err >= 0) && used && !amdtp_stream_running(stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			"Connection established by others: %cPCR[%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			(conn->direction == CMP_OUTPUT) ? 'o' : 'i',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			conn->pcr_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	struct cmp_connection *conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	enum cmp_direction c_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	enum amdtp_stream_direction s_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	if (stream == &oxfw->tx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		conn = &oxfw->out_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		c_dir = CMP_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		s_dir = AMDTP_IN_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		conn = &oxfw->in_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		c_dir = CMP_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		s_dir = AMDTP_OUT_STREAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	err = cmp_connection_init(conn, oxfw->unit, c_dir, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	err = amdtp_am824_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		cmp_connection_destroy(conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	 * OXFW starts to transmit packets with non-zero dbc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	 * OXFW postpone transferring packets till handling any asynchronous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	 * packets. As a result, next isochronous packet includes more data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	 * blocks than IEC 61883-6 defines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	if (stream == &oxfw->tx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		oxfw->tx_stream.flags |= CIP_JUMBO_PAYLOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		if (oxfw->wrong_dbs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			oxfw->tx_stream.flags |= CIP_WRONG_DBS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	enum avc_general_plug_dir dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	u8 **formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	struct cmp_connection *conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	if (stream == &oxfw->rx_stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		dir = AVC_GENERAL_PLUG_DIR_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		formats = oxfw->rx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		conn = &oxfw->in_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		dir = AVC_GENERAL_PLUG_DIR_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		formats = oxfw->tx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		conn = &oxfw->out_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		struct snd_oxfw_stream_formation fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		if (formats[i] == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		err = snd_oxfw_stream_parse_format(formats[i], &fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		if (fmt.rate == formation.rate && fmt.pcm == formation.pcm &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		    fmt.midi == formation.midi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	// The stream should have one pcm channels at least.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	if (formation.pcm == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 					 formation.midi * 8, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream));
^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) int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 				   struct amdtp_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 				   unsigned int rate, unsigned int pcm_channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 				   unsigned int frames_per_period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 				   unsigned int frames_per_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	enum avc_general_plug_dir dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	// Considering JACK/FFADO streaming:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	// TODO: This can be removed hwdep functionality becomes popular.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	err = check_connection_used_by_others(oxfw, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	if (oxfw->has_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		err = check_connection_used_by_others(oxfw, &oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			return err;
^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) 	if (stream == &oxfw->tx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		dir = AVC_GENERAL_PLUG_DIR_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		dir = AVC_GENERAL_PLUG_DIR_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	if (rate == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		rate = formation.rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		pcm_channels = formation.pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	if (formation.rate != rate || formation.pcm != pcm_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		amdtp_domain_stop(&oxfw->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		cmp_connection_break(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		cmp_connection_release(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		if (oxfw->has_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 			cmp_connection_break(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			cmp_connection_release(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	if (oxfw->substreams_count == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	    formation.rate != rate || formation.pcm != pcm_channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		err = set_stream_format(oxfw, stream, rate, pcm_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 			dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 				"fail to set stream format: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		err = keep_resources(oxfw, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		if (oxfw->has_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			err = keep_resources(oxfw, &oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 				cmp_connection_release(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 				return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		err = amdtp_domain_set_events_per_period(&oxfw->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 					frames_per_period, frames_per_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			cmp_connection_release(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 			if (oxfw->has_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 				cmp_connection_release(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			return err;
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	if (oxfw->substreams_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (amdtp_streaming_error(&oxfw->rx_stream) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	    amdtp_streaming_error(&oxfw->tx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		amdtp_domain_stop(&oxfw->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		cmp_connection_break(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		if (oxfw->has_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 			cmp_connection_break(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	if (!amdtp_stream_running(&oxfw->rx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		err = start_stream(oxfw, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 				"fail to prepare rx stream: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		if (oxfw->has_output &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		    !amdtp_stream_running(&oxfw->tx_stream)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			err = start_stream(oxfw, &oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 				dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 					"fail to prepare tx stream: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 				goto error;
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		err = amdtp_domain_start(&oxfw->domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		// Wait first packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		if (!amdtp_stream_wait_callback(&oxfw->rx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 						CALLBACK_TIMEOUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			err = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		if (oxfw->has_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			if (!amdtp_stream_wait_callback(&oxfw->tx_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 							CALLBACK_TIMEOUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 				err = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 				goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		}
^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) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	amdtp_domain_stop(&oxfw->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	cmp_connection_break(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	if (oxfw->has_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		cmp_connection_break(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	return err;
^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) void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	if (oxfw->substreams_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		amdtp_domain_stop(&oxfw->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		cmp_connection_break(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		cmp_connection_release(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		if (oxfw->has_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			cmp_connection_break(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 			cmp_connection_release(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static void destroy_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	struct cmp_connection *conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	if (stream == &oxfw->tx_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		conn = &oxfw->out_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		conn = &oxfw->in_conn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	amdtp_stream_destroy(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	cmp_connection_destroy(conn);
^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) int snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	err = init_stream(oxfw, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	if (oxfw->has_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		err = init_stream(oxfw, &oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 			destroy_stream(oxfw, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	err = amdtp_domain_init(&oxfw->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		destroy_stream(oxfw, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		if (oxfw->has_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 			destroy_stream(oxfw, &oxfw->tx_stream);
^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) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) // This function should be called before starting the stream or after stopping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) // the streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) void snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	amdtp_domain_destroy(&oxfw->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	destroy_stream(oxfw, &oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	if (oxfw->has_output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		destroy_stream(oxfw, &oxfw->tx_stream);
^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) void snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	amdtp_domain_stop(&oxfw->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	cmp_connection_break(&oxfw->in_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	amdtp_stream_pcm_abort(&oxfw->rx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	if (oxfw->has_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		cmp_connection_break(&oxfw->out_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		amdtp_stream_pcm_abort(&oxfw->tx_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 				enum avc_general_plug_dir dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 				struct snd_oxfw_stream_formation *formation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	u8 *format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	format = kmalloc(len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	if (format == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	if (len < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	err = snd_oxfw_stream_parse_format(format, formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	kfree(format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^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)  * See Table 6.16 - AM824 Stream Format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)  *     Figure 6.19 - format_information field for AM824 Compound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)  * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)  * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int snd_oxfw_stream_parse_format(u8 *format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 				 struct snd_oxfw_stream_formation *formation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	unsigned int i, e, channels, type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	memset(formation, 0, sizeof(struct snd_oxfw_stream_formation));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	 * this module can support a hierarchy combination that:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	 *  Root:	Audio and Music (0x90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	 *  Level 1:	AM824 Compound  (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	if ((format[0] != 0x90) || (format[1] != 0x40))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	/* check the sampling rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		if (format[2] == avc_stream_rate_table[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	if (i == ARRAY_SIZE(avc_stream_rate_table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	formation->rate = oxfw_rate_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	for (e = 0; e < format[4]; e++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		channels = format[5 + e * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		type = format[6 + e * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		/* IEC 60958 Conformant, currently handled as MBLA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		/* Multi Bit Linear Audio (Raw) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		case 0x06:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			formation->pcm += channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		/* MIDI Conformant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		case 0x0d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 			formation->midi = channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		/* IEC 61937-3 to 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		case 0x01:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		case 0x02:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		case 0x03:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		case 0x04:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		case 0x05:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		/* Multi Bit Linear Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		case 0x07:	/* DVD-Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		case 0x0c:	/* High Precision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		/* One Bit Audio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		case 0x08:	/* (Plain) Raw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		case 0x09:	/* (Plain) SACD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		case 0x0a:	/* (Encoded) Raw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		case 0x0b:	/* (Encoded) SACD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		/* SMPTE Time-Code conformant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		case 0x0e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		/* Sample Count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		case 0x0f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		/* Anciliary Data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		/* Synchronization Stream (Stereo Raw audio) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		case 0x40:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		/* Don't care */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		case 0xff:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 			return -ENXIO;	/* not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	if (formation->pcm  > AM824_MAX_CHANNELS_FOR_PCM ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	    formation->midi > AM824_MAX_CHANNELS_FOR_MIDI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		      unsigned int pid, u8 *buf, unsigned int *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		      u8 **formats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	unsigned int i, eid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	/* get format at current sampling rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		"fail to get current stream format for isoc %s plug %d:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 			(dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 			pid, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	/* parse and set stream format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	eid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	err = snd_oxfw_stream_parse_format(buf, &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 				    GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	if (!formats[eid]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	/* apply the format for each available sampling rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		if (formation.rate == oxfw_rate_table[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		err = avc_general_inquiry_sig_fmt(oxfw->unit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 						  oxfw_rate_table[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 						  dir, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		eid++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 		formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, *len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 					    GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		if (formats[eid] == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 			err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 			goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		formats[eid][2] = avc_stream_rate_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	oxfw->assumed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static int fill_stream_formats(struct snd_oxfw *oxfw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 			       enum avc_general_plug_dir dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 			       unsigned short pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	u8 *buf, **formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	unsigned int len, eid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	struct snd_oxfw_stream_formation dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	buf = kmalloc(AVC_GENERIC_FRAME_MAXIMUM_BYTES, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	if (buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	if (dir == AVC_GENERAL_PLUG_DIR_OUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		formats = oxfw->tx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 		formats = oxfw->rx_stream_formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	/* get first entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	if (err == -ENXIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 		/* LIST subfunction is not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 		err = assume_stream_formats(oxfw, dir, pid, buf, &len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 					    formats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 	} else if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 			"fail to get stream format %d for isoc %s plug %d:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 			eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 			pid, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	/* LIST subfunction is implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	while (eid < SND_OXFW_STREAM_FORMAT_ENTRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 		/* The format is too short. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 		if (len < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 			err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		/* parse and set stream format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 		err = snd_oxfw_stream_parse_format(buf, &dummy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 		formats[eid] = devm_kmemdup(&oxfw->card->card_dev, buf, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 					    GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 		if (!formats[eid]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 			err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 		/* get next entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 		len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		err = avc_stream_get_format_list(oxfw->unit, dir, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 						 buf, &len, ++eid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		/* No entries remained. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		if (err == -EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 			err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		} else if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 			dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 			"fail to get stream format %d for isoc %s plug %d:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 				eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 									"out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 				pid, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	u8 plugs[AVC_PLUG_INFO_BUF_BYTES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	struct snd_oxfw_stream_formation formation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	u8 *format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	/* the number of plugs for isoc in/out, ext in/out  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	err = avc_general_get_plug_info(oxfw->unit, 0x1f, 0x07, 0x00, plugs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 		dev_err(&oxfw->unit->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 		"fail to get info for isoc/external in/out plugs: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 			err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	} else if ((plugs[0] == 0) && (plugs[1] == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 		err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	/* use oPCR[0] if exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	if (plugs[1] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_OUT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 			if (err != -ENXIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 				return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 			// The oPCR is not available for isoc communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 			err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 			for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 				format = oxfw->tx_stream_formats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 				if (format == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 				err = snd_oxfw_stream_parse_format(format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 								   &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 				if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 				/* Add one MIDI port. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 				if (formation.midi > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 					oxfw->midi_input_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 			oxfw->has_output = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 		}
^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) 	/* use iPCR[0] if exists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	if (plugs[0] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 		err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 			if (err != -ENXIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 				return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 			// The iPCR is not available for isoc communication.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 			err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 			for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 				format = oxfw->rx_stream_formats[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 				if (format == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 				err = snd_oxfw_stream_parse_format(format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 								   &formation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 				if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 				/* Add one MIDI port. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 				if (formation.midi > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 					oxfw->midi_output_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 			oxfw->has_input = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) void snd_oxfw_stream_lock_changed(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	oxfw->dev_lock_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	wake_up(&oxfw->hwdep_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) int snd_oxfw_stream_lock_try(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 	spin_lock_irq(&oxfw->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	/* user land lock this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	if (oxfw->dev_lock_count < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 		err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 	/* this is the first time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 	if (oxfw->dev_lock_count++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 		snd_oxfw_stream_lock_changed(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	spin_unlock_irq(&oxfw->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) void snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	spin_lock_irq(&oxfw->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	if (WARN_ON(oxfw->dev_lock_count <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 	if (--oxfw->dev_lock_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 		snd_oxfw_stream_lock_changed(oxfw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	spin_unlock_irq(&oxfw->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }