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"
10e2786ca6STakashi Sakamoto 
115cd1d3f4STakashi Sakamoto #define AVC_GENERIC_FRAME_MAXIMUM_BYTES	512
125cd1d3f4STakashi Sakamoto 
135cd1d3f4STakashi Sakamoto /*
145cd1d3f4STakashi Sakamoto  * According to datasheet of Oxford Semiconductor:
155cd1d3f4STakashi Sakamoto  *  OXFW970: 32.0/44.1/48.0/96.0 Khz, 8 audio channels I/O
165cd1d3f4STakashi Sakamoto  *  OXFW971: 32.0/44.1/48.0/88.2/96.0/192.0 kHz, 16 audio channels I/O, MIDI I/O
175cd1d3f4STakashi Sakamoto  */
185cd1d3f4STakashi Sakamoto static const unsigned int oxfw_rate_table[] = {
195cd1d3f4STakashi Sakamoto 	[0] = 32000,
205cd1d3f4STakashi Sakamoto 	[1] = 44100,
215cd1d3f4STakashi Sakamoto 	[2] = 48000,
225cd1d3f4STakashi Sakamoto 	[3] = 88200,
235cd1d3f4STakashi Sakamoto 	[4] = 96000,
245cd1d3f4STakashi Sakamoto 	[5] = 192000,
255cd1d3f4STakashi Sakamoto };
265cd1d3f4STakashi Sakamoto 
275cd1d3f4STakashi Sakamoto /*
285cd1d3f4STakashi Sakamoto  * See Table 5.7 – Sampling frequency for Multi-bit Audio
295cd1d3f4STakashi Sakamoto  * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
305cd1d3f4STakashi Sakamoto  */
315cd1d3f4STakashi Sakamoto static const unsigned int avc_stream_rate_table[] = {
325cd1d3f4STakashi Sakamoto 	[0] = 0x02,
335cd1d3f4STakashi Sakamoto 	[1] = 0x03,
345cd1d3f4STakashi Sakamoto 	[2] = 0x04,
355cd1d3f4STakashi Sakamoto 	[3] = 0x0a,
365cd1d3f4STakashi Sakamoto 	[4] = 0x05,
375cd1d3f4STakashi Sakamoto 	[5] = 0x07,
385cd1d3f4STakashi Sakamoto };
395cd1d3f4STakashi Sakamoto 
40e2786ca6STakashi Sakamoto int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw)
41e2786ca6STakashi Sakamoto {
42e2786ca6STakashi Sakamoto 	int err;
43e2786ca6STakashi Sakamoto 
44e2786ca6STakashi Sakamoto 	err = cmp_connection_init(&oxfw->in_conn, oxfw->unit,
45e2786ca6STakashi Sakamoto 				  CMP_INPUT, 0);
46e2786ca6STakashi Sakamoto 	if (err < 0)
47e2786ca6STakashi Sakamoto 		goto end;
48e2786ca6STakashi Sakamoto 
49e2786ca6STakashi Sakamoto 	err = amdtp_stream_init(&oxfw->rx_stream, oxfw->unit,
50e2786ca6STakashi Sakamoto 				AMDTP_OUT_STREAM, CIP_NONBLOCKING);
51e2786ca6STakashi Sakamoto 	if (err < 0) {
52e2786ca6STakashi Sakamoto 		amdtp_stream_destroy(&oxfw->rx_stream);
53e2786ca6STakashi Sakamoto 		cmp_connection_destroy(&oxfw->in_conn);
54e2786ca6STakashi Sakamoto 	}
55e2786ca6STakashi Sakamoto end:
56e2786ca6STakashi Sakamoto 	return err;
57e2786ca6STakashi Sakamoto }
58e2786ca6STakashi Sakamoto 
59e2786ca6STakashi Sakamoto static void stop_stream(struct snd_oxfw *oxfw)
60e2786ca6STakashi Sakamoto {
61e2786ca6STakashi Sakamoto 	amdtp_stream_pcm_abort(&oxfw->rx_stream);
62e2786ca6STakashi Sakamoto 	amdtp_stream_stop(&oxfw->rx_stream);
63e2786ca6STakashi Sakamoto 	cmp_connection_break(&oxfw->in_conn);
64e2786ca6STakashi Sakamoto }
65e2786ca6STakashi Sakamoto 
66e2786ca6STakashi Sakamoto int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw)
67e2786ca6STakashi Sakamoto {
68e2786ca6STakashi Sakamoto 	int err = 0;
69e2786ca6STakashi Sakamoto 
70e2786ca6STakashi Sakamoto 	if (amdtp_streaming_error(&oxfw->rx_stream))
71e2786ca6STakashi Sakamoto 		stop_stream(oxfw);
72e2786ca6STakashi Sakamoto 
73e2786ca6STakashi Sakamoto 	if (amdtp_stream_running(&oxfw->rx_stream))
74e2786ca6STakashi Sakamoto 		goto end;
75e2786ca6STakashi Sakamoto 
76e2786ca6STakashi Sakamoto 	err = cmp_connection_establish(&oxfw->in_conn,
77e2786ca6STakashi Sakamoto 			amdtp_stream_get_max_payload(&oxfw->rx_stream));
78e2786ca6STakashi Sakamoto 	if (err < 0)
79e2786ca6STakashi Sakamoto 		goto end;
80e2786ca6STakashi Sakamoto 
81e2786ca6STakashi Sakamoto 	err = amdtp_stream_start(&oxfw->rx_stream,
82e2786ca6STakashi Sakamoto 				 oxfw->in_conn.resources.channel,
83e2786ca6STakashi Sakamoto 				 oxfw->in_conn.speed);
84e2786ca6STakashi Sakamoto 	if (err < 0)
85e2786ca6STakashi Sakamoto 		stop_stream(oxfw);
86e2786ca6STakashi Sakamoto end:
87e2786ca6STakashi Sakamoto 	return err;
88e2786ca6STakashi Sakamoto }
89e2786ca6STakashi Sakamoto 
90e2786ca6STakashi Sakamoto void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw)
91e2786ca6STakashi Sakamoto {
92e2786ca6STakashi Sakamoto 	stop_stream(oxfw);
93e2786ca6STakashi Sakamoto }
94e2786ca6STakashi Sakamoto 
95e2786ca6STakashi Sakamoto void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw)
96e2786ca6STakashi Sakamoto {
97e2786ca6STakashi Sakamoto 	stop_stream(oxfw);
98e2786ca6STakashi Sakamoto 
99e2786ca6STakashi Sakamoto 	amdtp_stream_destroy(&oxfw->rx_stream);
100e2786ca6STakashi Sakamoto 	cmp_connection_destroy(&oxfw->in_conn);
101e2786ca6STakashi Sakamoto }
102e2786ca6STakashi Sakamoto 
103e2786ca6STakashi Sakamoto void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw)
104e2786ca6STakashi Sakamoto {
105e2786ca6STakashi Sakamoto 	if (cmp_connection_update(&oxfw->in_conn) < 0)
106e2786ca6STakashi Sakamoto 		stop_stream(oxfw);
107e2786ca6STakashi Sakamoto 	else
108e2786ca6STakashi Sakamoto 		amdtp_stream_update(&oxfw->rx_stream);
109e2786ca6STakashi Sakamoto }
1105cd1d3f4STakashi Sakamoto 
1113c96101fSTakashi Sakamoto int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
1123c96101fSTakashi Sakamoto 				enum avc_general_plug_dir dir,
1133c96101fSTakashi Sakamoto 				struct snd_oxfw_stream_formation *formation)
1143c96101fSTakashi Sakamoto {
1153c96101fSTakashi Sakamoto 	u8 *format;
1163c96101fSTakashi Sakamoto 	unsigned int len;
1173c96101fSTakashi Sakamoto 	int err;
1183c96101fSTakashi Sakamoto 
1193c96101fSTakashi Sakamoto 	len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
1203c96101fSTakashi Sakamoto 	format = kmalloc(len, GFP_KERNEL);
1213c96101fSTakashi Sakamoto 	if (format == NULL)
1223c96101fSTakashi Sakamoto 		return -ENOMEM;
1233c96101fSTakashi Sakamoto 
1243c96101fSTakashi Sakamoto 	err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
1253c96101fSTakashi Sakamoto 	if (err < 0)
1263c96101fSTakashi Sakamoto 		goto end;
1273c96101fSTakashi Sakamoto 	if (len < 3) {
1283c96101fSTakashi Sakamoto 		err = -EIO;
1293c96101fSTakashi Sakamoto 		goto end;
1303c96101fSTakashi Sakamoto 	}
1313c96101fSTakashi Sakamoto 
1323c96101fSTakashi Sakamoto 	err = snd_oxfw_stream_parse_format(format, formation);
1333c96101fSTakashi Sakamoto end:
1343c96101fSTakashi Sakamoto 	kfree(format);
1353c96101fSTakashi Sakamoto 	return err;
1363c96101fSTakashi Sakamoto }
1373c96101fSTakashi Sakamoto 
1385cd1d3f4STakashi Sakamoto /*
1395cd1d3f4STakashi Sakamoto  * See Table 6.16 - AM824 Stream Format
1405cd1d3f4STakashi Sakamoto  *     Figure 6.19 - format_information field for AM824 Compound
1415cd1d3f4STakashi Sakamoto  * in AV/C Stream Format Information Specification 1.1 (Apr 2005, 1394TA)
1425cd1d3f4STakashi Sakamoto  * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005
1435cd1d3f4STakashi Sakamoto  */
1445cd1d3f4STakashi Sakamoto int snd_oxfw_stream_parse_format(u8 *format,
1455cd1d3f4STakashi Sakamoto 				 struct snd_oxfw_stream_formation *formation)
1465cd1d3f4STakashi Sakamoto {
1475cd1d3f4STakashi Sakamoto 	unsigned int i, e, channels, type;
1485cd1d3f4STakashi Sakamoto 
1495cd1d3f4STakashi Sakamoto 	memset(formation, 0, sizeof(struct snd_oxfw_stream_formation));
1505cd1d3f4STakashi Sakamoto 
1515cd1d3f4STakashi Sakamoto 	/*
1525cd1d3f4STakashi Sakamoto 	 * this module can support a hierarchy combination that:
1535cd1d3f4STakashi Sakamoto 	 *  Root:	Audio and Music (0x90)
1545cd1d3f4STakashi Sakamoto 	 *  Level 1:	AM824 Compound  (0x40)
1555cd1d3f4STakashi Sakamoto 	 */
1565cd1d3f4STakashi Sakamoto 	if ((format[0] != 0x90) || (format[1] != 0x40))
1575cd1d3f4STakashi Sakamoto 		return -ENOSYS;
1585cd1d3f4STakashi Sakamoto 
1595cd1d3f4STakashi Sakamoto 	/* check the sampling rate */
1605cd1d3f4STakashi Sakamoto 	for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) {
1615cd1d3f4STakashi Sakamoto 		if (format[2] == avc_stream_rate_table[i])
1625cd1d3f4STakashi Sakamoto 			break;
1635cd1d3f4STakashi Sakamoto 	}
1645cd1d3f4STakashi Sakamoto 	if (i == ARRAY_SIZE(avc_stream_rate_table))
1655cd1d3f4STakashi Sakamoto 		return -ENOSYS;
1665cd1d3f4STakashi Sakamoto 
1675cd1d3f4STakashi Sakamoto 	formation->rate = oxfw_rate_table[i];
1685cd1d3f4STakashi Sakamoto 
1695cd1d3f4STakashi Sakamoto 	for (e = 0; e < format[4]; e++) {
1705cd1d3f4STakashi Sakamoto 		channels = format[5 + e * 2];
1715cd1d3f4STakashi Sakamoto 		type = format[6 + e * 2];
1725cd1d3f4STakashi Sakamoto 
1735cd1d3f4STakashi Sakamoto 		switch (type) {
1745cd1d3f4STakashi Sakamoto 		/* IEC 60958 Conformant, currently handled as MBLA */
1755cd1d3f4STakashi Sakamoto 		case 0x00:
1765cd1d3f4STakashi Sakamoto 		/* Multi Bit Linear Audio (Raw) */
1775cd1d3f4STakashi Sakamoto 		case 0x06:
1785cd1d3f4STakashi Sakamoto 			formation->pcm += channels;
1795cd1d3f4STakashi Sakamoto 			break;
1805cd1d3f4STakashi Sakamoto 		/* MIDI Conformant */
1815cd1d3f4STakashi Sakamoto 		case 0x0d:
1825cd1d3f4STakashi Sakamoto 			formation->midi = channels;
1835cd1d3f4STakashi Sakamoto 			break;
1845cd1d3f4STakashi Sakamoto 		/* IEC 61937-3 to 7 */
1855cd1d3f4STakashi Sakamoto 		case 0x01:
1865cd1d3f4STakashi Sakamoto 		case 0x02:
1875cd1d3f4STakashi Sakamoto 		case 0x03:
1885cd1d3f4STakashi Sakamoto 		case 0x04:
1895cd1d3f4STakashi Sakamoto 		case 0x05:
1905cd1d3f4STakashi Sakamoto 		/* Multi Bit Linear Audio */
1915cd1d3f4STakashi Sakamoto 		case 0x07:	/* DVD-Audio */
1925cd1d3f4STakashi Sakamoto 		case 0x0c:	/* High Precision */
1935cd1d3f4STakashi Sakamoto 		/* One Bit Audio */
1945cd1d3f4STakashi Sakamoto 		case 0x08:	/* (Plain) Raw */
1955cd1d3f4STakashi Sakamoto 		case 0x09:	/* (Plain) SACD */
1965cd1d3f4STakashi Sakamoto 		case 0x0a:	/* (Encoded) Raw */
1975cd1d3f4STakashi Sakamoto 		case 0x0b:	/* (Encoded) SACD */
1985cd1d3f4STakashi Sakamoto 		/* SMPTE Time-Code conformant */
1995cd1d3f4STakashi Sakamoto 		case 0x0e:
2005cd1d3f4STakashi Sakamoto 		/* Sample Count */
2015cd1d3f4STakashi Sakamoto 		case 0x0f:
2025cd1d3f4STakashi Sakamoto 		/* Anciliary Data */
2035cd1d3f4STakashi Sakamoto 		case 0x10:
2045cd1d3f4STakashi Sakamoto 		/* Synchronization Stream (Stereo Raw audio) */
2055cd1d3f4STakashi Sakamoto 		case 0x40:
2065cd1d3f4STakashi Sakamoto 		/* Don't care */
2075cd1d3f4STakashi Sakamoto 		case 0xff:
2085cd1d3f4STakashi Sakamoto 		default:
2095cd1d3f4STakashi Sakamoto 			return -ENOSYS;	/* not supported */
2105cd1d3f4STakashi Sakamoto 		}
2115cd1d3f4STakashi Sakamoto 	}
2125cd1d3f4STakashi Sakamoto 
2135cd1d3f4STakashi Sakamoto 	if (formation->pcm  > AMDTP_MAX_CHANNELS_FOR_PCM ||
2145cd1d3f4STakashi Sakamoto 	    formation->midi > AMDTP_MAX_CHANNELS_FOR_MIDI)
2155cd1d3f4STakashi Sakamoto 		return -ENOSYS;
2165cd1d3f4STakashi Sakamoto 
2175cd1d3f4STakashi Sakamoto 	return 0;
2185cd1d3f4STakashi Sakamoto }
2195cd1d3f4STakashi Sakamoto 
2205cd1d3f4STakashi Sakamoto static int
2215cd1d3f4STakashi Sakamoto assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
2225cd1d3f4STakashi Sakamoto 		      unsigned int pid, u8 *buf, unsigned int *len,
2235cd1d3f4STakashi Sakamoto 		      u8 **formats)
2245cd1d3f4STakashi Sakamoto {
2255cd1d3f4STakashi Sakamoto 	struct snd_oxfw_stream_formation formation;
2265cd1d3f4STakashi Sakamoto 	unsigned int i, eid;
2275cd1d3f4STakashi Sakamoto 	int err;
2285cd1d3f4STakashi Sakamoto 
2295cd1d3f4STakashi Sakamoto 	/* get format at current sampling rate */
2305cd1d3f4STakashi Sakamoto 	err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
2315cd1d3f4STakashi Sakamoto 	if (err < 0) {
2325cd1d3f4STakashi Sakamoto 		dev_err(&oxfw->unit->device,
2335cd1d3f4STakashi Sakamoto 		"fail to get current stream format for isoc %s plug %d:%d\n",
2345cd1d3f4STakashi Sakamoto 			(dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
2355cd1d3f4STakashi Sakamoto 			pid, err);
2365cd1d3f4STakashi Sakamoto 		goto end;
2375cd1d3f4STakashi Sakamoto 	}
2385cd1d3f4STakashi Sakamoto 
2395cd1d3f4STakashi Sakamoto 	/* parse and set stream format */
2405cd1d3f4STakashi Sakamoto 	eid = 0;
2415cd1d3f4STakashi Sakamoto 	err = snd_oxfw_stream_parse_format(buf, &formation);
2425cd1d3f4STakashi Sakamoto 	if (err < 0)
2435cd1d3f4STakashi Sakamoto 		goto end;
2445cd1d3f4STakashi Sakamoto 
2455cd1d3f4STakashi Sakamoto 	formats[eid] = kmalloc(*len, GFP_KERNEL);
2465cd1d3f4STakashi Sakamoto 	if (formats[eid] == NULL) {
2475cd1d3f4STakashi Sakamoto 		err = -ENOMEM;
2485cd1d3f4STakashi Sakamoto 		goto end;
2495cd1d3f4STakashi Sakamoto 	}
2505cd1d3f4STakashi Sakamoto 	memcpy(formats[eid], buf, *len);
2515cd1d3f4STakashi Sakamoto 
2525cd1d3f4STakashi Sakamoto 	/* apply the format for each available sampling rate */
2535cd1d3f4STakashi Sakamoto 	for (i = 0; i < ARRAY_SIZE(oxfw_rate_table); i++) {
2545cd1d3f4STakashi Sakamoto 		if (formation.rate == oxfw_rate_table[i])
2555cd1d3f4STakashi Sakamoto 			continue;
2565cd1d3f4STakashi Sakamoto 
2575cd1d3f4STakashi Sakamoto 		err = avc_general_inquiry_sig_fmt(oxfw->unit,
2585cd1d3f4STakashi Sakamoto 						  oxfw_rate_table[i],
2595cd1d3f4STakashi Sakamoto 						  dir, pid);
2605cd1d3f4STakashi Sakamoto 		if (err < 0)
2615cd1d3f4STakashi Sakamoto 			continue;
2625cd1d3f4STakashi Sakamoto 
2635cd1d3f4STakashi Sakamoto 		eid++;
2645cd1d3f4STakashi Sakamoto 		formats[eid] = kmalloc(*len, GFP_KERNEL);
2655cd1d3f4STakashi Sakamoto 		if (formats[eid] == NULL) {
2665cd1d3f4STakashi Sakamoto 			err = -ENOMEM;
2675cd1d3f4STakashi Sakamoto 			goto end;
2685cd1d3f4STakashi Sakamoto 		}
2695cd1d3f4STakashi Sakamoto 		memcpy(formats[eid], buf, *len);
2705cd1d3f4STakashi Sakamoto 		formats[eid][2] = avc_stream_rate_table[i];
2715cd1d3f4STakashi Sakamoto 	}
2725cd1d3f4STakashi Sakamoto 
2735cd1d3f4STakashi Sakamoto 	err = 0;
2745cd1d3f4STakashi Sakamoto 	oxfw->assumed = true;
2755cd1d3f4STakashi Sakamoto end:
2765cd1d3f4STakashi Sakamoto 	return err;
2775cd1d3f4STakashi Sakamoto }
2785cd1d3f4STakashi Sakamoto 
2795cd1d3f4STakashi Sakamoto static int fill_stream_formats(struct snd_oxfw *oxfw,
2805cd1d3f4STakashi Sakamoto 			       enum avc_general_plug_dir dir,
2815cd1d3f4STakashi Sakamoto 			       unsigned short pid)
2825cd1d3f4STakashi Sakamoto {
2835cd1d3f4STakashi Sakamoto 	u8 *buf, **formats;
2845cd1d3f4STakashi Sakamoto 	unsigned int len, eid = 0;
2855cd1d3f4STakashi Sakamoto 	struct snd_oxfw_stream_formation dummy;
2865cd1d3f4STakashi Sakamoto 	int err;
2875cd1d3f4STakashi Sakamoto 
2885cd1d3f4STakashi Sakamoto 	buf = kmalloc(AVC_GENERIC_FRAME_MAXIMUM_BYTES, GFP_KERNEL);
2895cd1d3f4STakashi Sakamoto 	if (buf == NULL)
2905cd1d3f4STakashi Sakamoto 		return -ENOMEM;
2915cd1d3f4STakashi Sakamoto 
2925cd1d3f4STakashi Sakamoto 	formats = oxfw->rx_stream_formats;
2935cd1d3f4STakashi Sakamoto 
2945cd1d3f4STakashi Sakamoto 	/* get first entry */
2955cd1d3f4STakashi Sakamoto 	len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
2965cd1d3f4STakashi Sakamoto 	err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0);
2975cd1d3f4STakashi Sakamoto 	if (err == -ENOSYS) {
2985cd1d3f4STakashi Sakamoto 		/* LIST subfunction is not implemented */
2995cd1d3f4STakashi Sakamoto 		len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
3005cd1d3f4STakashi Sakamoto 		err = assume_stream_formats(oxfw, dir, pid, buf, &len,
3015cd1d3f4STakashi Sakamoto 					    formats);
3025cd1d3f4STakashi Sakamoto 		goto end;
3035cd1d3f4STakashi Sakamoto 	} else if (err < 0) {
3045cd1d3f4STakashi Sakamoto 		dev_err(&oxfw->unit->device,
3055cd1d3f4STakashi Sakamoto 			"fail to get stream format %d for isoc %s plug %d:%d\n",
3065cd1d3f4STakashi Sakamoto 			eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
3075cd1d3f4STakashi Sakamoto 			pid, err);
3085cd1d3f4STakashi Sakamoto 		goto end;
3095cd1d3f4STakashi Sakamoto 	}
3105cd1d3f4STakashi Sakamoto 
3115cd1d3f4STakashi Sakamoto 	/* LIST subfunction is implemented */
3125cd1d3f4STakashi Sakamoto 	while (eid < SND_OXFW_STREAM_FORMAT_ENTRIES) {
3135cd1d3f4STakashi Sakamoto 		/* The format is too short. */
3145cd1d3f4STakashi Sakamoto 		if (len < 3) {
3155cd1d3f4STakashi Sakamoto 			err = -EIO;
3165cd1d3f4STakashi Sakamoto 			break;
3175cd1d3f4STakashi Sakamoto 		}
3185cd1d3f4STakashi Sakamoto 
3195cd1d3f4STakashi Sakamoto 		/* parse and set stream format */
3205cd1d3f4STakashi Sakamoto 		err = snd_oxfw_stream_parse_format(buf, &dummy);
3215cd1d3f4STakashi Sakamoto 		if (err < 0)
3225cd1d3f4STakashi Sakamoto 			break;
3235cd1d3f4STakashi Sakamoto 
3245cd1d3f4STakashi Sakamoto 		formats[eid] = kmalloc(len, GFP_KERNEL);
3255cd1d3f4STakashi Sakamoto 		if (formats[eid] == NULL) {
3265cd1d3f4STakashi Sakamoto 			err = -ENOMEM;
3275cd1d3f4STakashi Sakamoto 			break;
3285cd1d3f4STakashi Sakamoto 		}
3295cd1d3f4STakashi Sakamoto 		memcpy(formats[eid], buf, len);
3305cd1d3f4STakashi Sakamoto 
3315cd1d3f4STakashi Sakamoto 		/* get next entry */
3325cd1d3f4STakashi Sakamoto 		len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
3335cd1d3f4STakashi Sakamoto 		err = avc_stream_get_format_list(oxfw->unit, dir, 0,
3345cd1d3f4STakashi Sakamoto 						 buf, &len, ++eid);
3355cd1d3f4STakashi Sakamoto 		/* No entries remained. */
3365cd1d3f4STakashi Sakamoto 		if (err == -EINVAL) {
3375cd1d3f4STakashi Sakamoto 			err = 0;
3385cd1d3f4STakashi Sakamoto 			break;
3395cd1d3f4STakashi Sakamoto 		} else if (err < 0) {
3405cd1d3f4STakashi Sakamoto 			dev_err(&oxfw->unit->device,
3415cd1d3f4STakashi Sakamoto 			"fail to get stream format %d for isoc %s plug %d:%d\n",
3425cd1d3f4STakashi Sakamoto 				eid, (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" :
3435cd1d3f4STakashi Sakamoto 									"out",
3445cd1d3f4STakashi Sakamoto 				pid, err);
3455cd1d3f4STakashi Sakamoto 			break;
3465cd1d3f4STakashi Sakamoto 		}
3475cd1d3f4STakashi Sakamoto 	}
3485cd1d3f4STakashi Sakamoto end:
3495cd1d3f4STakashi Sakamoto 	kfree(buf);
3505cd1d3f4STakashi Sakamoto 	return err;
3515cd1d3f4STakashi Sakamoto }
3525cd1d3f4STakashi Sakamoto 
3535cd1d3f4STakashi Sakamoto int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
3545cd1d3f4STakashi Sakamoto {
3555cd1d3f4STakashi Sakamoto 	u8 plugs[AVC_PLUG_INFO_BUF_BYTES];
3565cd1d3f4STakashi Sakamoto 	int err;
3575cd1d3f4STakashi Sakamoto 
3585cd1d3f4STakashi Sakamoto 	/* the number of plugs for isoc in/out, ext in/out  */
3595cd1d3f4STakashi Sakamoto 	err = avc_general_get_plug_info(oxfw->unit, 0x1f, 0x07, 0x00, plugs);
3605cd1d3f4STakashi Sakamoto 	if (err < 0) {
3615cd1d3f4STakashi Sakamoto 		dev_err(&oxfw->unit->device,
3625cd1d3f4STakashi Sakamoto 		"fail to get info for isoc/external in/out plugs: %d\n",
3635cd1d3f4STakashi Sakamoto 			err);
3645cd1d3f4STakashi Sakamoto 		goto end;
3655cd1d3f4STakashi Sakamoto 	} else if (plugs[0] == 0) {
3665cd1d3f4STakashi Sakamoto 		err = -ENOSYS;
3675cd1d3f4STakashi Sakamoto 		goto end;
3685cd1d3f4STakashi Sakamoto 	}
3695cd1d3f4STakashi Sakamoto 
3705cd1d3f4STakashi Sakamoto 	/* use iPCR[0] if exists */
3715cd1d3f4STakashi Sakamoto 	if (plugs[0] > 0)
3725cd1d3f4STakashi Sakamoto 		err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
3735cd1d3f4STakashi Sakamoto end:
3745cd1d3f4STakashi Sakamoto 	return err;
3755cd1d3f4STakashi Sakamoto }
376