aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2015-06-13 23:49:27 -0400
committerTakashi Iwai <tiwai@suse.de>2015-06-15 07:34:13 -0400
commit5a6688127082683f8c343da7d326dc22e45f4e4b (patch)
tree22bc08802000c9c0507136fe26ba5b2bfee1bee8
parent88f1236bfa9586ca458b67abde8ce91665bba079 (diff)
ALSA: bebob: improve signal mode detection for clock source
With BeBoB version 3, current ALSA BeBoB driver detects the type of current clock signal source wrongly. This is due to a lack of proper implementation to parse the information. This commit renews the parser. As a result, this driver detects SYT-Match clock signal, thus it can start streams with two modes; SYT-Match mode and the others. SYT-Match mode will be supported in future commits. There's a constrain about detected internal/external clock source. When detecting external clock source, this driver allows userspace applications to use current sampling rate only. This is due to consider abour synchronization to external clock sources such as S/PDIF, ADAT or word-clock. According to several information from some devices, I guesss that the internal clock of most devices synchronize to IEEE 1394 cycle start packet. In this case, by a usual way, it's detect as 'Sync type of output Music Sub-Unit' connected to 'Sync type of PCR output Unit (oPCR)', and this driver judges it as internal clock. Therefore, userspace applications is allowed to request arbitrary supported sampling rates. On the other hand, several devices based on BeBoB version 3 have additional internal clock. In this case, by a usual way, it's detect as 'Sync/Additional type of External input Unit'. Unfortunately, there's no way to distinguish this sync type from the other external clock sources such as word-clock. In this case, this driver handles it as external and userspace applications is forced to use current sampling rate. I note that when the source of clock is detected as 'Isochronous stream type of input PCR[0]', it's under 'SYT-Match' mode. In this mode, the synchronization clock is generated according to SYT-series in received packets. In this case, this driver generates the series by myself. I experienced this mode often make the device silent suddenly during playbacking. This means that the mode is easy to lost synchronization. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/firewire/bebob/bebob.h3
-rw-r--r--sound/firewire/bebob/bebob_stream.c78
2 files changed, 72 insertions, 9 deletions
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h
index dfbcd233178c..2a918caa88a1 100644
--- a/sound/firewire/bebob/bebob.h
+++ b/sound/firewire/bebob/bebob.h
@@ -159,7 +159,8 @@ enum avc_bridgeco_plug_type {
159 AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02, 159 AVC_BRIDGECO_PLUG_TYPE_MIDI = 0x02,
160 AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03, 160 AVC_BRIDGECO_PLUG_TYPE_SYNC = 0x03,
161 AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04, 161 AVC_BRIDGECO_PLUG_TYPE_ANA = 0x04,
162 AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05 162 AVC_BRIDGECO_PLUG_TYPE_DIG = 0x05,
163 AVC_BRIDGECO_PLUG_TYPE_ADDITION = 0x06
163}; 164};
164static inline void 165static inline void
165avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES], 166avc_bridgeco_fill_unit_addr(u8 buf[AVC_BRIDGECO_ADDR_BYTES],
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index 98e4fc8121a1..2ccef4ce050d 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -122,6 +122,7 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
122 struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock; 122 struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock;
123 u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7]; 123 u8 addr[AVC_BRIDGECO_ADDR_BYTES], input[7];
124 unsigned int id; 124 unsigned int id;
125 enum avc_bridgeco_plug_type type;
125 int err = 0; 126 int err = 0;
126 127
127 *internal = false; 128 *internal = false;
@@ -182,14 +183,75 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
182 goto end; 183 goto end;
183 } 184 }
184 185
185 /* 186 /* The source from any output plugs is for one purpose only. */
186 * If source of clock is internal CSR, Music Sub Unit Sync Input is 187 if (input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) {
187 * a destination of Music Sub Unit Sync Output. 188 /*
188 */ 189 * In BeBoB architecture, the source from music subunit may
189 *internal = ((input[0] == AVC_BRIDGECO_PLUG_DIR_OUT) && 190 * bypass from oPCR[0]. This means that this source gives
190 (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT) && 191 * synchronization to IEEE 1394 cycle start packet.
191 (input[2] == 0x0c) && 192 */
192 (input[3] == 0x00)); 193 if (input[1] == AVC_BRIDGECO_PLUG_MODE_SUBUNIT &&
194 input[2] == 0x0c) {
195 *internal = true;
196 goto end;
197 }
198 /* The source from any input units is for several purposes. */
199 } else if (input[1] == AVC_BRIDGECO_PLUG_MODE_UNIT) {
200 if (input[2] == AVC_BRIDGECO_PLUG_UNIT_ISOC) {
201 if (input[3] == 0x00) {
202 /*
203 * This source comes from iPCR[0]. This means
204 * that presentation timestamp calculated by
205 * SYT series of the received packets. In
206 * short, this driver is the master of
207 * synchronization.
208 */
209 err = -EIO;
210 goto end;
211 } else {
212 /*
213 * This source comes from iPCR[1-29]. This
214 * means that the synchronization stream is not
215 * the Audio/MIDI compound stream.
216 */
217 *internal = false;
218 goto end;
219 }
220 } else if (input[2] == AVC_BRIDGECO_PLUG_UNIT_EXT) {
221 /* Check type of this plug. */
222 avc_bridgeco_fill_unit_addr(addr,
223 AVC_BRIDGECO_PLUG_DIR_IN,
224 AVC_BRIDGECO_PLUG_UNIT_EXT,
225 input[3]);
226 err = avc_bridgeco_get_plug_type(bebob->unit, addr,
227 &type);
228 if (err < 0)
229 goto end;
230
231 if (type == AVC_BRIDGECO_PLUG_TYPE_DIG) {
232 /*
233 * SPDIF/ADAT or sometimes (not always) word
234 * clock.
235 */
236 *internal = false;
237 goto end;
238 } else if (type == AVC_BRIDGECO_PLUG_TYPE_SYNC) {
239 /* Often word clock. */
240 *internal = false;
241 goto end;
242 } else if (type == AVC_BRIDGECO_PLUG_TYPE_ADDITION) {
243 /*
244 * Not standard.
245 * Mostly, additional internal clock.
246 */
247 *internal = true;
248 goto end;
249 }
250 }
251 }
252
253 /* Not supported. */
254 err = -EIO;
193end: 255end:
194 return err; 256 return err;
195} 257}