Skip to content

Commit 8ae25b7

Browse files
takaswietiwai
authored andcommitted
ALSA: dice: have two sets of isochronous resources/streams
Currently ALSA dice driver handles a pair of isochronous resources for IEC 61883-1/6 packet streaming. While, according to some documents about ASICs named as 'Dice', several isochronous streams are available. Here, I start to describe ASICs produced under 'Dice' name. * Dice II (designed by wavefront semiconductor, including TCAT's IP) * STD (with limited functionality of DTCP) * CP (with full functionality of DTCP) * TCD2210/2210-E (so-called 'Dice Mini') * TCD2220/2220-E (so-called 'Dice Jr.') * TCD3070-CH (so-called 'Dice III') Some documents are public and we can see hardware design of them. We can find some articles about hardware internal register definitions (not registers exported to IEEE 1394 bus). * DICE II User Guide * http://www.tctechnologies.tc/archive/downloads/dice_ii_user_guide.pdf * 6.1 AVS Audio Receivers * Table 6.1: AVS Audio Receiver Memory Map * ARX1-ARX4 * 6.2 AVS Audio Transmitters * Table 6.2: AVS Audio Transmitter Memory Map * ATX1, ATX2 * TCD22xx User Guide * http://www.tctechnologies.tc/downloads/tcd22xx_user_guide.pdf * 6.1 AVS Audio Receivers * Table 66: AVS Audio Receiver Memory Map * ARX1, ARX2 * 6/2 AVS Audio Transmitters * Table 67: AVS Audio Transmitter Memory Map * ATX1, ATX2 * DICE III * http://www.tctechnologies.tc/downloads/TCD3070-CH.pdf * Dual stream 63 channel transmitter/receiver For Dice II and TCD22xx series, maximum 16 data channels are transferred in an AMDTP packet, while for Dice III, maximum 32 data channels are transferred. According to the design of the series of these ASICs, this commit allows this driver to handle additional set of isochronous resources. For practical reason, two pair of isochronous resources are added. As of this commit, this driver still use a pair of the first isochronous resources. Signed-off-by: Takashi Sakamoto <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent a1ce94d commit 8ae25b7

File tree

4 files changed

+79
-48
lines changed

4 files changed

+79
-48
lines changed

sound/firewire/dice/dice-midi.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ static void midi_capture_trigger(struct snd_rawmidi_substream *substrm, int up)
5252
spin_lock_irqsave(&dice->lock, flags);
5353

5454
if (up)
55-
amdtp_am824_midi_trigger(&dice->tx_stream,
55+
amdtp_am824_midi_trigger(&dice->tx_stream[0],
5656
substrm->number, substrm);
5757
else
58-
amdtp_am824_midi_trigger(&dice->tx_stream,
58+
amdtp_am824_midi_trigger(&dice->tx_stream[0],
5959
substrm->number, NULL);
6060

6161
spin_unlock_irqrestore(&dice->lock, flags);
@@ -69,10 +69,10 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substrm, int up)
6969
spin_lock_irqsave(&dice->lock, flags);
7070

7171
if (up)
72-
amdtp_am824_midi_trigger(&dice->rx_stream,
72+
amdtp_am824_midi_trigger(&dice->rx_stream[0],
7373
substrm->number, substrm);
7474
else
75-
amdtp_am824_midi_trigger(&dice->rx_stream,
75+
amdtp_am824_midi_trigger(&dice->rx_stream[0],
7676
substrm->number, NULL);
7777

7878
spin_unlock_irqrestore(&dice->lock, flags);

sound/firewire/dice/dice-pcm.c

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ static int limit_channels_and_rates(struct snd_dice *dice,
2222
* Retrieve current Multi Bit Linear Audio data channel and limit to
2323
* it.
2424
*/
25-
if (stream == &dice->tx_stream) {
25+
if (stream == &dice->tx_stream[0]) {
2626
err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO,
2727
reg, sizeof(reg));
2828
} else {
@@ -74,10 +74,10 @@ static int init_hw_info(struct snd_dice *dice,
7474

7575
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
7676
hw->formats = AM824_IN_PCM_FORMAT_BITS;
77-
stream = &dice->tx_stream;
77+
stream = &dice->tx_stream[0];
7878
} else {
7979
hw->formats = AM824_OUT_PCM_FORMAT_BITS;
80-
stream = &dice->rx_stream;
80+
stream = &dice->rx_stream[0];
8181
}
8282

8383
err = limit_channels_and_rates(dice, runtime, stream);
@@ -122,6 +122,7 @@ static int capture_hw_params(struct snd_pcm_substream *substream,
122122
struct snd_pcm_hw_params *hw_params)
123123
{
124124
struct snd_dice *dice = substream->private_data;
125+
struct amdtp_stream *stream = &dice->tx_stream[0];
125126
int err;
126127

127128
err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
@@ -135,14 +136,15 @@ static int capture_hw_params(struct snd_pcm_substream *substream,
135136
mutex_unlock(&dice->mutex);
136137
}
137138

138-
amdtp_am824_set_pcm_format(&dice->tx_stream, params_format(hw_params));
139+
amdtp_am824_set_pcm_format(stream, params_format(hw_params));
139140

140141
return 0;
141142
}
142143
static int playback_hw_params(struct snd_pcm_substream *substream,
143144
struct snd_pcm_hw_params *hw_params)
144145
{
145146
struct snd_dice *dice = substream->private_data;
147+
struct amdtp_stream *stream = &dice->rx_stream[0];
146148
int err;
147149

148150
err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
@@ -156,7 +158,7 @@ static int playback_hw_params(struct snd_pcm_substream *substream,
156158
mutex_unlock(&dice->mutex);
157159
}
158160

159-
amdtp_am824_set_pcm_format(&dice->rx_stream, params_format(hw_params));
161+
amdtp_am824_set_pcm_format(stream, params_format(hw_params));
160162

161163
return 0;
162164
}
@@ -196,40 +198,43 @@ static int playback_hw_free(struct snd_pcm_substream *substream)
196198
static int capture_prepare(struct snd_pcm_substream *substream)
197199
{
198200
struct snd_dice *dice = substream->private_data;
201+
struct amdtp_stream *stream = &dice->tx_stream[0];
199202
int err;
200203

201204
mutex_lock(&dice->mutex);
202205
err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
203206
mutex_unlock(&dice->mutex);
204207
if (err >= 0)
205-
amdtp_stream_pcm_prepare(&dice->tx_stream);
208+
amdtp_stream_pcm_prepare(stream);
206209

207210
return 0;
208211
}
209212
static int playback_prepare(struct snd_pcm_substream *substream)
210213
{
211214
struct snd_dice *dice = substream->private_data;
215+
struct amdtp_stream *stream = &dice->rx_stream[0];
212216
int err;
213217

214218
mutex_lock(&dice->mutex);
215219
err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
216220
mutex_unlock(&dice->mutex);
217221
if (err >= 0)
218-
amdtp_stream_pcm_prepare(&dice->rx_stream);
222+
amdtp_stream_pcm_prepare(stream);
219223

220224
return err;
221225
}
222226

223227
static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
224228
{
225229
struct snd_dice *dice = substream->private_data;
230+
struct amdtp_stream *stream = &dice->tx_stream[0];
226231

227232
switch (cmd) {
228233
case SNDRV_PCM_TRIGGER_START:
229-
amdtp_stream_pcm_trigger(&dice->tx_stream, substream);
234+
amdtp_stream_pcm_trigger(stream, substream);
230235
break;
231236
case SNDRV_PCM_TRIGGER_STOP:
232-
amdtp_stream_pcm_trigger(&dice->tx_stream, NULL);
237+
amdtp_stream_pcm_trigger(stream, NULL);
233238
break;
234239
default:
235240
return -EINVAL;
@@ -240,13 +245,14 @@ static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
240245
static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
241246
{
242247
struct snd_dice *dice = substream->private_data;
248+
struct amdtp_stream *stream = &dice->rx_stream[0];
243249

244250
switch (cmd) {
245251
case SNDRV_PCM_TRIGGER_START:
246-
amdtp_stream_pcm_trigger(&dice->rx_stream, substream);
252+
amdtp_stream_pcm_trigger(stream, substream);
247253
break;
248254
case SNDRV_PCM_TRIGGER_STOP:
249-
amdtp_stream_pcm_trigger(&dice->rx_stream, NULL);
255+
amdtp_stream_pcm_trigger(stream, NULL);
250256
break;
251257
default:
252258
return -EINVAL;
@@ -258,14 +264,16 @@ static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
258264
static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
259265
{
260266
struct snd_dice *dice = substream->private_data;
267+
struct amdtp_stream *stream = &dice->tx_stream[0];
261268

262-
return amdtp_stream_pcm_pointer(&dice->tx_stream);
269+
return amdtp_stream_pcm_pointer(stream);
263270
}
264271
static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
265272
{
266273
struct snd_dice *dice = substream->private_data;
274+
struct amdtp_stream *stream = &dice->rx_stream[0];
267275

268-
return amdtp_stream_pcm_pointer(&dice->rx_stream);
276+
return amdtp_stream_pcm_pointer(stream);
269277
}
270278

271279
int snd_dice_create_pcm(struct snd_dice *dice)

sound/firewire/dice/dice-stream.c

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static void release_resources(struct snd_dice *dice,
7272

7373
/* Reset channel number */
7474
channel = cpu_to_be32((u32)-1);
75-
if (resources == &dice->tx_resources)
75+
if (resources == &dice->tx_resources[0])
7676
snd_dice_transaction_write_tx(dice, TX_ISOCHRONOUS,
7777
&channel, sizeof(channel));
7878
else
@@ -96,7 +96,7 @@ static int keep_resources(struct snd_dice *dice,
9696

9797
/* Set channel number */
9898
channel = cpu_to_be32(resources->channel);
99-
if (resources == &dice->tx_resources)
99+
if (resources == &dice->tx_resources[0])
100100
err = snd_dice_transaction_write_tx(dice, TX_ISOCHRONOUS,
101101
&channel, sizeof(channel));
102102
else
@@ -113,10 +113,10 @@ static void stop_stream(struct snd_dice *dice, struct amdtp_stream *stream)
113113
amdtp_stream_pcm_abort(stream);
114114
amdtp_stream_stop(stream);
115115

116-
if (stream == &dice->tx_stream)
117-
release_resources(dice, &dice->tx_resources);
116+
if (stream == &dice->tx_stream[0])
117+
release_resources(dice, &dice->tx_resources[0]);
118118
else
119-
release_resources(dice, &dice->rx_resources);
119+
release_resources(dice, &dice->rx_resources[0]);
120120
}
121121

122122
static int start_stream(struct snd_dice *dice, struct amdtp_stream *stream,
@@ -128,12 +128,12 @@ static int start_stream(struct snd_dice *dice, struct amdtp_stream *stream,
128128
bool double_pcm_frames;
129129
int err;
130130

131-
if (stream == &dice->tx_stream) {
132-
resources = &dice->tx_resources;
131+
if (stream == &dice->tx_stream[0]) {
132+
resources = &dice->tx_resources[0];
133133
err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO,
134134
reg, sizeof(reg));
135135
} else {
136-
resources = &dice->rx_resources;
136+
resources = &dice->rx_resources[0];
137137
err = snd_dice_transaction_read_rx(dice, RX_NUMBER_AUDIO,
138138
reg, sizeof(reg));
139139
}
@@ -200,8 +200,8 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
200200
if (dice->substreams_counter == 0)
201201
goto end;
202202

203-
master = &dice->rx_stream;
204-
slave = &dice->tx_stream;
203+
master = &dice->rx_stream[0];
204+
slave = &dice->tx_stream[0];
205205

206206
/* Some packet queueing errors. */
207207
if (amdtp_streaming_error(master) || amdtp_streaming_error(slave))
@@ -275,8 +275,8 @@ void snd_dice_stream_stop_duplex(struct snd_dice *dice)
275275

276276
snd_dice_transaction_clear_enable(dice);
277277

278-
stop_stream(dice, &dice->tx_stream);
279-
stop_stream(dice, &dice->rx_stream);
278+
stop_stream(dice, &dice->tx_stream[0]);
279+
stop_stream(dice, &dice->rx_stream[0]);
280280
}
281281

282282
static int init_stream(struct snd_dice *dice, struct amdtp_stream *stream)
@@ -285,11 +285,11 @@ static int init_stream(struct snd_dice *dice, struct amdtp_stream *stream)
285285
struct fw_iso_resources *resources;
286286
enum amdtp_stream_direction dir;
287287

288-
if (stream == &dice->tx_stream) {
289-
resources = &dice->tx_resources;
288+
if (stream == &dice->tx_stream[0]) {
289+
resources = &dice->tx_resources[0];
290290
dir = AMDTP_IN_STREAM;
291291
} else {
292-
resources = &dice->rx_resources;
292+
resources = &dice->rx_resources[0];
293293
dir = AMDTP_OUT_STREAM;
294294
}
295295

@@ -315,10 +315,10 @@ static void destroy_stream(struct snd_dice *dice, struct amdtp_stream *stream)
315315
{
316316
struct fw_iso_resources *resources;
317317

318-
if (stream == &dice->tx_stream)
319-
resources = &dice->tx_resources;
318+
if (stream == &dice->tx_stream[0])
319+
resources = &dice->tx_resources[0];
320320
else
321-
resources = &dice->rx_resources;
321+
resources = &dice->rx_resources[0];
322322

323323
amdtp_stream_destroy(stream);
324324
fw_iso_resources_destroy(resources);
@@ -330,13 +330,13 @@ int snd_dice_stream_init_duplex(struct snd_dice *dice)
330330

331331
dice->substreams_counter = 0;
332332

333-
err = init_stream(dice, &dice->tx_stream);
333+
err = init_stream(dice, &dice->tx_stream[0]);
334334
if (err < 0)
335335
goto end;
336336

337-
err = init_stream(dice, &dice->rx_stream);
337+
err = init_stream(dice, &dice->rx_stream[0]);
338338
if (err < 0)
339-
destroy_stream(dice, &dice->tx_stream);
339+
destroy_stream(dice, &dice->tx_stream[0]);
340340
end:
341341
return err;
342342
}
@@ -345,8 +345,8 @@ void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
345345
{
346346
snd_dice_transaction_clear_enable(dice);
347347

348-
destroy_stream(dice, &dice->tx_stream);
349-
destroy_stream(dice, &dice->rx_stream);
348+
destroy_stream(dice, &dice->tx_stream[0]);
349+
destroy_stream(dice, &dice->rx_stream[0]);
350350

351351
dice->substreams_counter = 0;
352352
}
@@ -363,11 +363,11 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice)
363363
*/
364364
dice->global_enabled = false;
365365

366-
stop_stream(dice, &dice->rx_stream);
367-
stop_stream(dice, &dice->tx_stream);
366+
stop_stream(dice, &dice->rx_stream[0]);
367+
stop_stream(dice, &dice->tx_stream[0]);
368368

369-
fw_iso_resources_update(&dice->rx_resources);
370-
fw_iso_resources_update(&dice->tx_resources);
369+
fw_iso_resources_update(&dice->rx_resources[0]);
370+
fw_iso_resources_update(&dice->tx_resources[0]);
371371
}
372372

373373
static void dice_lock_changed(struct snd_dice *dice)

sound/firewire/dice/dice.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,29 @@
3939
#include "../lib.h"
4040
#include "dice-interface.h"
4141

42+
/*
43+
* This module support maximum 2 pairs of tx/rx isochronous streams for
44+
* our convinience.
45+
*
46+
* In documents for ASICs called with a name of 'DICE':
47+
* - ASIC for DICE II:
48+
* - Maximum 2 tx and 4 rx are supported.
49+
* - A packet supports maximum 16 data channels.
50+
* - TCD2210/2210-E (so-called 'Dice Mini'):
51+
* - Maximum 2 tx and 2 rx are supported.
52+
* - A packet supports maximum 16 data channels.
53+
* - TCD2220/2220-E (so-called 'Dice Jr.')
54+
* - 2 tx and 2 rx are supported.
55+
* - A packet supports maximum 16 data channels.
56+
* - TCD3070-CH (so-called 'Dice III')
57+
* - Maximum 2 tx and 2 rx are supported.
58+
* - A packet supports maximum 32 data channels.
59+
*
60+
* For the above, MIDI conformant data channel is just on the first isochronous
61+
* stream.
62+
*/
63+
#define MAX_STREAMS 2
64+
4265
struct snd_dice {
4366
struct snd_card *card;
4467
struct fw_unit *unit;
@@ -67,10 +90,10 @@ struct snd_dice {
6790
wait_queue_head_t hwdep_wait;
6891

6992
/* For streaming */
70-
struct fw_iso_resources tx_resources;
71-
struct fw_iso_resources rx_resources;
72-
struct amdtp_stream tx_stream;
73-
struct amdtp_stream rx_stream;
93+
struct fw_iso_resources tx_resources[MAX_STREAMS];
94+
struct fw_iso_resources rx_resources[MAX_STREAMS];
95+
struct amdtp_stream tx_stream[MAX_STREAMS];
96+
struct amdtp_stream rx_stream[MAX_STREAMS];
7497
bool global_enabled;
7598
struct completion clock_accepted;
7699
unsigned int substreams_counter;

0 commit comments

Comments
 (0)