aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/amdtp.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2011-09-04 16:12:48 -0400
committerClemens Ladisch <clemens@ladisch.de>2013-10-20 16:07:57 -0400
commite84d15f619c13e83b33023c84527ee35ef01b6b4 (patch)
treea5d06e046895ebc5a14d06c93fdd4f39eb7c840a /sound/firewire/amdtp.c
parentd13109673ac49cd4b992df17238ee030be7ed7f0 (diff)
ALSA: dice, firewire-lib: add blocking mode
Allow AMDTP output streams to use blocking mode. Use it for DICE devices, because the old DICE-II chip will in some cases not be able to lock to non-blocking streams (erratum E7). Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound/firewire/amdtp.c')
-rw-r--r--sound/firewire/amdtp.c54
1 files changed, 29 insertions, 25 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index ea995af6d049..efb2e2947ce7 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -42,9 +42,6 @@ static void pcm_period_tasklet(unsigned long data);
42int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, 42int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
43 enum cip_out_flags flags) 43 enum cip_out_flags flags)
44{ 44{
45 if (flags != CIP_NONBLOCKING)
46 return -EINVAL;
47
48 s->unit = fw_unit_get(unit); 45 s->unit = fw_unit_get(unit);
49 s->flags = flags; 46 s->flags = flags;
50 s->context = ERR_PTR(-1); 47 s->context = ERR_PTR(-1);
@@ -96,12 +93,20 @@ void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate)
96 return; 93 return;
97 94
98 for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc) 95 for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc)
99 if (rate_info[sfc].rate == rate) { 96 if (rate_info[sfc].rate == rate)
100 s->sfc = sfc; 97 goto sfc_found;
101 s->syt_interval = rate_info[sfc].syt_interval;
102 return;
103 }
104 WARN_ON(1); 98 WARN_ON(1);
99 return;
100
101sfc_found:
102 s->sfc = sfc;
103 s->syt_interval = rate_info[sfc].syt_interval;
104
105 /* default buffering in the device */
106 s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
107 if (s->flags & CIP_BLOCKING)
108 /* additional buffering needed to adjust for no-data packets */
109 s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate;
105} 110}
106EXPORT_SYMBOL(amdtp_out_stream_set_rate); 111EXPORT_SYMBOL(amdtp_out_stream_set_rate);
107 112
@@ -110,25 +115,15 @@ EXPORT_SYMBOL(amdtp_out_stream_set_rate);
110 * @s: the AMDTP output stream 115 * @s: the AMDTP output stream
111 * 116 *
112 * This function must not be called before the stream has been configured 117 * This function must not be called before the stream has been configured
113 * with amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and 118 * with amdtp_out_stream_set_rate(), amdtp_out_stream_set_pcm(), and
114 * amdtp_out_stream_set_midi(). 119 * amdtp_out_stream_set_midi().
115 */ 120 */
116unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s) 121unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s)
117{ 122{
118 static const unsigned int max_data_blocks[] = {
119 [CIP_SFC_32000] = 4,
120 [CIP_SFC_44100] = 6,
121 [CIP_SFC_48000] = 6,
122 [CIP_SFC_88200] = 12,
123 [CIP_SFC_96000] = 12,
124 [CIP_SFC_176400] = 23,
125 [CIP_SFC_192000] = 24,
126 };
127
128 s->data_block_quadlets = s->pcm_channels; 123 s->data_block_quadlets = s->pcm_channels;
129 s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8); 124 s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8);
130 125
131 return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets; 126 return 8 + s->syt_interval * s->data_block_quadlets * 4;
132} 127}
133EXPORT_SYMBOL(amdtp_out_stream_get_max_payload); 128EXPORT_SYMBOL(amdtp_out_stream_get_max_payload);
134 129
@@ -248,7 +243,7 @@ static unsigned int calculate_syt(struct amdtp_out_stream *s,
248 s->last_syt_offset = syt_offset; 243 s->last_syt_offset = syt_offset;
249 244
250 if (syt_offset < TICKS_PER_CYCLE) { 245 if (syt_offset < TICKS_PER_CYCLE) {
251 syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; 246 syt_offset += s->transfer_delay;
252 syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; 247 syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
253 syt += syt_offset % TICKS_PER_CYCLE; 248 syt += syt_offset % TICKS_PER_CYCLE;
254 249
@@ -344,8 +339,17 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
344 return; 339 return;
345 index = s->packet_index; 340 index = s->packet_index;
346 341
347 data_blocks = calculate_data_blocks(s);
348 syt = calculate_syt(s, cycle); 342 syt = calculate_syt(s, cycle);
343 if (!(s->flags & CIP_BLOCKING)) {
344 data_blocks = calculate_data_blocks(s);
345 } else {
346 if (syt != 0xffff) {
347 data_blocks = s->syt_interval;
348 } else {
349 data_blocks = 0;
350 syt = 0xffffff;
351 }
352 }
349 353
350 buffer = s->buffer.packets[index].buffer; 354 buffer = s->buffer.packets[index].buffer;
351 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | 355 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
@@ -455,9 +459,9 @@ static int queue_initial_skip_packets(struct amdtp_out_stream *s)
455 * @speed: firewire speed code 459 * @speed: firewire speed code
456 * 460 *
457 * The stream cannot be started until it has been configured with 461 * The stream cannot be started until it has been configured with
458 * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and 462 * amdtp_out_stream_set_rate(), amdtp_out_stream_set_pcm(),
459 * amdtp_out_stream_set_midi(); and it must be started before any 463 * amdtp_out_stream_set_midi(), and amdtp_out_stream_set_format();
460 * PCM or MIDI device can be started. 464 * and it must be started before any PCM or MIDI device can be started.
461 */ 465 */
462int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed) 466int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
463{ 467{