1e2786ca6STakashi Sakamoto /*
2e2786ca6STakashi Sakamoto  * oxfw_stream.c - a part of driver for OXFW970/971 based devices
3e2786ca6STakashi Sakamoto  *
4e2786ca6STakashi Sakamoto  * Copyright (c) 2014 Takashi Sakamoto
5e2786ca6STakashi Sakamoto  *
6e2786ca6STakashi Sakamoto  * Licensed under the terms of the GNU General Public License, version 2.
7e2786ca6STakashi Sakamoto  */
8e2786ca6STakashi Sakamoto 
9e2786ca6STakashi Sakamoto #include "oxfw.h"
10f3699e2cSTakashi Sakamoto #include <linux/delay.h>
11e2786ca6STakashi Sakamoto 
125cd1d3f4STakashi Sakamoto #define AVC_GENERIC_FRAME_MAXIMUM_BYTES	512
13f3699e2cSTakashi Sakamoto #define CALLBACK_TIMEOUT	200
145cd1d3f4STakashi Sakamoto 
155cd1d3f4STakashi Sakamoto /*
165cd1d3f4STakashi Sakamoto  * According to datasheet of Oxford Semiconductor:
175cd1d3f4STakashi Sakamoto  *  OXFW970: 32.0/44.1/48.0/96.0 Khz, 8 audio channels I/O
185cd1d3f4STakashi Sakamoto  *  OXFW971: 32.0/44.1/48.0/88.2/96.0/192.0 kHz, 16 audio channels I/O, MIDI I/O
195cd1d3f4STakashi Sakamoto  */
205cd1d3f4STakashi Sakamoto static const unsigned int oxfw_rate_table[] = {
215cd1d3f4STakashi Sakamoto 	[0] = 32000,
225cd1d3f4STakashi Sakamoto 	[1] = 44100,
235cd1d3f4STakashi Sakamoto 	[2] = 48000,
245cd1d3f4STakashi Sakamoto 	[3] = 88200,
255cd1d3f4STakashi Sakamoto 	[4] = 96000,
265cd1d3f4STakashi Sakamoto 	[5] = 192000,
275cd1d3f4STakashi Sakamoto };
285cd1d3f4STakashi Sakamoto 
295cd1d3f4STakashi Sakamoto /*
305cd1d3f4STakashi Sakamoto  * See Table 5.7 – Sampling frequency for Multi-bit Audio
315cd1d3f4STakashi Sakamoto  * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
325cd1d3f4STakashi Sakamoto  */
335cd1d3f4STakashi Sakamoto static const unsigned int avc_stream_rate_table[] = {
345cd1d3f4STakashi Sakamoto 	[0] = 0x02,
355cd1d3f4STakashi Sakamoto 	[1] = 0x03,
365cd1d3f4STakashi Sakamoto 	[2] = 0x04,
375cd1d3f4STakashi Sakamoto 	[3] = 0x0a,
385cd1d3f4STakashi Sakamoto 	[4] = 0x05,
395cd1d3f4STakashi Sakamoto 	[5] = 0x07,
405cd1d3f4STakashi Sakamoto };
415cd1d3f4STakashi Sakamoto 
42f3699e2cSTakashi Sakamoto static int set_stream_format(struct snd_oxfw *oxfw, struct amdtp_stream *s,
43f3699e2cSTakashi Sakamoto 			     unsigned int rate, unsigned int pcm_channels)
44f3699e2cSTakashi Sakamoto {
45f3699e2cSTakashi Sakamoto 	u8 **formats;
46f3699e2cSTakashi Sakamoto 	struct snd_oxfw_stream_formation formation;
47f3699e2cSTakashi Sakamoto 	enum avc_general_plug_dir dir;
48f3699e2cSTakashi Sakamoto 	unsigned int i, err, len;
49f3699e2cSTakashi Sakamoto 
50f3699e2cSTakashi Sakamoto 	formats = oxfw->rx_stream_formats;
51f3699e2cSTakashi Sakamoto 	dir = AVC_GENERAL_PLUG_DIR_IN;
52f3699e2cSTakashi Sakamoto 
53f3699e2cSTakashi Sakamoto 	/* Seek stream format for requirements. */
54f3699e2cSTakashi Sakamoto 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
55f3699e2cSTakashi Sakamoto 		err = snd_oxfw_stream_parse_format(formats[i], &formation);
56f3699e2cSTakashi Sakamoto 		if (err < 0)
57f3699e2cSTakashi Sakamoto 			return err;
58f3699e2cSTakashi Sakamoto 
59f3699e2cSTakashi Sakamoto 		if ((formation.rate == rate) && (formation.pcm == pcm_channels))
60f3699e2cSTakashi Sakamoto 			break;
61f3699e2cSTakashi Sakamoto 	}
62f3699e2cSTakashi Sakamoto 	if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
63f3699e2cSTakashi Sakamoto 		return -EINVAL;
64f3699e2cSTakashi Sakamoto 
65f3699e2cSTakashi Sakamoto 	/* If assumed, just change rate. */
66f3699e2cSTakashi Sakamoto 	if (oxfw->assumed)
67f3699e2cSTakashi Sakamoto 		return avc_general_set_sig_fmt(oxfw->unit, rate,
68f3699e2cSTakashi Sakamoto 					       AVC_GENERAL_PLUG_DIR_IN, 0);
69f3699e2cSTakashi Sakamoto 
70f3699e2cSTakashi Sakamoto 	/* Calculate format length. */
71f3699e2cSTakashi Sakamoto 	len = 5 + formats[i][4] * 2;
72f3699e2cSTakashi Sakamoto 
73f3699e2cSTakashi Sakamoto 	err = avc_stream_set_format(oxfw->unit, dir, 0, formats[i], len);
74f3699e2cSTakashi Sakamoto 	if (err < 0)
75f3699e2cSTakashi Sakamoto 		return err;
76f3699e2cSTakashi Sakamoto 
77f3699e2cSTakashi Sakamoto 	/* Some requests just after changing format causes freezing. */
78f3699e2cSTakashi Sakamoto 	msleep(100);
79f3699e2cSTakashi Sakamoto 
80f3699e2cSTakashi Sakamoto 	return 0;
81f3699e2cSTakashi Sakamoto }
82f3699e2cSTakashi Sakamoto 
83e2786ca6STakashi Sakamoto int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw)
84e2786ca6STakashi Sakamoto {
85e2786ca6STakashi Sakamoto 	int err;
86e2786ca6STakashi Sakamoto 
87e2786ca6STakashi Sakamoto 	err = cmp_connection_init(&oxfw->in_conn, oxfw->unit,
88e2786ca6STakashi Sakamoto 				  CMP_INPUT, 0);
89e2786ca6STakashi Sakamoto 	if (err < 0)
90e2786ca6STakashi Sakamoto 		goto end;
91e2786ca6STakashi Sakamoto 
92e2786ca6STakashi Sakamoto 	err = amdtp_stream_init(&oxfw->rx_stream, oxfw->unit,
93e2786ca6STakashi Sakamoto 				AMDTP_OUT_STREAM, CIP_NONBLOCKING);
94e2786ca6STakashi Sakamoto 	if (err < 0) {
95e2786ca6STakashi Sakamoto 		amdtp_stream_destroy(&oxfw->rx_stream);
96e2786ca6STakashi Sakamoto 		cmp_connection_destroy(&oxfw->in_conn);
97e2786ca6STakashi Sakamoto 	}
98e2786ca6STakashi Sakamoto end:
99e2786ca6STakashi Sakamoto 	return err;
100e2786ca6STakashi Sakamoto }
101e2786ca6STakashi Sakamoto 
102e2786ca6STakashi Sakamoto static void stop_stream(struct snd_oxfw *oxfw)
103e2786ca6STakashi Sakamoto {
104e2786ca6STakashi Sakamoto 	amdtp_stream_pcm_abort(&oxfw->rx_stream);
105e2786ca6STakashi Sakamoto 	amdtp_stream_stop(&oxfw->rx_stream);
106e2786ca6STakashi Sakamoto 	cmp_connection_break(&oxfw->in_conn);
107e2786ca6STakashi Sakamoto }
108e2786ca6STakashi Sakamoto 
109f3699e2cSTakashi Sakamoto static int start_stream(struct snd_oxfw *oxfw, unsigned int rate,
110f3699e2cSTakashi Sakamoto 			unsigned int pcm_channels)
111e2786ca6STakashi Sakamoto {
112f3699e2cSTakashi Sakamoto 	u8 **formats;
113f3699e2cSTakashi Sakamoto 	struct cmp_connection *conn;
114f3699e2cSTakashi Sakamoto 	struct snd_oxfw_stream_formation formation;
115f3699e2cSTakashi Sakamoto 	unsigned int i, midi_ports;
116f3699e2cSTakashi Sakamoto 	struct amdtp_stream *stream;
117f3699e2cSTakashi Sakamoto 	int err;
118f3699e2cSTakashi Sakamoto 
119f3699e2cSTakashi Sakamoto 	stream = &oxfw->rx_stream;
120f3699e2cSTakashi Sakamoto 	formats = oxfw->rx_stream_formats;
121f3699e2cSTakashi Sakamoto 	conn = &oxfw->in_conn;
122f3699e2cSTakashi Sakamoto 
123f3699e2cSTakashi Sakamoto 	/* Get stream formation */
124f3699e2cSTakashi Sakamoto 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
125f3699e2cSTakashi Sakamoto 		if (formats[i] == NULL)
126f3699e2cSTakashi Sakamoto 			break;
127f3699e2cSTakashi Sakamoto 
128f3699e2cSTakashi Sakamoto 		err = snd_oxfw_stream_parse_format(formats[i], &formation);
129f3699e2cSTakashi Sakamoto 		if (err < 0)
130f3699e2cSTakashi Sakamoto 			goto end;
131f3699e2cSTakashi Sakamoto 		if (rate != formation.rate)
132f3699e2cSTakashi Sakamoto 			continue;
133f3699e2cSTakashi Sakamoto 		if (pcm_channels == 0 ||  pcm_channels == formation.pcm)
134f3699e2cSTakashi Sakamoto 			break;
135f3699e2cSTakashi Sakamoto 	}
136f3699e2cSTakashi Sakamoto 	if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) {
137f3699e2cSTakashi Sakamoto 		err = -EINVAL;
138f3699e2cSTakashi Sakamoto 		goto end;
139f3699e2cSTakashi Sakamoto 	}
140f3699e2cSTakashi Sakamoto 
141f3699e2cSTakashi Sakamoto 	pcm_channels = formation.pcm;
142f3699e2cSTakashi Sakamoto 	midi_ports = DIV_ROUND_UP(formation.midi, 8);
143f3699e2cSTakashi Sakamoto 
144f3699e2cSTakashi Sakamoto 	/* The stream should have one pcm channels at least */
145f3699e2cSTakashi Sakamoto 	if (pcm_channels == 0) {
146f3699e2cSTakashi Sakamoto 		err = -EINVAL;
147f3699e2cSTakashi Sakamoto 		goto end;
148f3699e2cSTakashi Sakamoto 	}
149f3699e2cSTakashi Sakamoto 	amdtp_stream_set_parameters(stream, rate, pcm_channels, midi_ports);
150f3699e2cSTakashi Sakamoto 
151f3699e2cSTakashi Sakamoto 	err = cmp_connection_establish(conn,
152f3699e2cSTakashi Sakamoto 				       amdtp_stream_get_max_payload(stream));
153f3699e2cSTakashi Sakamoto 	if (err < 0)
154f3699e2cSTakashi Sakamoto 		goto end;
155f3699e2cSTakashi Sakamoto 
156f3699e2cSTakashi Sakamoto 	err = amdtp_stream_start(stream,
157f3699e2cSTakashi Sakamoto 				 conn->resources.channel,
158f3699e2cSTakashi Sakamoto 				 conn->speed);
159f3699e2cSTakashi Sakamoto 	if (err < 0) {
160f3699e2cSTakashi Sakamoto 		cmp_connection_break(conn);
161f3699e2cSTakashi Sakamoto 		goto end;
162f3699e2cSTakashi Sakamoto 	}
163f3699e2cSTakashi Sakamoto 
164f3699e2cSTakashi Sakamoto 	/* Wait first packet */
165f3699e2cSTakashi Sakamoto 	err = amdtp_stream_wait_callback(stream, CALLBACK_TIMEOUT);
166f3699e2cSTakashi Sakamoto 	if (err < 0)
167f3699e2cSTakashi Sakamoto 		stop_stream(oxfw);
168f3699e2cSTakashi Sakamoto end:
169f3699e2cSTakashi Sakamoto 	return err;
170f3699e2cSTakashi Sakamoto }
171f3699e2cSTakashi Sakamoto 
172f3699e2cSTakashi Sakamoto int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw, unsigned int rate,
173f3699e2cSTakashi Sakamoto 				  unsigned int pcm_channels)
174f3699e2cSTakashi Sakamoto {
175f3699e2cSTakashi Sakamoto 	struct snd_oxfw_stream_formation formation;
176e2786ca6STakashi Sakamoto 	int err = 0;
177e2786ca6STakashi Sakamoto 
178f3699e2cSTakashi Sakamoto 	/* packet queueing error */
179e2786ca6STakashi Sakamoto 	if (amdtp_streaming_error(&oxfw->rx_stream))
180e2786ca6STakashi Sakamoto 		stop_stream(oxfw);
181e2786ca6STakashi Sakamoto 
182f3699e2cSTakashi Sakamoto 	err = snd_oxfw_stream_get_current_formation(oxfw,
183f3699e2cSTakashi Sakamoto 						    AVC_GENERAL_PLUG_DIR_IN,
184f3699e2cSTakashi Sakamoto 						    &formation);
185e2786ca6STakashi Sakamoto 	if (err < 0)
186e2786ca6STakashi Sakamoto 		goto end;
187e2786ca6STakashi Sakamoto 
188f3699e2cSTakashi Sakamoto 	if ((formation.rate != rate) || (formation.pcm != pcm_channels)) {
189e2786ca6STakashi Sakamoto 		stop_stream(oxfw);
190f3699e2cSTakashi Sakamoto 
191f3699e2cSTakashi Sakamoto 		/* arrange sampling rate */
192f3699e2cSTakashi Sakamoto 		err = set_stream_format(oxfw, &oxfw->rx_stream, rate,
193f3699e2cSTakashi Sakamoto 					pcm_channels);
194f3699e2cSTakashi Sakamoto 		if (err < 0) {
195f3699e2cSTakashi Sakamoto 			dev_err(&oxfw->unit->device,
196f3699e2cSTakashi Sakamoto 				"fail to set stream format: %d\n", err);
197f3699e2cSTakashi Sakamoto 			goto end;
198f3699e2cSTakashi Sakamoto 		}
199f3699e2cSTakashi Sakamoto 	}
200f3699e2cSTakashi Sakamoto 
201f3699e2cSTakashi Sakamoto 	err = start_stream(oxfw, rate, pcm_channels);
202f3699e2cSTakashi Sakamoto 	if (err < 0)
203f3699e2cSTakashi Sakamoto 		dev_err(&oxfw->unit->device,
204f3699e2cSTakashi Sakamoto 			"fail to start stream: %d\n", err);
205e2786ca6STakashi Sakamoto end:
206e2786ca6STakashi Sakamoto 	return err;
207e2786ca6STakashi Sakamoto }
208e2786ca6STakashi Sakamoto 
209e2786ca6STakashi Sakamoto void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw)
210e2786ca6STakashi Sakamoto {
211e2786ca6STakashi Sakamoto 	stop_stream(oxfw);
212e2786ca6STakashi Sakamoto }
213e2786ca6STakashi Sakamoto 
214e2786ca6STakashi Sakamoto void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw)
215e2786ca6STakashi Sakamoto {
216e2786ca6STakashi Sakamoto 	stop_stream(oxfw);
217e2786ca6STakashi Sakamoto 
218e2786ca6STakashi Sakamoto 	amdtp_stream_destroy(&oxfw->rx_stream);
219e2786ca6STakashi Sakamoto 	cmp_connection_destroy(&oxfw->in_conn);
220e2786ca6STakashi Sakamoto }
221e2786ca6STakashi Sakamoto 
222e2786ca6STakashi Sakamoto void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw)
223e2786ca6STakashi Sakamoto {
224e2786ca6STakashi Sakamoto 	if (cmp_connection_update(&oxfw->in_conn) < 0)
225e2786ca6STakashi Sakamoto 		stop_stream(oxfw);
226e2786ca6STakashi Sakamoto 	else
227e2786ca6STakashi Sakamoto 		amdtp_stream_update(&oxfw->rx_stream);
228e2786ca6STakashi Sakamoto }
2295cd1d3f4STakashi Sakamoto 
2303c96101fSTakashi Sakamoto int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
2313c96101fSTakashi Sakamoto 				enum avc_general_plug_dir dir,
2323c96101fSTakashi Sakamoto 				struct snd_oxfw_stream_formation *formation)
2333c96101fSTakashi Sakamoto {
2343c96101fSTakashi Sakamoto 	u8 *format;
2353c96101fSTakashi Sakamoto 	unsigned int len;
2363c96101fSTakashi Sakamoto 	int err;
2373c96101fSTakashi Sakamoto 
2383c96101fSTakashi Sakamoto 	len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
2393c96101fSTakashi Sakamoto 	format = kmalloc(len, GFP_KERNEL);
2403c96101fSTakashi Sakamoto 	if (format == NULL)
2413c96101fSTakashi Sakamoto 		return -ENOMEM;
2423c96101fSTakashi Sakamoto 
2433c96101fSTakashi Sakamoto 	err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
2443c96101fSTakashi Sakamoto 	if (err < 0)
2453c96101fSTakashi Sakamoto 		goto end;
2463c96101fSTakashi Sakamoto 	if (len < 3) {
2473c96101fSTakashi Sakamoto 		err = -EIO;
2483c96101fSTakashi Sakamoto 		goto end;
2493c96101fSTakashi Sakamoto 	}
2503c96101fSTakashi Sakamoto 
2513c96101fSTakashi Sakamoto 	err = snd_oxfw_stream_parse_format(format, formation);
2523c96101fSTakashi Sakamoto end:
2533c96101fSTakashi Sakamoto 	kfree(format);
2543c96101fSTakashi Sakamoto 	return err;
2553c96101fSTakashi Sakamoto }
2563c96101fSTakashi Sakamoto 
2575cd1d3f4STakashi Sakamoto /*
2585cd1d3f4STakashi Sakamoto  * See Table 6.16 - AM824 Stream Format
2595cd1d3f4STakashi Sakamoto  *     Figure 6.19 - format_information field for AM824 Compound
2605cd1d3f4STakashi Sakamoto  * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
2615cd1d3f4STakashi Sakamoto  * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005
2625cd1d3f4STakashi Sakamoto  */
2635cd1d3f4STakashi Sakamoto int snd_oxfw_stream_parse_format(u8 *format,
2645cd1d3f4STakashi Sakamoto 				 struct snd_oxfw_stream_formation *formation)
2655cd1d3f4STakashi Sakamoto {
2665cd1d3f4STakashi Sakamoto 	unsigned int i, e, channels, type;
2675cd1d3f4STakashi Sakamoto 
2685cd1d3f4STakashi Sakamoto 	memset(formation, 0, sizeof(struct snd_oxfw_stream_formation));
2695cd1d3f4STakashi Sakamoto 
2705cd1d3f4STakashi Sakamoto 	/*
2715cd1d3f4STakashi Sakamoto 	 * this module can support a hierarchy combination that:
2725cd1d3f4STakashi Sakamoto 	 *  Root:	Audio and Music (0x90)
2735cd1d3f4STakashi Sakamoto 	 *  Level 1:	AM824 Compound  (0x40)
2745cd1d3f4STakashi Sakamoto 	 */
2755cd1d3f4STakashi Sakamoto 	if ((format[0] != 0x90) || (format[1] != 0x40))
2765cd1d3f4STakashi Sakamoto 		return -ENOSYS;
2775cd1d3f4STakashi Sakamoto 
2785cd1d3f4STakashi Sakamoto 	/* check the sampling rate */
2795cd1d3f4STakashi Sakamoto 	for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) {
2805cd1d3f4STakashi Sakamoto 		if (format[2] == avc_stream_rate_table[i])
2815cd1d3f4STakashi Sakamoto 			break;
2825cd1d3f4STakashi Sakamoto 	}
2835cd1d3f4STakashi Sakamoto 	if (i == ARRAY_SIZE(avc_stream_rate_table))
2845cd1d3f4STakashi Sakamoto 		return -ENOSYS;
2855cd1d3f4STakashi Sakamoto 
2865cd1d3f4STakashi Sakamoto 	formation->rate = oxfw_rate_table[i];
2875cd1d3f4STakashi Sakamoto 
2885cd1d3f4STakashi Sakamoto 	for (e = 0; e < format[4]; e++) {
2895cd1d3f4STakashi Sakamoto 		channels = format[5 + e * 2];
2905cd1d3f4STakashi Sakamoto 		type = format[6 + e * 2];
2915cd1d3f4STakashi Sakamoto 
2925cd1d3f4STakashi Sakamoto 		switch (type) {
2935cd1d3f4STakashi Sakamoto 		/* IEC 60958 Conformant, currently handled as MBLA */
2945cd1d3f4STakashi Sakamoto 		case 0x00:
2955cd1d3f4STakashi Sakamoto 		/* Multi Bit Linear Audio (Raw) */
2965cd1d3f4STakashi Sakamoto 		case 0x06:
2975cd1d3f4STakashi Sakamoto 			formation->pcm += channels;
2985cd1d3f4STakashi Sakamoto 			break;
2995cd1d3f4STakashi Sakamoto 		/* MIDI Conformant */
3005cd1d3f4STakashi Sakamoto 		case 0x0d:
3015cd1d3f4STakashi Sakamoto 			formation->midi = channels;
3025cd1d3f4STakashi Sakamoto 			break;
3035cd1d3f4STakashi Sakamoto 		/* IEC 61937-3 to 7 */
3045cd1d3f4STakashi Sakamoto 		case 0x01:
3055cd1d3f4STakashi Sakamoto 		case 0x02:
3065cd1d3f4STakashi Sakamoto 		case 0x03:
3075cd1d3f4STakashi Sakamoto 		case 0x04:
3085cd1d3f4STakashi Sakamoto 		case 0x05:
3095cd1d3f4STakashi Sakamoto 		/* Multi Bit Linear Audio */
3105cd1d3f4STakashi Sakamoto 		case 0x07:	/* DVD-Audio */
3115cd1d3f4STakashi Sakamoto 		case 0x0c:	/* High Precision */
3125cd1d3f4STakashi Sakamoto 		/* One Bit Audio */
3135cd1d3f4STakashi Sakamoto 		case 0x08:	/* (Plain) Raw */
3145cd1d3f4STakashi Sakamoto 		case 0x09:	/* (Plain) SACD */
3155cd1d3f4STakashi Sakamoto 		case 0x0a:	/* (Encoded) Raw */
3165cd1d3f4STakashi Sakamoto 		case 0x0b:	/* (Encoded) SACD */
3175cd1d3f4STakashi Sakamoto 		/* SMPTE Time-Code conformant */
3185cd1d3f4STakashi Sakamoto 		case 0x0e:
3195cd1d3f4STakashi Sakamoto 		/* Sample Count */
3205cd1d3f4STakashi Sakamoto 		case 0x0f:
3215cd1d3f4STakashi Sakamoto 		/* Anciliary Data */
3225cd1d3f4STakashi Sakamoto 		case 0x10:
3235cd1d3f4STakashi Sakamoto 		/* Synchronization Stream (Stereo Raw audio) */
3245cd1d3f4STakashi Sakamoto 		case 0x40:
3255cd1d3f4STakashi Sakamoto 		/* Don't care */
3265cd1d3f4STakashi Sakamoto 		case 0xff:
3275cd1d3f4STakashi Sakamoto 		default:
3285cd1d3f4STakashi Sakamoto 			return -ENOSYS;	/* not supported */
3295cd1d3f4STakashi Sakamoto 		}
3305cd1d3f4STakashi Sakamoto 	}
3315cd1d3f4STakashi Sakamoto 
3325cd1d3f4STakashi Sakamoto 	if (formation->pcm  > AMDTP_MAX_CHANNELS_FOR_PCM ||
3335cd1d3f4STakashi Sakamoto 	    formation->midi > AMDTP_MAX_CHANNELS_FOR_MIDI)
3345cd1d3f4STakashi Sakamoto 		return -ENOSYS;
3355cd1d3f4STakashi Sakamoto 
3365cd1d3f4STakashi Sakamoto 	return 0;
3375cd1d3f4STakashi Sakamoto }
3385cd1d3f4STakashi Sakamoto 
3395cd1d3f4STakashi Sakamoto static int
3405cd1d3f4STakashi Sakamoto assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
3415cd1d3f4STakashi Sakamoto 		      unsigned int pid, u8 *buf, unsigned int *len,
3425cd1d3f4STakashi Sakamoto 		      u8 **formats)
3435cd1d3f4STakashi Sakamoto {
3445cd1d3f4STakashi Sakamoto 	struct snd_oxfw_stream_formation formation;
3455cd1d3f4STakashi Sakamoto 	unsigned int i, eid;
3465cd1d3f4STakashi Sakamoto 	int err;
3475cd1d3f4STakashi Sakamoto 
3485cd1d3f4STakashi Sakamoto 	/* get format at current sampling rate */
3495cd1d3f4STakashi Sakamoto 	err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
3505cd1d3f4STakashi Sakamoto 	if (err < 0) {
3515cd1d3f4STakashi Sakamoto 		dev_err(&oxfw->unit->device,
3525cd1d3f4STakashi Sakamoto 		"fail to get current stream format for isoc %s plug %d:%d\n",
3535cd1d3f4STakashi Sakamoto 			(dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
3545cd1d3f4STakashi Sakamoto 			pid, err);
3555cd1d3f4STakashi Sakamoto 		goto end;
3565cd1d3f4STakashi Sakamoto 	}
3575cd1d3f4STakashi Sakamoto 
3585cd1d3f4STakashi Sakamoto 	/* parse and set stream format */
3595cd1d3f4STakashi Sakamoto 	eid = 0;
3605cd1d3f4STakashi Sakamoto 	err = snd_oxfw_stream_parse_format(buf, &formation);
3615cd1d3f4STakashi Sakamoto 	if (err < 0)
3625cd1d3f4STakashi Sakamoto 		goto end;
3635cd1d3f4STakashi Sakamoto 
3645cd1d3f4STakashi Sakamoto 	formats[eid] = kmalloc(*len, GFP_KERNEL);
3655cd1d3f4STakashi Sakamoto 	if (formats[eid] == NULL) {
3665cd1d3f4STakashi Sakamoto 		err = -ENOMEM;
3675cd1d3f4STakashi Sakamoto 		goto end;
3685cd1d3f4STakashi Sakamoto 	}
3695cd1d3f4STakashi Sakamoto 	memcpy(formats[eid], buf, *len);
3705cd1d3f4STakashi Sakamoto 
3715cd1d3f4STakashi Sakamoto 	/* apply the format for each available sampling rate */
3725cd1d3f4STakashi Sakamoto 	for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) {
3735cd1d3f4STakashi Sakamoto 		if (formation.rate == oxfw_rate_table[i])
3745cd1d3f4STakashi Sakamoto 			continue;
3755cd1d3f4STakashi Sakamoto 
3765cd1d3f4STakashi Sakamoto 		err = avc_general_inquiry_sig_fmt(oxfw->unit,
3775cd1d3f4STakashi Sakamoto 						  oxfw_rate_table[i],
3785cd1d3f4STakashi Sakamoto 						  dir, pid);
3795cd1d3f4STakashi Sakamoto 		if (err < 0)
3805cd1d3f4STakashi Sakamoto 			continue;
3815cd1d3f4STakashi Sakamoto 
3825cd1d3f4STakashi Sakamoto 		eid++;
3835cd1d3f4STakashi Sakamoto 		formats[eid] = kmalloc(*len, GFP_KERNEL);
3845cd1d3f4STakashi Sakamoto 		if (formats[eid] == NULL) {
3855cd1d3f4STakashi Sakamoto 			err = -ENOMEM;
3865cd1d3f4STakashi Sakamoto 			goto end;
3875cd1d3f4STakashi Sakamoto 		}
3885cd1d3f4STakashi Sakamoto 		memcpy(formats[eid], buf, *len);
3895cd1d3f4STakashi Sakamoto 		formats[eid][2] = avc_stream_rate_table[i];
3905cd1d3f4STakashi Sakamoto 	}
3915cd1d3f4STakashi Sakamoto 
3925cd1d3f4STakashi Sakamoto 	err = 0;
3935cd1d3f4STakashi Sakamoto 	oxfw->assumed = true;
3945cd1d3f4STakashi Sakamoto end:
3955cd1d3f4STakashi Sakamoto 	return err;
3965cd1d3f4STakashi Sakamoto }
3975cd1d3f4STakashi Sakamoto 
3985cd1d3f4STakashi Sakamoto static int fill_stream_formats(struct snd_oxfw *oxfw,
3995cd1d3f4STakashi Sakamoto 			       enum avc_general_plug_dir dir,
4005cd1d3f4STakashi Sakamoto 			       unsigned short pid)
4015cd1d3f4STakashi Sakamoto {
4025cd1d3f4STakashi Sakamoto 	u8 *buf, **formats;
4035cd1d3f4STakashi Sakamoto 	unsigned int len, eid = 0;
4045cd1d3f4STakashi Sakamoto 	struct snd_oxfw_stream_formation dummy;
4055cd1d3f4STakashi Sakamoto 	int err;
4065cd1d3f4STakashi Sakamoto 
4075cd1d3f4STakashi Sakamoto 	buf = kmalloc(AVC_GENERIC_FRAME_MAXIMUM_BYTES, GFP_KERNEL);
4085cd1d3f4STakashi Sakamoto 	if (buf == NULL)
4095cd1d3f4STakashi Sakamoto 		return -ENOMEM;
4105cd1d3f4STakashi Sakamoto 
4115cd1d3f4STakashi Sakamoto 	formats = oxfw->rx_stream_formats;
4125cd1d3f4STakashi Sakamoto 
4135cd1d3f4STakashi Sakamoto 	/* get first entry */
4145cd1d3f4STakashi Sakamoto 	len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
4155cd1d3f4STakashi Sakamoto 	err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0);
4165cd1d3f4STakashi Sakamoto 	if (err == -ENOSYS) {
4175cd1d3f4STakashi Sakamoto 		/* LIST subfunction is not implemented */
4185cd1d3f4STakashi Sakamoto 		len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
4195cd1d3f4STakashi Sakamoto 		err = assume_stream_formats(oxfw, dir, pid, buf, &len,
4205cd1d3f4STakashi Sakamoto 					    formats);
4215cd1d3f4STakashi Sakamoto 		goto end;
4225cd1d3f4STakashi Sakamoto 	} else if (err < 0) {
4235cd1d3f4STakashi Sakamoto 		dev_err(&oxfw->unit->device,
4245cd1d3f4STakashi Sakamoto 			"fail to get stream format %d for isoc %s plug %d:%d\n",
4255cd1d3f4STakashi Sakamoto 			eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
4265cd1d3f4STakashi Sakamoto 			pid, err);
4275cd1d3f4STakashi Sakamoto 		goto end;
4285cd1d3f4STakashi Sakamoto 	}
4295cd1d3f4STakashi Sakamoto 
4305cd1d3f4STakashi Sakamoto 	/* LIST subfunction is implemented */
4315cd1d3f4STakashi Sakamoto 	while (eid < SND_OXFW_STREAM_FORMAT_ENTRIES) {
4325cd1d3f4STakashi Sakamoto 		/* The format is too short. */
4335cd1d3f4STakashi Sakamoto 		if (len < 3) {
4345cd1d3f4STakashi Sakamoto 			err = -EIO;
4355cd1d3f4STakashi Sakamoto 			break;
4365cd1d3f4STakashi Sakamoto 		}
4375cd1d3f4STakashi Sakamoto 
4385cd1d3f4STakashi Sakamoto 		/* parse and set stream format */
4395cd1d3f4STakashi Sakamoto 		err = snd_oxfw_stream_parse_format(buf, &dummy);
4405cd1d3f4STakashi Sakamoto 		if (err < 0)
4415cd1d3f4STakashi Sakamoto 			break;
4425cd1d3f4STakashi Sakamoto 
4435cd1d3f4STakashi Sakamoto 		formats[eid] = kmalloc(len, GFP_KERNEL);
4445cd1d3f4STakashi Sakamoto 		if (formats[eid] == NULL) {
4455cd1d3f4STakashi Sakamoto 			err = -ENOMEM;
4465cd1d3f4STakashi Sakamoto 			break;
4475cd1d3f4STakashi Sakamoto 		}
4485cd1d3f4STakashi Sakamoto 		memcpy(formats[eid], buf, len);
4495cd1d3f4STakashi Sakamoto 
4505cd1d3f4STakashi Sakamoto 		/* get next entry */
4515cd1d3f4STakashi Sakamoto 		len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
4525cd1d3f4STakashi Sakamoto 		err = avc_stream_get_format_list(oxfw->unit, dir, 0,
4535cd1d3f4STakashi Sakamoto 						 buf, &len, ++eid);
4545cd1d3f4STakashi Sakamoto 		/* No entries remained. */
4555cd1d3f4STakashi Sakamoto 		if (err == -EINVAL) {
4565cd1d3f4STakashi Sakamoto 			err = 0;
4575cd1d3f4STakashi Sakamoto 			break;
4585cd1d3f4STakashi Sakamoto 		} else if (err < 0) {
4595cd1d3f4STakashi Sakamoto 			dev_err(&oxfw->unit->device,
4605cd1d3f4STakashi Sakamoto 			"fail to get stream format %d for isoc %s plug %d:%d\n",
4615cd1d3f4STakashi Sakamoto 				eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" :
4625cd1d3f4STakashi Sakamoto 									"out",
4635cd1d3f4STakashi Sakamoto 				pid, err);
4645cd1d3f4STakashi Sakamoto 			break;
4655cd1d3f4STakashi Sakamoto 		}
4665cd1d3f4STakashi Sakamoto 	}
4675cd1d3f4STakashi Sakamoto end:
4685cd1d3f4STakashi Sakamoto 	kfree(buf);
4695cd1d3f4STakashi Sakamoto 	return err;
4705cd1d3f4STakashi Sakamoto }
4715cd1d3f4STakashi Sakamoto 
4725cd1d3f4STakashi Sakamoto int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
4735cd1d3f4STakashi Sakamoto {
4745cd1d3f4STakashi Sakamoto 	u8 plugs[AVC_PLUG_INFO_BUF_BYTES];
4755cd1d3f4STakashi Sakamoto 	int err;
4765cd1d3f4STakashi Sakamoto 
4775cd1d3f4STakashi Sakamoto 	/* the number of plugs for isoc in/out, ext in/out  */
4785cd1d3f4STakashi Sakamoto 	err = avc_general_get_plug_info(oxfw->unit, 0x1f, 0x07, 0x00, plugs);
4795cd1d3f4STakashi Sakamoto 	if (err < 0) {
4805cd1d3f4STakashi Sakamoto 		dev_err(&oxfw->unit->device,
4815cd1d3f4STakashi Sakamoto 		"fail to get info for isoc/external in/out plugs: %d\n",
4825cd1d3f4STakashi Sakamoto 			err);
4835cd1d3f4STakashi Sakamoto 		goto end;
4845cd1d3f4STakashi Sakamoto 	} else if (plugs[0] == 0) {
4855cd1d3f4STakashi Sakamoto 		err = -ENOSYS;
4865cd1d3f4STakashi Sakamoto 		goto end;
4875cd1d3f4STakashi Sakamoto 	}
4885cd1d3f4STakashi Sakamoto 
4895cd1d3f4STakashi Sakamoto 	/* use iPCR[0] if exists */
4905cd1d3f4STakashi Sakamoto 	if (plugs[0] > 0)
4915cd1d3f4STakashi Sakamoto 		err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
4925cd1d3f4STakashi Sakamoto end:
4935cd1d3f4STakashi Sakamoto 	return err;
4945cd1d3f4STakashi Sakamoto }
495