aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/amdtp.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-10-22 04:02:57 -0400
committerTakashi Iwai <tiwai@suse.de>2013-10-22 04:02:57 -0400
commit861e66d3418a90f57b31a50110fc70b23569c551 (patch)
treeffa0d5bf8dc3e4b82b88d8942390a11d827423f9 /sound/firewire/amdtp.c
parentb55447a7301b12d509df4b2909ed38d125ad83d4 (diff)
parentb20be8de1b3972ccf9af72850b045214faa8d830 (diff)
Merge branch 'dice-driver-playback-only' of git://git.alsa-project.org/alsa-kprivate into for-next
Diffstat (limited to 'sound/firewire/amdtp.c')
-rw-r--r--sound/firewire/amdtp.c209
1 files changed, 155 insertions, 54 deletions
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 4b08b25a4db8..d3226892ad6b 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);
@@ -62,73 +59,91 @@ EXPORT_SYMBOL(amdtp_out_stream_init);
62 */ 59 */
63void amdtp_out_stream_destroy(struct amdtp_out_stream *s) 60void amdtp_out_stream_destroy(struct amdtp_out_stream *s)
64{ 61{
65 WARN_ON(!IS_ERR(s->context)); 62 WARN_ON(amdtp_out_stream_running(s));
66 mutex_destroy(&s->mutex); 63 mutex_destroy(&s->mutex);
67 fw_unit_put(s->unit); 64 fw_unit_put(s->unit);
68} 65}
69EXPORT_SYMBOL(amdtp_out_stream_destroy); 66EXPORT_SYMBOL(amdtp_out_stream_destroy);
70 67
68const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = {
69 [CIP_SFC_32000] = 8,
70 [CIP_SFC_44100] = 8,
71 [CIP_SFC_48000] = 8,
72 [CIP_SFC_88200] = 16,
73 [CIP_SFC_96000] = 16,
74 [CIP_SFC_176400] = 32,
75 [CIP_SFC_192000] = 32,
76};
77EXPORT_SYMBOL(amdtp_syt_intervals);
78
71/** 79/**
72 * amdtp_out_stream_set_rate - set the sample rate 80 * amdtp_out_stream_set_parameters - set stream parameters
73 * @s: the AMDTP output stream to configure 81 * @s: the AMDTP output stream to configure
74 * @rate: the sample rate 82 * @rate: the sample rate
83 * @pcm_channels: the number of PCM samples in each data block, to be encoded
84 * as AM824 multi-bit linear audio
85 * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
75 * 86 *
76 * The sample rate must be set before the stream is started, and must not be 87 * The parameters must be set before the stream is started, and must not be
77 * changed while the stream is running. 88 * changed while the stream is running.
78 */ 89 */
79void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate) 90void amdtp_out_stream_set_parameters(struct amdtp_out_stream *s,
91 unsigned int rate,
92 unsigned int pcm_channels,
93 unsigned int midi_ports)
80{ 94{
81 static const struct { 95 static const unsigned int rates[] = {
82 unsigned int rate; 96 [CIP_SFC_32000] = 32000,
83 unsigned int syt_interval; 97 [CIP_SFC_44100] = 44100,
84 } rate_info[] = { 98 [CIP_SFC_48000] = 48000,
85 [CIP_SFC_32000] = { 32000, 8, }, 99 [CIP_SFC_88200] = 88200,
86 [CIP_SFC_44100] = { 44100, 8, }, 100 [CIP_SFC_96000] = 96000,
87 [CIP_SFC_48000] = { 48000, 8, }, 101 [CIP_SFC_176400] = 176400,
88 [CIP_SFC_88200] = { 88200, 16, }, 102 [CIP_SFC_192000] = 192000,
89 [CIP_SFC_96000] = { 96000, 16, },
90 [CIP_SFC_176400] = { 176400, 32, },
91 [CIP_SFC_192000] = { 192000, 32, },
92 }; 103 };
93 unsigned int sfc; 104 unsigned int sfc;
94 105
95 if (WARN_ON(!IS_ERR(s->context))) 106 if (WARN_ON(amdtp_out_stream_running(s)))
96 return; 107 return;
97 108
98 for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc) 109 for (sfc = 0; sfc < CIP_SFC_COUNT; ++sfc)
99 if (rate_info[sfc].rate == rate) { 110 if (rates[sfc] == rate)
100 s->sfc = sfc; 111 goto sfc_found;
101 s->syt_interval = rate_info[sfc].syt_interval;
102 return;
103 }
104 WARN_ON(1); 112 WARN_ON(1);
113 return;
114
115sfc_found:
116 s->dual_wire = (s->flags & CIP_HI_DUALWIRE) && sfc > CIP_SFC_96000;
117 if (s->dual_wire) {
118 sfc -= 2;
119 rate /= 2;
120 pcm_channels *= 2;
121 }
122 s->sfc = sfc;
123 s->data_block_quadlets = pcm_channels + DIV_ROUND_UP(midi_ports, 8);
124 s->pcm_channels = pcm_channels;
125 s->midi_ports = midi_ports;
126
127 s->syt_interval = amdtp_syt_intervals[sfc];
128
129 /* default buffering in the device */
130 s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
131 if (s->flags & CIP_BLOCKING)
132 /* additional buffering needed to adjust for no-data packets */
133 s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate;
105} 134}
106EXPORT_SYMBOL(amdtp_out_stream_set_rate); 135EXPORT_SYMBOL(amdtp_out_stream_set_parameters);
107 136
108/** 137/**
109 * amdtp_out_stream_get_max_payload - get the stream's packet size 138 * amdtp_out_stream_get_max_payload - get the stream's packet size
110 * @s: the AMDTP output stream 139 * @s: the AMDTP output stream
111 * 140 *
112 * This function must not be called before the stream has been configured 141 * 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 142 * with amdtp_out_stream_set_parameters().
114 * amdtp_out_stream_set_midi().
115 */ 143 */
116unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s) 144unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s)
117{ 145{
118 static const unsigned int max_data_blocks[] = { 146 return 8 + s->syt_interval * s->data_block_quadlets * 4;
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;
129 s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8);
130
131 return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets;
132} 147}
133EXPORT_SYMBOL(amdtp_out_stream_get_max_payload); 148EXPORT_SYMBOL(amdtp_out_stream_get_max_payload);
134 149
@@ -138,19 +153,26 @@ static void amdtp_write_s16(struct amdtp_out_stream *s,
138static void amdtp_write_s32(struct amdtp_out_stream *s, 153static void amdtp_write_s32(struct amdtp_out_stream *s,
139 struct snd_pcm_substream *pcm, 154 struct snd_pcm_substream *pcm,
140 __be32 *buffer, unsigned int frames); 155 __be32 *buffer, unsigned int frames);
156static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s,
157 struct snd_pcm_substream *pcm,
158 __be32 *buffer, unsigned int frames);
159static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s,
160 struct snd_pcm_substream *pcm,
161 __be32 *buffer, unsigned int frames);
141 162
142/** 163/**
143 * amdtp_out_stream_set_pcm_format - set the PCM format 164 * amdtp_out_stream_set_pcm_format - set the PCM format
144 * @s: the AMDTP output stream to configure 165 * @s: the AMDTP output stream to configure
145 * @format: the format of the ALSA PCM device 166 * @format: the format of the ALSA PCM device
146 * 167 *
147 * The sample format must be set before the stream is started, and must not be 168 * The sample format must be set after the other paramters (rate/PCM channels/
148 * changed while the stream is running. 169 * MIDI) and before the stream is started, and must not be changed while the
170 * stream is running.
149 */ 171 */
150void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, 172void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
151 snd_pcm_format_t format) 173 snd_pcm_format_t format)
152{ 174{
153 if (WARN_ON(!IS_ERR(s->context))) 175 if (WARN_ON(amdtp_out_stream_running(s)))
154 return; 176 return;
155 177
156 switch (format) { 178 switch (format) {
@@ -158,10 +180,16 @@ void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
158 WARN_ON(1); 180 WARN_ON(1);
159 /* fall through */ 181 /* fall through */
160 case SNDRV_PCM_FORMAT_S16: 182 case SNDRV_PCM_FORMAT_S16:
161 s->transfer_samples = amdtp_write_s16; 183 if (s->dual_wire)
184 s->transfer_samples = amdtp_write_s16_dualwire;
185 else
186 s->transfer_samples = amdtp_write_s16;
162 break; 187 break;
163 case SNDRV_PCM_FORMAT_S32: 188 case SNDRV_PCM_FORMAT_S32:
164 s->transfer_samples = amdtp_write_s32; 189 if (s->dual_wire)
190 s->transfer_samples = amdtp_write_s32_dualwire;
191 else
192 s->transfer_samples = amdtp_write_s32;
165 break; 193 break;
166 } 194 }
167} 195}
@@ -248,7 +276,7 @@ static unsigned int calculate_syt(struct amdtp_out_stream *s,
248 s->last_syt_offset = syt_offset; 276 s->last_syt_offset = syt_offset;
249 277
250 if (syt_offset < TICKS_PER_CYCLE) { 278 if (syt_offset < TICKS_PER_CYCLE) {
251 syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; 279 syt_offset += s->transfer_delay;
252 syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; 280 syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
253 syt += syt_offset % TICKS_PER_CYCLE; 281 syt += syt_offset % TICKS_PER_CYCLE;
254 282
@@ -310,6 +338,68 @@ static void amdtp_write_s16(struct amdtp_out_stream *s,
310 } 338 }
311} 339}
312 340
341static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s,
342 struct snd_pcm_substream *pcm,
343 __be32 *buffer, unsigned int frames)
344{
345 struct snd_pcm_runtime *runtime = pcm->runtime;
346 unsigned int channels, frame_adjust_1, frame_adjust_2, i, c;
347 const u32 *src;
348
349 channels = s->pcm_channels;
350 src = (void *)runtime->dma_area +
351 s->pcm_buffer_pointer * (runtime->frame_bits / 8);
352 frame_adjust_1 = channels - 1;
353 frame_adjust_2 = 1 - (s->data_block_quadlets - channels);
354
355 channels /= 2;
356 for (i = 0; i < frames; ++i) {
357 for (c = 0; c < channels; ++c) {
358 *buffer = cpu_to_be32((*src >> 8) | 0x40000000);
359 src++;
360 buffer += 2;
361 }
362 buffer -= frame_adjust_1;
363 for (c = 0; c < channels; ++c) {
364 *buffer = cpu_to_be32((*src >> 8) | 0x40000000);
365 src++;
366 buffer += 2;
367 }
368 buffer -= frame_adjust_2;
369 }
370}
371
372static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s,
373 struct snd_pcm_substream *pcm,
374 __be32 *buffer, unsigned int frames)
375{
376 struct snd_pcm_runtime *runtime = pcm->runtime;
377 unsigned int channels, frame_adjust_1, frame_adjust_2, i, c;
378 const u16 *src;
379
380 channels = s->pcm_channels;
381 src = (void *)runtime->dma_area +
382 s->pcm_buffer_pointer * (runtime->frame_bits / 8);
383 frame_adjust_1 = channels - 1;
384 frame_adjust_2 = 1 - (s->data_block_quadlets - channels);
385
386 channels /= 2;
387 for (i = 0; i < frames; ++i) {
388 for (c = 0; c < channels; ++c) {
389 *buffer = cpu_to_be32((*src << 8) | 0x40000000);
390 src++;
391 buffer += 2;
392 }
393 buffer -= frame_adjust_1;
394 for (c = 0; c < channels; ++c) {
395 *buffer = cpu_to_be32((*src << 8) | 0x40000000);
396 src++;
397 buffer += 2;
398 }
399 buffer -= frame_adjust_2;
400 }
401}
402
313static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s, 403static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s,
314 __be32 *buffer, unsigned int frames) 404 __be32 *buffer, unsigned int frames)
315{ 405{
@@ -344,8 +434,17 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
344 return; 434 return;
345 index = s->packet_index; 435 index = s->packet_index;
346 436
347 data_blocks = calculate_data_blocks(s);
348 syt = calculate_syt(s, cycle); 437 syt = calculate_syt(s, cycle);
438 if (!(s->flags & CIP_BLOCKING)) {
439 data_blocks = calculate_data_blocks(s);
440 } else {
441 if (syt != 0xffff) {
442 data_blocks = s->syt_interval;
443 } else {
444 data_blocks = 0;
445 syt = 0xffffff;
446 }
447 }
349 448
350 buffer = s->buffer.packets[index].buffer; 449 buffer = s->buffer.packets[index].buffer;
351 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | 450 buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
@@ -386,6 +485,9 @@ static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
386 s->packet_index = index; 485 s->packet_index = index;
387 486
388 if (pcm) { 487 if (pcm) {
488 if (s->dual_wire)
489 data_blocks *= 2;
490
389 ptr = s->pcm_buffer_pointer + data_blocks; 491 ptr = s->pcm_buffer_pointer + data_blocks;
390 if (ptr >= pcm->runtime->buffer_size) 492 if (ptr >= pcm->runtime->buffer_size)
391 ptr -= pcm->runtime->buffer_size; 493 ptr -= pcm->runtime->buffer_size;
@@ -455,9 +557,8 @@ static int queue_initial_skip_packets(struct amdtp_out_stream *s)
455 * @speed: firewire speed code 557 * @speed: firewire speed code
456 * 558 *
457 * The stream cannot be started until it has been configured with 559 * The stream cannot be started until it has been configured with
458 * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and 560 * amdtp_out_stream_set_parameters() and amdtp_out_stream_set_pcm_format(),
459 * amdtp_out_stream_set_midi(); and it must be started before any 561 * and it must be started before any PCM or MIDI device can be started.
460 * PCM or MIDI device can be started.
461 */ 562 */
462int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed) 563int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
463{ 564{
@@ -477,7 +578,7 @@ int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
477 578
478 mutex_lock(&s->mutex); 579 mutex_lock(&s->mutex);
479 580
480 if (WARN_ON(!IS_ERR(s->context) || 581 if (WARN_ON(amdtp_out_stream_running(s) ||
481 (!s->pcm_channels && !s->midi_ports))) { 582 (!s->pcm_channels && !s->midi_ports))) {
482 err = -EBADFD; 583 err = -EBADFD;
483 goto err_unlock; 584 goto err_unlock;
@@ -573,7 +674,7 @@ void amdtp_out_stream_stop(struct amdtp_out_stream *s)
573{ 674{
574 mutex_lock(&s->mutex); 675 mutex_lock(&s->mutex);
575 676
576 if (IS_ERR(s->context)) { 677 if (!amdtp_out_stream_running(s)) {
577 mutex_unlock(&s->mutex); 678 mutex_unlock(&s->mutex);
578 return; 679 return;
579 } 680 }