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