aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-04-25 09:45:15 -0400
committerTakashi Iwai <tiwai@suse.de>2014-05-26 08:29:29 -0400
commiteb7b3a056cd8130e45c4494fb27de54d53ce9f31 (patch)
tree13971a8c6d72473e1c53b1a092041a148db176ed /sound
parentfd6f4b0dc167c6329a153ceeeb95bc41307156f3 (diff)
ALSA: bebob: Add commands and connections/streams management
This commit adds management functionality for connections and streams. BeBoB uses CMP to manage connections and uses AMDTP for streams. This commit also adds some BridgeCo's AV/C extension commands. There are some BridgeCo's AV/C extension commands but this commit just uses below commands to get device's capability and status: 1.Extended Plug Info commands - Plug Channel Position Specific Data - Plug Type Specific Data - Cluster(Section) Info Specific Data - Plug Input Specific Data 2.Extended Stream Format Information commands - Extended Stream Format Information Command - List Request For Extended Plug Info commands for Cluster Info Specific Data, I pick up 'section' instead of 'cluster' from document to prevent from misunderstanding because 'cluster' is also used in IEC 61883-6. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/firewire/bebob/Makefile2
-rw-r--r--sound/firewire/bebob/bebob.c15
-rw-r--r--sound/firewire/bebob/bebob.h114
-rw-r--r--sound/firewire/bebob/bebob_command.c205
-rw-r--r--sound/firewire/bebob/bebob_stream.c874
5 files changed, 1208 insertions, 2 deletions
diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile
index c6f014188bbd..5cece62e30c0 100644
--- a/sound/firewire/bebob/Makefile
+++ b/sound/firewire/bebob/Makefile
@@ -1,2 +1,2 @@
1snd-bebob-objs := bebob.o 1snd-bebob-objs := bebob_command.o bebob_stream.o bebob.o
2obj-m += snd-bebob.o 2obj-m += snd-bebob.o
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index b5644ab473c6..180284db84c9 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -158,9 +158,20 @@ bebob_probe(struct fw_unit *unit,
158 if (err < 0) 158 if (err < 0)
159 goto error; 159 goto error;
160 160
161 err = snd_card_register(card); 161 err = snd_bebob_stream_discover(bebob);
162 if (err < 0) 162 if (err < 0)
163 goto error; 163 goto error;
164
165 err = snd_bebob_stream_init_duplex(bebob);
166 if (err < 0)
167 goto error;
168
169 err = snd_card_register(card);
170 if (err < 0) {
171 snd_bebob_stream_destroy_duplex(bebob);
172 goto error;
173 }
174
164 dev_set_drvdata(&unit->device, bebob); 175 dev_set_drvdata(&unit->device, bebob);
165end: 176end:
166 mutex_unlock(&devices_mutex); 177 mutex_unlock(&devices_mutex);
@@ -176,11 +187,13 @@ bebob_update(struct fw_unit *unit)
176{ 187{
177 struct snd_bebob *bebob = dev_get_drvdata(&unit->device); 188 struct snd_bebob *bebob = dev_get_drvdata(&unit->device);
178 fcp_bus_reset(bebob->unit); 189 fcp_bus_reset(bebob->unit);
190 snd_bebob_stream_update_duplex(bebob);
179} 191}
180 192
181static void bebob_remove(struct fw_unit *unit) 193static void bebob_remove(struct fw_unit *unit)
182{ 194{
183 struct snd_bebob *bebob = dev_get_drvdata(&unit->device); 195 struct snd_bebob *bebob = dev_get_drvdata(&unit->device);
196 snd_bebob_stream_destroy_duplex(bebob);
184 snd_card_disconnect(bebob->card); 197 snd_card_disconnect(bebob->card);
185 snd_card_free_when_closed(bebob->card); 198 snd_card_free_when_closed(bebob->card);
186} 199}
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h
index 862f756ec281..a195c16da41e 100644
--- a/sound/firewire/bebob/bebob.h
+++ b/sound/firewire/bebob/bebob.h
@@ -23,11 +23,25 @@
23 23
24#include "../lib.h" 24#include "../lib.h"
25#include "../fcp.h" 25#include "../fcp.h"
26#include "../packets-buffer.h"
27#include "../iso-resources.h"
28#include "../amdtp.h"
29#include "../cmp.h"
26 30
27/* basic register addresses on DM1000/DM1100/DM1500 */ 31/* basic register addresses on DM1000/DM1100/DM1500 */
28#define BEBOB_ADDR_REG_INFO 0xffffc8020000 32#define BEBOB_ADDR_REG_INFO 0xffffc8020000
29#define BEBOB_ADDR_REG_REQ 0xffffc8021000 33#define BEBOB_ADDR_REG_REQ 0xffffc8021000
30 34
35struct snd_bebob;
36
37#define SND_BEBOB_STRM_FMT_ENTRIES 7
38struct snd_bebob_stream_formation {
39 unsigned int pcm;
40 unsigned int midi;
41};
42/* this is a lookup table for index of stream formations */
43extern const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES];
44
31struct snd_bebob { 45struct snd_bebob {
32 struct snd_card *card; 46 struct snd_card *card;
33 struct fw_unit *unit; 47 struct fw_unit *unit;
@@ -35,6 +49,24 @@ struct snd_bebob {
35 49
36 struct mutex mutex; 50 struct mutex mutex;
37 spinlock_t lock; 51 spinlock_t lock;
52
53 unsigned int midi_input_ports;
54 unsigned int midi_output_ports;
55
56 struct amdtp_stream *master;
57 struct amdtp_stream tx_stream;
58 struct amdtp_stream rx_stream;
59 struct cmp_connection out_conn;
60 struct cmp_connection in_conn;
61 atomic_t capture_substreams;
62 atomic_t playback_substreams;
63
64 struct snd_bebob_stream_formation
65 tx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
66 struct snd_bebob_stream_formation
67 rx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
68
69 int sync_input_plug;
38}; 70};
39 71
40static inline int 72static inline int
@@ -53,6 +85,88 @@ snd_bebob_read_quad(struct fw_unit *unit, u64 addr, u32 *buf)
53 (void *)buf, sizeof(u32), 0); 85 (void *)buf, sizeof(u32), 0);
54} 86}
55 87
88/*
89 * AVC command extensions, AV/C Unit and Subunit, Revision 17
90 * (Nov 2003, BridgeCo)
91 */
92#define AVC_BRIDGECO_ADDR_BYTES 6
93enum avc_bridgeco_plug_dir {
94 AVC_BRIDGECO_PLUG_DIR_IN = 0x00,
95 AVC_BRIDGECO_PLUG_DIR_OUT = 0x01
96};
97enum avc_bridgeco_plug_mode {
98 AVC_BRIDGECO_PLUG_MODE_UNIT = 0x00,
99 AVC_BRIDGECO_PLUG_MODE_SUBUNIT = 0x01,
100 AVC_BRIDGECO_PLUG_MODE_FUNCTION_BLOCK = 0x02
101};
102enum avc_bridgeco_plug_unit {
103 AVC_BRIDGECO_PLUG_UNIT_ISOC = 0x00,
104 AVC_BRIDGECO_PLUG_UNIT_EXT = 0x01,
105 AVC_BRIDGECO_PLUG_UNIT_ASYNC = 0x02
106};
107enum avc_bridgeco_plug_type {
108 AVC_BRIDGECO_PLUG_TYPE_ISOC = 0x00,
109 AVC_BRIDGECO_PLUG_TYPE_ASYNC = 0x01,
110 AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02,
111 AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03,
112 AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04,
113 AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05
114};
115static inline void
116avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES],
117 enum avc_bridgeco_plug_dir dir,
118 enum avc_bridgeco_plug_unit unit,
119 unsigned int pid)
120{
121 buf[0] = 0xff; /* Unit */
122 buf[1] = dir;
123 buf[2] = AVC_BRIDGECO_PLUG_MODE_UNIT;
124 buf[3] = unit;
125 buf[4] = 0xff & pid;
126 buf[5] = 0xff; /* reserved */
127}
128static inline void
129avc_bridgeco_fill_msu_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES],
130 enum avc_bridgeco_plug_dir dir,
131 unsigned int pid)
132{
133 buf[0] = 0x60; /* Music subunit */
134 buf[1] = dir;
135 buf[2] = AVC_BRIDGECO_PLUG_MODE_SUBUNIT;
136 buf[3] = 0xff & pid;
137 buf[4] = 0xff; /* reserved */
138 buf[5] = 0xff; /* reserved */
139}
140int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
141 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
142 u8 *buf, unsigned int len);
143int avc_bridgeco_get_plug_type(struct fw_unit *unit,
144 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
145 enum avc_bridgeco_plug_type *type);
146int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
147 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
148 unsigned int id, u8 *type);
149int avc_bridgeco_get_plug_input(struct fw_unit *unit,
150 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
151 u8 input[7]);
152int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
153 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
154 unsigned int *len, unsigned int eid);
155
156/* for AMDTP streaming */
157int snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *rate);
158int snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate);
159int snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob,
160 bool *internal);
161int snd_bebob_stream_discover(struct snd_bebob *bebob);
162int snd_bebob_stream_map(struct snd_bebob *bebob,
163 struct amdtp_stream *stream);
164int snd_bebob_stream_init_duplex(struct snd_bebob *bebob);
165int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, int rate);
166void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob);
167void snd_bebob_stream_update_duplex(struct snd_bebob *bebob);
168void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob);
169
56#define SND_BEBOB_DEV_ENTRY(vendor, model) \ 170#define SND_BEBOB_DEV_ENTRY(vendor, model) \
57{ \ 171{ \
58 .match_flags = IEEE1394_MATCH_VENDOR_ID | \ 172 .match_flags = IEEE1394_MATCH_VENDOR_ID | \
diff --git a/sound/firewire/bebob/bebob_command.c b/sound/firewire/bebob/bebob_command.c
new file mode 100644
index 000000000000..6a017951a888
--- /dev/null
+++ b/sound/firewire/bebob/bebob_command.c
@@ -0,0 +1,205 @@
1/*
2 * bebob_command.c - driver for BeBoB based devices
3 *
4 * Copyright (c) 2013-2014 Takashi Sakamoto
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8
9#include "./bebob.h"
10
11static inline void
12avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
13{
14 buf[1] = addr[0];
15 memcpy(buf + 4, addr + 1, 5);
16}
17
18static inline void
19avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
20 unsigned int itype)
21{
22 buf[0] = 0x01; /* AV/C STATUS */
23 buf[2] = 0x02; /* AV/C GENERAL PLUG INFO */
24 buf[3] = 0xc0; /* BridgeCo extension */
25 avc_bridgeco_fill_extension_addr(buf, addr);
26 buf[9] = itype; /* info type */
27}
28
29int avc_bridgeco_get_plug_type(struct fw_unit *unit,
30 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
31 enum avc_bridgeco_plug_type *type)
32{
33 u8 *buf;
34 int err;
35
36 buf = kzalloc(12, GFP_KERNEL);
37 if (buf == NULL)
38 return -ENOMEM;
39
40 /* Info type is 'plug type'. */
41 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
42
43 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
44 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
45 BIT(6) | BIT(7) | BIT(9));
46 if ((err >= 0) && (err < 8))
47 err = -EIO;
48 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
49 err = -ENOSYS;
50 else if (buf[0] == 0x0a) /* REJECTED */
51 err = -EINVAL;
52 else if (buf[0] == 0x0b) /* IN TRANSITION */
53 err = -EAGAIN;
54 if (err < 0)
55 goto end;
56
57 *type = buf[10];
58 err = 0;
59end:
60 kfree(buf);
61 return err;
62}
63
64int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
65 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
66 u8 *buf, unsigned int len)
67{
68 int err;
69
70 /* Info type is 'channel position'. */
71 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
72
73 err = fcp_avc_transaction(unit, buf, 12, buf, 256,
74 BIT(1) | BIT(2) | BIT(3) | BIT(4) |
75 BIT(5) | BIT(6) | BIT(7) | BIT(9));
76 if ((err >= 0) && (err < 8))
77 err = -EIO;
78 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
79 err = -ENOSYS;
80 else if (buf[0] == 0x0a) /* REJECTED */
81 err = -EINVAL;
82 else if (buf[0] == 0x0b) /* IN TRANSITION */
83 err = -EAGAIN;
84 if (err < 0)
85 goto end;
86
87 /* Pick up specific data. */
88 memmove(buf, buf + 10, err - 10);
89 err = 0;
90end:
91 return err;
92}
93
94int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
95 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
96 unsigned int id, u8 *type)
97{
98 u8 *buf;
99 int err;
100
101 /* section info includes charactors but this module don't need it */
102 buf = kzalloc(12, GFP_KERNEL);
103 if (buf == NULL)
104 return -ENOMEM;
105
106 /* Info type is 'section info'. */
107 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
108 buf[10] = 0xff & ++id; /* section id */
109
110 err = fcp_avc_transaction(unit, buf, 12, buf, 12,
111 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
112 BIT(6) | BIT(7) | BIT(9) | BIT(10));
113 if ((err >= 0) && (err < 8))
114 err = -EIO;
115 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
116 err = -ENOSYS;
117 else if (buf[0] == 0x0a) /* REJECTED */
118 err = -EINVAL;
119 else if (buf[0] == 0x0b) /* IN TRANSITION */
120 err = -EAGAIN;
121 if (err < 0)
122 goto end;
123
124 *type = buf[11];
125 err = 0;
126end:
127 kfree(buf);
128 return err;
129}
130
131int avc_bridgeco_get_plug_input(struct fw_unit *unit,
132 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
133{
134 int err;
135 u8 *buf;
136
137 buf = kzalloc(18, GFP_KERNEL);
138 if (buf == NULL)
139 return -ENOMEM;
140
141 /* Info type is 'plug input'. */
142 avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
143
144 err = fcp_avc_transaction(unit, buf, 16, buf, 16,
145 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
146 BIT(6) | BIT(7));
147 if ((err >= 0) && (err < 8))
148 err = -EIO;
149 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
150 err = -ENOSYS;
151 else if (buf[0] == 0x0a) /* REJECTED */
152 err = -EINVAL;
153 else if (buf[0] == 0x0b) /* IN TRANSITION */
154 err = -EAGAIN;
155 if (err < 0)
156 goto end;
157
158 memcpy(input, buf + 10, 5);
159 err = 0;
160end:
161 kfree(buf);
162 return err;
163}
164
165int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
166 u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
167 unsigned int *len, unsigned int eid)
168{
169 int err;
170
171 /* check given buffer */
172 if ((buf == NULL) || (*len < 12)) {
173 err = -EINVAL;
174 goto end;
175 }
176
177 buf[0] = 0x01; /* AV/C STATUS */
178 buf[2] = 0x2f; /* AV/C STREAM FORMAT SUPPORT */
179 buf[3] = 0xc1; /* Bridgeco extension - List Request */
180 avc_bridgeco_fill_extension_addr(buf, addr);
181 buf[10] = 0xff & eid; /* Entry ID */
182
183 err = fcp_avc_transaction(unit, buf, 12, buf, *len,
184 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
185 BIT(6) | BIT(7) | BIT(10));
186 if ((err >= 0) && (err < 12))
187 err = -EIO;
188 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
189 err = -ENOSYS;
190 else if (buf[0] == 0x0a) /* REJECTED */
191 err = -EINVAL;
192 else if (buf[0] == 0x0b) /* IN TRANSITION */
193 err = -EAGAIN;
194 else if (buf[10] != eid)
195 err = -EIO;
196 if (err < 0)
197 goto end;
198
199 /* Pick up 'stream format info'. */
200 memmove(buf, buf + 11, err - 11);
201 *len = err - 11;
202 err = 0;
203end:
204 return err;
205}
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
new file mode 100644
index 000000000000..c868c17c6fc4
--- /dev/null
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -0,0 +1,874 @@
1/*
2 * bebob_stream.c - a part of driver for BeBoB based devices
3 *
4 * Copyright (c) 2013-2014 Takashi Sakamoto
5 *
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
8
9#include "./bebob.h"
10
11#define CALLBACK_TIMEOUT 1000
12
13/*
14 * NOTE;
15 * For BeBoB streams, Both of input and output CMP connection are important.
16 *
17 * For most devices, each CMP connection starts to transmit/receive a
18 * corresponding stream. But for a few devices, both of CMP connection needs
19 * to start transmitting stream. An example is 'M-Audio Firewire 410'.
20 */
21
22/* 128 is an arbitrary length but it seems to be enough */
23#define FORMAT_MAXIMUM_LENGTH 128
24
25const unsigned int snd_bebob_rate_table[SND_BEBOB_STRM_FMT_ENTRIES] = {
26 [0] = 32000,
27 [1] = 44100,
28 [2] = 48000,
29 [3] = 88200,
30 [4] = 96000,
31 [5] = 176400,
32 [6] = 192000,
33};
34
35/*
36 * See: Table 51: Extended Stream Format Info ‘Sampling Frequency’
37 * in Additional AVC commands (Nov 2003, BridgeCo)
38 */
39static const unsigned int bridgeco_freq_table[] = {
40 [0] = 0x02,
41 [1] = 0x03,
42 [2] = 0x04,
43 [3] = 0x0a,
44 [4] = 0x05,
45 [5] = 0x06,
46 [6] = 0x07,
47};
48
49static unsigned int
50get_formation_index(unsigned int rate)
51{
52 unsigned int i;
53
54 for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) {
55 if (snd_bebob_rate_table[i] == rate)
56 return i;
57 }
58 return -EINVAL;
59}
60
61int
62snd_bebob_stream_get_rate(struct snd_bebob *bebob, unsigned int *curr_rate)
63{
64 unsigned int tx_rate, rx_rate, trials;
65 int err;
66
67 trials = 0;
68 do {
69 err = avc_general_get_sig_fmt(bebob->unit, &tx_rate,
70 AVC_GENERAL_PLUG_DIR_OUT, 0);
71 } while (err == -EAGAIN && ++trials < 3);
72 if (err < 0)
73 goto end;
74
75 trials = 0;
76 do {
77 err = avc_general_get_sig_fmt(bebob->unit, &rx_rate,
78 AVC_GENERAL_PLUG_DIR_IN, 0);
79 } while (err == -EAGAIN && ++trials < 3);
80 if (err < 0)
81 goto end;
82
83 *curr_rate = rx_rate;
84 if (rx_rate == tx_rate)
85 goto end;
86
87 /* synchronize receive stream rate to transmit stream rate */
88 err = avc_general_set_sig_fmt(bebob->unit, rx_rate,
89 AVC_GENERAL_PLUG_DIR_IN, 0);
90end:
91 return err;
92}
93
94int
95snd_bebob_stream_set_rate(struct snd_bebob *bebob, unsigned int rate)
96{
97 int err;
98
99 err = avc_general_set_sig_fmt(bebob->unit, rate,
100 AVC_GENERAL_PLUG_DIR_OUT, 0);
101 if (err < 0)
102 goto end;
103
104 err = avc_general_set_sig_fmt(bebob->unit, rate,
105 AVC_GENERAL_PLUG_DIR_IN, 0);
106 if (err < 0)
107 goto end;
108
109 /*
110 * Some devices need a bit time for transition.
111 * 300msec is got by some experiments.
112 */
113 msleep(300);
114end:
115 return err;
116}
117
118int
119snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
120{
121 u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7];
122 int err = 0;
123
124 *internal = false;
125
126 /*
127 * 1.The device don't support to switch source of clock then assumed
128 * to use internal clock always
129 */
130 if (bebob->sync_input_plug < 0) {
131 *internal = true;
132 goto end;
133 }
134
135 /*
136 * 2.The device supports to switch source of clock by an usual way.
137 * Let's check input for 'Music Sub Unit Sync Input' plug.
138 */
139 avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN,
140 bebob->sync_input_plug);
141 err = avc_bridgeco_get_plug_input(bebob->unit, addr, input);
142 if (err < 0) {
143 dev_err(&bebob->unit->device,
144 "fail to get an input for MSU in plug %d: %d\n",
145 bebob->sync_input_plug, err);
146 goto end;
147 }
148
149 /*
150 * If there are no input plugs, all of fields are 0xff.
151 * Here check the first field. This field is used for direction.
152 */
153 if (input[0] == 0xff) {
154 *internal = true;
155 goto end;
156 }
157
158 /*
159 * If source of clock is internal CSR, Music Sub Unit Sync Input is
160 * a destination of Music Sub Unit Sync Output.
161 */
162 *internal = ((input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) &&
163 (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT) &&
164 (input[2] == 0x0c) &&
165 (input[3] == 0x00));
166end:
167 return err;
168}
169
170static unsigned int
171map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s)
172{
173 unsigned int sec, sections, ch, channels;
174 unsigned int pcm, midi, location;
175 unsigned int stm_pos, sec_loc, pos;
176 u8 *buf, addr[AVC_BRIDGECO_ADDR_BYTES], type;
177 enum avc_bridgeco_plug_dir dir;
178 int err;
179
180 /*
181 * The length of return value of this command cannot be expected. Here
182 * use the maximum length of FCP.
183 */
184 buf = kzalloc(256, GFP_KERNEL);
185 if (buf == NULL)
186 return -ENOMEM;
187
188 if (s == &bebob->tx_stream)
189 dir = AVC_BRIDGECO_PLUG_DIR_OUT;
190 else
191 dir = AVC_BRIDGECO_PLUG_DIR_IN;
192
193 avc_bridgeco_fill_unit_addr(addr, dir, AVC_BRIDGECO_PLUG_UNIT_ISOC, 0);
194 err = avc_bridgeco_get_plug_ch_pos(bebob->unit, addr, buf, 256);
195 if (err < 0) {
196 dev_err(&bebob->unit->device,
197 "fail to get channel position for isoc %s plug 0: %d\n",
198 (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" : "out",
199 err);
200 goto end;
201 }
202 pos = 0;
203
204 /* positions in I/O buffer */
205 pcm = 0;
206 midi = 0;
207
208 /* the number of sections in AMDTP packet */
209 sections = buf[pos++];
210
211 for (sec = 0; sec < sections; sec++) {
212 /* type of this section */
213 avc_bridgeco_fill_unit_addr(addr, dir,
214 AVC_BRIDGECO_PLUG_UNIT_ISOC, 0);
215 err = avc_bridgeco_get_plug_section_type(bebob->unit, addr,
216 sec, &type);
217 if (err < 0) {
218 dev_err(&bebob->unit->device,
219 "fail to get section type for isoc %s plug 0: %d\n",
220 (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" :
221 "out",
222 err);
223 goto end;
224 }
225 /* NoType */
226 if (type == 0xff) {
227 err = -ENOSYS;
228 goto end;
229 }
230
231 /* the number of channels in this section */
232 channels = buf[pos++];
233
234 for (ch = 0; ch < channels; ch++) {
235 /* position of this channel in AMDTP packet */
236 stm_pos = buf[pos++] - 1;
237 /* location of this channel in this section */
238 sec_loc = buf[pos++] - 1;
239
240 switch (type) {
241 /* for MIDI conformant data channel */
242 case 0x0a:
243 /* AMDTP_MAX_CHANNELS_FOR_MIDI is 1. */
244 if ((midi > 0) && (stm_pos != midi)) {
245 err = -ENOSYS;
246 goto end;
247 }
248 s->midi_position = stm_pos;
249 midi = stm_pos;
250 break;
251 /* for PCM data channel */
252 case 0x01: /* Headphone */
253 case 0x02: /* Microphone */
254 case 0x03: /* Line */
255 case 0x04: /* SPDIF */
256 case 0x05: /* ADAT */
257 case 0x06: /* TDIF */
258 case 0x07: /* MADI */
259 /* for undefined/changeable signal */
260 case 0x08: /* Analog */
261 case 0x09: /* Digital */
262 default:
263 location = pcm + sec_loc;
264 if (location >= AMDTP_MAX_CHANNELS_FOR_PCM) {
265 err = -ENOSYS;
266 goto end;
267 }
268 s->pcm_positions[location] = stm_pos;
269 break;
270 }
271 }
272
273 if (type != 0x0a)
274 pcm += channels;
275 else
276 midi += channels;
277 }
278end:
279 kfree(buf);
280 return err;
281}
282
283static int
284init_both_connections(struct snd_bebob *bebob)
285{
286 int err;
287
288 err = cmp_connection_init(&bebob->in_conn,
289 bebob->unit, CMP_INPUT, 0);
290 if (err < 0)
291 goto end;
292
293 err = cmp_connection_init(&bebob->out_conn,
294 bebob->unit, CMP_OUTPUT, 0);
295 if (err < 0)
296 cmp_connection_destroy(&bebob->in_conn);
297end:
298 return err;
299}
300
301static int
302check_connection_used_by_others(struct snd_bebob *bebob, struct amdtp_stream *s)
303{
304 struct cmp_connection *conn;
305 bool used;
306 int err;
307
308 if (s == &bebob->tx_stream)
309 conn = &bebob->out_conn;
310 else
311 conn = &bebob->in_conn;
312
313 err = cmp_connection_check_used(conn, &used);
314 if ((err >= 0) && used && !amdtp_stream_running(s)) {
315 dev_err(&bebob->unit->device,
316 "Connection established by others: %cPCR[%d]\n",
317 (conn->direction == CMP_OUTPUT) ? 'o' : 'i',
318 conn->pcr_index);
319 err = -EBUSY;
320 }
321
322 return err;
323}
324
325static int
326make_both_connections(struct snd_bebob *bebob, unsigned int rate)
327{
328 int index, pcm_channels, midi_channels, err;
329
330 /* confirm params for both streams */
331 index = get_formation_index(rate);
332 pcm_channels = bebob->tx_stream_formations[index].pcm;
333 midi_channels = bebob->tx_stream_formations[index].midi;
334 amdtp_stream_set_parameters(&bebob->tx_stream,
335 rate, pcm_channels, midi_channels * 8);
336 pcm_channels = bebob->rx_stream_formations[index].pcm;
337 midi_channels = bebob->rx_stream_formations[index].midi;
338 amdtp_stream_set_parameters(&bebob->rx_stream,
339 rate, pcm_channels, midi_channels * 8);
340
341 /* establish connections for both streams */
342 err = cmp_connection_establish(&bebob->out_conn,
343 amdtp_stream_get_max_payload(&bebob->tx_stream));
344 if (err < 0)
345 goto end;
346 err = cmp_connection_establish(&bebob->in_conn,
347 amdtp_stream_get_max_payload(&bebob->rx_stream));
348 if (err < 0)
349 cmp_connection_break(&bebob->out_conn);
350end:
351 return err;
352}
353
354static void
355break_both_connections(struct snd_bebob *bebob)
356{
357 cmp_connection_break(&bebob->in_conn);
358 cmp_connection_break(&bebob->out_conn);
359}
360
361static void
362destroy_both_connections(struct snd_bebob *bebob)
363{
364 break_both_connections(bebob);
365
366 cmp_connection_destroy(&bebob->in_conn);
367 cmp_connection_destroy(&bebob->out_conn);
368}
369
370static int
371get_sync_mode(struct snd_bebob *bebob, enum cip_flags *sync_mode)
372{
373 /* currently this module doesn't support SYT-Match mode */
374 *sync_mode = CIP_SYNC_TO_DEVICE;
375 return 0;
376}
377
378static int
379start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream,
380 unsigned int rate)
381{
382 struct cmp_connection *conn;
383 int err = 0;
384
385 if (stream == &bebob->rx_stream)
386 conn = &bebob->in_conn;
387 else
388 conn = &bebob->out_conn;
389
390 /* channel mapping */
391 err = map_data_channels(bebob, stream);
392 if (err < 0)
393 goto end;
394
395 /* start amdtp stream */
396 err = amdtp_stream_start(stream,
397 conn->resources.channel,
398 conn->speed);
399end:
400 return err;
401}
402
403int snd_bebob_stream_init_duplex(struct snd_bebob *bebob)
404{
405 int err;
406
407 err = init_both_connections(bebob);
408 if (err < 0)
409 goto end;
410
411 err = amdtp_stream_init(&bebob->tx_stream, bebob->unit,
412 AMDTP_IN_STREAM, CIP_BLOCKING);
413 if (err < 0) {
414 amdtp_stream_destroy(&bebob->tx_stream);
415 destroy_both_connections(bebob);
416 goto end;
417 }
418
419 err = amdtp_stream_init(&bebob->rx_stream, bebob->unit,
420 AMDTP_OUT_STREAM, CIP_BLOCKING);
421 if (err < 0) {
422 amdtp_stream_destroy(&bebob->tx_stream);
423 amdtp_stream_destroy(&bebob->rx_stream);
424 destroy_both_connections(bebob);
425 }
426end:
427 return err;
428}
429
430int snd_bebob_stream_start_duplex(struct snd_bebob *bebob, int rate)
431{
432 struct amdtp_stream *master, *slave;
433 atomic_t *slave_substreams;
434 enum cip_flags sync_mode;
435 unsigned int curr_rate;
436 int err = 0;
437
438 mutex_lock(&bebob->mutex);
439
440 /* Need no substreams */
441 if (atomic_read(&bebob->playback_substreams) == 0 &&
442 atomic_read(&bebob->capture_substreams) == 0)
443 goto end;
444
445 err = get_sync_mode(bebob, &sync_mode);
446 if (err < 0)
447 goto end;
448 if (sync_mode == CIP_SYNC_TO_DEVICE) {
449 master = &bebob->tx_stream;
450 slave = &bebob->rx_stream;
451 slave_substreams = &bebob->playback_substreams;
452 } else {
453 master = &bebob->rx_stream;
454 slave = &bebob->tx_stream;
455 slave_substreams = &bebob->capture_substreams;
456 }
457
458 /*
459 * Considering JACK/FFADO streaming:
460 * TODO: This can be removed hwdep functionality becomes popular.
461 */
462 err = check_connection_used_by_others(bebob, master);
463 if (err < 0)
464 goto end;
465
466 /* packet queueing error */
467 if (amdtp_streaming_error(master)) {
468 amdtp_stream_stop(master);
469 amdtp_stream_stop(slave);
470 }
471 if (amdtp_streaming_error(slave))
472 amdtp_stream_stop(slave);
473
474 /* stop streams if rate is different */
475 err = snd_bebob_stream_get_rate(bebob, &curr_rate);
476 if (err < 0) {
477 dev_err(&bebob->unit->device,
478 "fail to get sampling rate: %d\n", err);
479 goto end;
480 }
481 if (rate == 0)
482 rate = curr_rate;
483 if (rate != curr_rate) {
484 amdtp_stream_stop(master);
485 amdtp_stream_stop(slave);
486 break_both_connections(bebob);
487 }
488
489 /* master should be always running */
490 if (!amdtp_stream_running(master)) {
491 amdtp_stream_set_sync(sync_mode, master, slave);
492 bebob->master = master;
493
494 /*
495 * NOTE:
496 * If establishing connections at first, Yamaha GO46
497 * (and maybe Terratec X24) don't generate sound.
498 */
499 err = snd_bebob_stream_set_rate(bebob, rate);
500 if (err < 0) {
501 dev_err(&bebob->unit->device,
502 "fail to set sampling rate: %d\n",
503 err);
504 goto end;
505 }
506
507 err = make_both_connections(bebob, rate);
508 if (err < 0)
509 goto end;
510
511 err = start_stream(bebob, master, rate);
512 if (err < 0) {
513 dev_err(&bebob->unit->device,
514 "fail to run AMDTP master stream:%d\n", err);
515 break_both_connections(bebob);
516 goto end;
517 }
518
519 /* wait first callback */
520 if (!amdtp_stream_wait_callback(master, CALLBACK_TIMEOUT)) {
521 amdtp_stream_stop(master);
522 break_both_connections(bebob);
523 err = -ETIMEDOUT;
524 goto end;
525 }
526 }
527
528 /* start slave if needed */
529 if (atomic_read(slave_substreams) > 0 && !amdtp_stream_running(slave)) {
530 err = start_stream(bebob, slave, rate);
531 if (err < 0) {
532 dev_err(&bebob->unit->device,
533 "fail to run AMDTP slave stream:%d\n", err);
534 amdtp_stream_stop(master);
535 break_both_connections(bebob);
536 goto end;
537 }
538
539 /* wait first callback */
540 if (!amdtp_stream_wait_callback(slave, CALLBACK_TIMEOUT)) {
541 amdtp_stream_stop(slave);
542 amdtp_stream_stop(master);
543 break_both_connections(bebob);
544 err = -ETIMEDOUT;
545 }
546 }
547end:
548 mutex_unlock(&bebob->mutex);
549 return err;
550}
551
552void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob)
553{
554 struct amdtp_stream *master, *slave;
555 atomic_t *master_substreams, *slave_substreams;
556
557 mutex_lock(&bebob->mutex);
558
559 if (bebob->master == &bebob->rx_stream) {
560 slave = &bebob->tx_stream;
561 master = &bebob->rx_stream;
562 slave_substreams = &bebob->capture_substreams;
563 master_substreams = &bebob->playback_substreams;
564 } else {
565 slave = &bebob->rx_stream;
566 master = &bebob->tx_stream;
567 slave_substreams = &bebob->playback_substreams;
568 master_substreams = &bebob->capture_substreams;
569 }
570
571 if (atomic_read(slave_substreams) == 0) {
572 amdtp_stream_pcm_abort(slave);
573 amdtp_stream_stop(slave);
574
575 if (atomic_read(master_substreams) == 0) {
576 amdtp_stream_pcm_abort(master);
577 amdtp_stream_stop(master);
578 break_both_connections(bebob);
579 }
580 }
581
582 mutex_unlock(&bebob->mutex);
583}
584
585void snd_bebob_stream_update_duplex(struct snd_bebob *bebob)
586{
587 /* vs. XRUN recovery due to discontinuity at bus reset */
588 mutex_lock(&bebob->mutex);
589
590 if ((cmp_connection_update(&bebob->in_conn) < 0) ||
591 (cmp_connection_update(&bebob->out_conn) < 0)) {
592 amdtp_stream_pcm_abort(&bebob->rx_stream);
593 amdtp_stream_pcm_abort(&bebob->tx_stream);
594 amdtp_stream_stop(&bebob->rx_stream);
595 amdtp_stream_stop(&bebob->tx_stream);
596 break_both_connections(bebob);
597 } else {
598 amdtp_stream_update(&bebob->rx_stream);
599 amdtp_stream_update(&bebob->tx_stream);
600 }
601
602 mutex_unlock(&bebob->mutex);
603}
604
605void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob)
606{
607 mutex_lock(&bebob->mutex);
608
609 amdtp_stream_pcm_abort(&bebob->rx_stream);
610 amdtp_stream_pcm_abort(&bebob->tx_stream);
611
612 amdtp_stream_stop(&bebob->rx_stream);
613 amdtp_stream_stop(&bebob->tx_stream);
614
615 amdtp_stream_destroy(&bebob->rx_stream);
616 amdtp_stream_destroy(&bebob->tx_stream);
617
618 destroy_both_connections(bebob);
619
620 mutex_unlock(&bebob->mutex);
621}
622
623/*
624 * See: Table 50: Extended Stream Format Info Format Hierarchy Level 2’
625 * in Additional AVC commands (Nov 2003, BridgeCo)
626 * Also 'Clause 12 AM824 sequence adaption layers' in IEC 61883-6:2005
627 */
628static int
629parse_stream_formation(u8 *buf, unsigned int len,
630 struct snd_bebob_stream_formation *formation)
631{
632 unsigned int i, e, channels, format;
633
634 /*
635 * this module can support a hierarchy combination that:
636 * Root: Audio and Music (0x90)
637 * Level 1: AM824 Compound (0x40)
638 */
639 if ((buf[0] != 0x90) || (buf[1] != 0x40))
640 return -ENOSYS;
641
642 /* check sampling rate */
643 for (i = 0; i < ARRAY_SIZE(bridgeco_freq_table); i++) {
644 if (buf[2] == bridgeco_freq_table[i])
645 break;
646 }
647 if (i == sizeof(bridgeco_freq_table))
648 return -ENOSYS;
649
650 /* Avoid double count by different entries for the same rate. */
651 memset(&formation[i], 0, sizeof(struct snd_bebob_stream_formation));
652
653 for (e = 0; e < buf[4]; e++) {
654 channels = buf[5 + e * 2];
655 format = buf[6 + e * 2];
656
657 switch (format) {
658 /* IEC 60958-3, currently handle as MBLA */
659 case 0x00:
660 /* Multi bit linear audio */
661 case 0x06: /* Raw */
662 formation[i].pcm += channels;
663 break;
664 /* MIDI Conformant */
665 case 0x0d:
666 formation[i].midi += channels;
667 break;
668 /* IEC 61937-3 to 7 */
669 case 0x01:
670 case 0x02:
671 case 0x03:
672 case 0x04:
673 case 0x05:
674 /* Multi bit linear audio */
675 case 0x07: /* DVD-Audio */
676 case 0x0c: /* High Precision */
677 /* One Bit Audio */
678 case 0x08: /* (Plain) Raw */
679 case 0x09: /* (Plain) SACD */
680 case 0x0a: /* (Encoded) Raw */
681 case 0x0b: /* (Encoded) SACD */
682 /* Synchronization Stream (Stereo Raw audio) */
683 case 0x40:
684 /* Don't care */
685 case 0xff:
686 default:
687 return -ENOSYS; /* not supported */
688 }
689 }
690
691 if (formation[i].pcm > AMDTP_MAX_CHANNELS_FOR_PCM ||
692 formation[i].midi > AMDTP_MAX_CHANNELS_FOR_MIDI)
693 return -ENOSYS;
694
695 return 0;
696}
697
698static int
699fill_stream_formations(struct snd_bebob *bebob, enum avc_bridgeco_plug_dir dir,
700 unsigned short pid)
701{
702 u8 *buf;
703 struct snd_bebob_stream_formation *formations;
704 unsigned int len, eid;
705 u8 addr[AVC_BRIDGECO_ADDR_BYTES];
706 int err;
707
708 buf = kmalloc(FORMAT_MAXIMUM_LENGTH, GFP_KERNEL);
709 if (buf == NULL)
710 return -ENOMEM;
711
712 if (dir == AVC_BRIDGECO_PLUG_DIR_IN)
713 formations = bebob->rx_stream_formations;
714 else
715 formations = bebob->tx_stream_formations;
716
717 for (eid = 0; eid < SND_BEBOB_STRM_FMT_ENTRIES; eid++) {
718 len = FORMAT_MAXIMUM_LENGTH;
719 avc_bridgeco_fill_unit_addr(addr, dir,
720 AVC_BRIDGECO_PLUG_UNIT_ISOC, pid);
721 err = avc_bridgeco_get_plug_strm_fmt(bebob->unit, addr, buf,
722 &len, eid);
723 /* No entries remained. */
724 if (err == -EINVAL && eid > 0) {
725 err = 0;
726 break;
727 } else if (err < 0) {
728 dev_err(&bebob->unit->device,
729 "fail to get stream format %d for isoc %s plug %d:%d\n",
730 eid,
731 (dir == AVC_BRIDGECO_PLUG_DIR_IN) ? "in" :
732 "out",
733 pid, err);
734 break;
735 }
736
737 err = parse_stream_formation(buf, len, formations);
738 if (err < 0)
739 break;
740 }
741
742 kfree(buf);
743 return err;
744}
745
746static int
747seek_msu_sync_input_plug(struct snd_bebob *bebob)
748{
749 u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES];
750 unsigned int i, type;
751 int err;
752
753 /* Get the number of Music Sub Unit for both direction. */
754 err = avc_general_get_plug_info(bebob->unit, 0x0c, 0x00, 0x00, plugs);
755 if (err < 0) {
756 dev_err(&bebob->unit->device,
757 "fail to get info for MSU in/out plugs: %d\n",
758 err);
759 goto end;
760 }
761
762 /* seek destination plugs for 'MSU sync input' */
763 bebob->sync_input_plug = -1;
764 for (i = 0; i < plugs[0]; i++) {
765 avc_bridgeco_fill_msu_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN, i);
766 err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
767 if (err < 0) {
768 dev_err(&bebob->unit->device,
769 "fail to get type for MSU in plug %d: %d\n",
770 i, err);
771 goto end;
772 }
773
774 if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) {
775 bebob->sync_input_plug = i;
776 break;
777 }
778 }
779end:
780 return err;
781}
782
783int snd_bebob_stream_discover(struct snd_bebob *bebob)
784{
785 u8 plugs[AVC_PLUG_INFO_BUF_BYTES], addr[AVC_BRIDGECO_ADDR_BYTES];
786 enum avc_bridgeco_plug_type type;
787 unsigned int i;
788 int err;
789
790 /* the number of plugs for isoc in/out, ext in/out */
791 err = avc_general_get_plug_info(bebob->unit, 0x1f, 0x07, 0x00, plugs);
792 if (err < 0) {
793 dev_err(&bebob->unit->device,
794 "fail to get info for isoc/external in/out plugs: %d\n",
795 err);
796 goto end;
797 }
798
799 /*
800 * This module supports at least one isoc input plug and one isoc
801 * output plug.
802 */
803 if ((plugs[0] == 0) || (plugs[1] == 0)) {
804 err = -ENOSYS;
805 goto end;
806 }
807
808 avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN,
809 AVC_BRIDGECO_PLUG_UNIT_ISOC, 0);
810 err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
811 if (err < 0) {
812 dev_err(&bebob->unit->device,
813 "fail to get type for isoc in plug 0: %d\n", err);
814 goto end;
815 } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) {
816 err = -ENOSYS;
817 goto end;
818 }
819 err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_IN, 0);
820 if (err < 0)
821 goto end;
822
823 avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT,
824 AVC_BRIDGECO_PLUG_UNIT_ISOC, 0);
825 err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
826 if (err < 0) {
827 dev_err(&bebob->unit->device,
828 "fail to get type for isoc out plug 0: %d\n", err);
829 goto end;
830 } else if (type != AVC_BRIDGECO_PLUG_TYPE_ISOC) {
831 err = -ENOSYS;
832 goto end;
833 }
834 err = fill_stream_formations(bebob, AVC_BRIDGECO_PLUG_DIR_OUT, 0);
835 if (err < 0)
836 goto end;
837
838 /* count external input plugs for MIDI */
839 bebob->midi_input_ports = 0;
840 for (i = 0; i < plugs[2]; i++) {
841 avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_IN,
842 AVC_BRIDGECO_PLUG_UNIT_EXT, i);
843 err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
844 if (err < 0) {
845 dev_err(&bebob->unit->device,
846 "fail to get type for external in plug %d: %d\n",
847 i, err);
848 goto end;
849 } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) {
850 bebob->midi_input_ports++;
851 }
852 }
853
854 /* count external output plugs for MIDI */
855 bebob->midi_output_ports = 0;
856 for (i = 0; i < plugs[3]; i++) {
857 avc_bridgeco_fill_unit_addr(addr, AVC_BRIDGECO_PLUG_DIR_OUT,
858 AVC_BRIDGECO_PLUG_UNIT_EXT, i);
859 err = avc_bridgeco_get_plug_type(bebob->unit, addr, &type);
860 if (err < 0) {
861 dev_err(&bebob->unit->device,
862 "fail to get type for external out plug %d: %d\n",
863 i, err);
864 goto end;
865 } else if (type == AVC_BRIDGECO_PLUG_TYPE_MIDI) {
866 bebob->midi_output_ports++;
867 }
868 }
869
870 /* for check source of clock later */
871 err = seek_msu_sync_input_plug(bebob);
872end:
873 return err;
874}