^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) }