aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2014-12-08 10:10:35 -0500
committerTakashi Iwai <tiwai@suse.de>2014-12-10 04:44:37 -0500
commit288a8d0cb04f7715c7c302c8a40bdb227142f3a6 (patch)
tree9427dabd4ef1f858e4e7315a0ebeb1e3760dafa9 /sound
parentbf35df66f1c613b46e054ca35ceb5caddacc6fa8 (diff)
ALSA: dice: Change the way to start stream
Streaming functionality can start streams when rate is given but currently some codes are in PCM functionality. This commit changes the way to start stream and add some arrangement to make it easy to understand the way. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Acked-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/firewire/dice/dice-pcm.c75
-rw-r--r--sound/firewire/dice/dice-stream.c191
-rw-r--r--sound/firewire/dice/dice.c4
-rw-r--r--sound/firewire/dice/dice.h4
4 files changed, 143 insertions, 131 deletions
diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c
index 2e531bd30e28..b185391dc021 100644
--- a/sound/firewire/dice/dice-pcm.c
+++ b/sound/firewire/dice/dice-pcm.c
@@ -169,65 +169,11 @@ static int playback_hw_params(struct snd_pcm_substream *substream,
169 struct snd_pcm_hw_params *hw_params) 169 struct snd_pcm_hw_params *hw_params)
170{ 170{
171 struct snd_dice *dice = substream->private_data; 171 struct snd_dice *dice = substream->private_data;
172 unsigned int mode, rate, channels, i;
173 int err;
174
175 mutex_lock(&dice->mutex);
176 snd_dice_stream_stop(dice);
177 mutex_unlock(&dice->mutex);
178
179 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
180 params_buffer_bytes(hw_params));
181 if (err < 0)
182 return err;
183
184 rate = params_rate(hw_params);
185 err = snd_dice_transaction_set_rate(dice, rate);
186 if (err < 0)
187 return err;
188
189 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
190 return err;
191
192 /*
193 * At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
194 * one data block of AMDTP packet. Thus sampling transfer frequency is
195 * a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
196 * transferred on AMDTP packets at 96 kHz. Two successive samples of a
197 * channel are stored consecutively in the packet. This quirk is called
198 * as 'Dual Wire'.
199 * For this quirk, blocking mode is required and PCM buffer size should
200 * be aligned to SYT_INTERVAL.
201 */
202 channels = params_channels(hw_params);
203 if (mode > 1) {
204 if (channels > AMDTP_MAX_CHANNELS_FOR_PCM / 2) {
205 err = -ENOSYS;
206 return err;
207 }
208
209 rate /= 2;
210 channels *= 2;
211 dice->rx_stream.double_pcm_frames = true;
212 } else {
213 dice->rx_stream.double_pcm_frames = false;
214 }
215
216 amdtp_stream_set_parameters(&dice->rx_stream, rate, channels,
217 dice->rx_midi_ports[mode]);
218 if (mode > 1) {
219 channels /= 2;
220
221 for (i = 0; i < channels; i++) {
222 dice->rx_stream.pcm_positions[i] = i * 2;
223 dice->rx_stream.pcm_positions[i + channels] = i * 2 + 1;
224 }
225 }
226
227 amdtp_stream_set_pcm_format(&dice->rx_stream, 172 amdtp_stream_set_pcm_format(&dice->rx_stream,
228 params_format(hw_params)); 173 params_format(hw_params));
229 174
230 return 0; 175 return snd_pcm_lib_alloc_vmalloc_buffer(substream,
176 params_buffer_bytes(hw_params));
231} 177}
232 178
233static int playback_hw_free(struct snd_pcm_substream *substream) 179static int playback_hw_free(struct snd_pcm_substream *substream)
@@ -247,21 +193,12 @@ static int playback_prepare(struct snd_pcm_substream *substream)
247 int err; 193 int err;
248 194
249 mutex_lock(&dice->mutex); 195 mutex_lock(&dice->mutex);
250 196 err = snd_dice_stream_start(dice, substream->runtime->rate);
251 if (amdtp_streaming_error(&dice->rx_stream))
252 snd_dice_stream_stop_packets(dice);
253
254 err = snd_dice_stream_start(dice);
255 if (err < 0) {
256 mutex_unlock(&dice->mutex);
257 return err;
258 }
259
260 mutex_unlock(&dice->mutex); 197 mutex_unlock(&dice->mutex);
198 if (err >= 0)
199 amdtp_stream_pcm_prepare(&dice->rx_stream);
261 200
262 amdtp_stream_pcm_prepare(&dice->rx_stream); 201 return err;
263
264 return 0;
265} 202}
266 203
267static int playback_trigger(struct snd_pcm_substream *substream, int cmd) 204static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index 4c4c4fff6272..b9d7a4846459 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -9,6 +9,8 @@
9 9
10#include "dice.h" 10#include "dice.h"
11 11
12#define CALLBACK_TIMEOUT 200
13
12const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = { 14const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
13 /* mode 0 */ 15 /* mode 0 */
14 [0] = 32000, 16 [0] = 32000,
@@ -39,83 +41,162 @@ int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
39 return -EINVAL; 41 return -EINVAL;
40} 42}
41 43
42int snd_dice_stream_start_packets(struct snd_dice *dice) 44static void release_resources(struct snd_dice *dice)
43{ 45{
44 int err; 46 unsigned int channel;
45 47
46 if (amdtp_stream_running(&dice->rx_stream)) 48 /* Reset channel number */
47 return 0; 49 channel = cpu_to_be32((u32)-1);
48 50 snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS, &channel, 4);
49 err = amdtp_stream_start(&dice->rx_stream, dice->rx_resources.channel,
50 fw_parent_device(dice->unit)->max_speed);
51 if (err < 0)
52 return err;
53
54 err = snd_dice_transaction_set_enable(dice);
55 if (err < 0) {
56 amdtp_stream_stop(&dice->rx_stream);
57 return err;
58 }
59 51
60 return 0; 52 fw_iso_resources_free(&dice->rx_resources);
61} 53}
62 54
63int snd_dice_stream_start(struct snd_dice *dice) 55static int keep_resources(struct snd_dice *dice, unsigned int max_payload_bytes)
64{ 56{
65 __be32 channel; 57 unsigned int channel;
66 int err; 58 int err;
67 59
68 if (!dice->rx_resources.allocated) { 60 err = fw_iso_resources_allocate(&dice->rx_resources, max_payload_bytes,
69 err = fw_iso_resources_allocate(&dice->rx_resources,
70 amdtp_stream_get_max_payload(&dice->rx_stream),
71 fw_parent_device(dice->unit)->max_speed); 61 fw_parent_device(dice->unit)->max_speed);
72 if (err < 0)
73 goto error;
74
75 channel = cpu_to_be32(dice->rx_resources.channel);
76 err = snd_dice_transaction_write_tx(dice, RX_ISOCHRONOUS,
77 &channel, 4);
78 if (err < 0)
79 goto err_resources;
80 }
81
82 err = snd_dice_stream_start_packets(dice);
83 if (err < 0) 62 if (err < 0)
84 goto err_rx_channel; 63 goto end;
85
86 return 0;
87 64
88err_rx_channel: 65 /* Set channel number */
89 channel = cpu_to_be32((u32)-1); 66 channel = cpu_to_be32(dice->rx_resources.channel);
90 snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS, &channel, 4); 67 err = snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS,
91err_resources: 68 &channel, 4);
92 fw_iso_resources_free(&dice->rx_resources); 69 if (err < 0)
93error: 70 release_resources(dice);
71end:
94 return err; 72 return err;
95} 73}
96 74
97void snd_dice_stream_stop_packets(struct snd_dice *dice) 75static void stop_stream(struct snd_dice *dice)
98{ 76{
99 if (!amdtp_stream_running(&dice->rx_stream)) 77 if (!amdtp_stream_running(&dice->rx_stream))
100 return; 78 return;
101 79
102 snd_dice_transaction_clear_enable(dice); 80 amdtp_stream_pcm_abort(&dice->rx_stream);
103 amdtp_stream_stop(&dice->rx_stream); 81 amdtp_stream_stop(&dice->rx_stream);
82 release_resources(dice);
104} 83}
105 84
106void snd_dice_stream_stop(struct snd_dice *dice) 85static int start_stream(struct snd_dice *dice, unsigned int rate)
107{ 86{
108 __be32 channel; 87 unsigned int i, mode, pcm_chs, midi_ports;
88 int err;
109 89
110 snd_dice_stream_stop_packets(dice); 90 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
91 if (err < 0)
92 goto end;
111 93
112 if (!dice->rx_resources.allocated) 94 /*
113 return; 95 * At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
96 * one data block of AMDTP packet. Thus sampling transfer frequency is
97 * a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
98 * transferred on AMDTP packets at 96 kHz. Two successive samples of a
99 * channel are stored consecutively in the packet. This quirk is called
100 * as 'Dual Wire'.
101 * For this quirk, blocking mode is required and PCM buffer size should
102 * be aligned to SYT_INTERVAL.
103 */
104 pcm_chs = dice->rx_channels[mode];
105 midi_ports = dice->rx_midi_ports[mode];
106 if (mode > 1) {
107 rate /= 2;
108 pcm_chs *= 2;
109 dice->rx_stream.double_pcm_frames = true;
110 } else {
111 dice->rx_stream.double_pcm_frames = false;
112 }
114 113
115 channel = cpu_to_be32((u32)-1); 114 amdtp_stream_set_parameters(&dice->rx_stream, rate,
116 snd_dice_transaction_write_rx(dice, RX_ISOCHRONOUS, &channel, 4); 115 pcm_chs, midi_ports);
116 if (mode > 1) {
117 pcm_chs /= 2;
117 118
118 fw_iso_resources_free(&dice->rx_resources); 119 for (i = 0; i < pcm_chs; i++) {
120 dice->rx_stream.pcm_positions[i] = i * 2;
121 dice->rx_stream.pcm_positions[i + pcm_chs] = i * 2 + 1;
122 }
123 }
124
125 err = keep_resources(dice,
126 amdtp_stream_get_max_payload(&dice->rx_stream));
127 if (err < 0) {
128 dev_err(&dice->unit->device,
129 "fail to keep isochronous resources\n");
130 goto end;
131 }
132
133 err = amdtp_stream_start(&dice->rx_stream, dice->rx_resources.channel,
134 fw_parent_device(dice->unit)->max_speed);
135 if (err < 0)
136 release_resources(dice);
137end:
138 return err;
139}
140
141int snd_dice_stream_start(struct snd_dice *dice, unsigned int rate)
142{
143 unsigned int curr_rate;
144 int err;
145
146 /* Some packet queueing errors. */
147 if (amdtp_streaming_error(&dice->rx_stream))
148 stop_stream(dice);
149
150 /* Stop stream if rate is different. */
151 err = snd_dice_transaction_get_rate(dice, &curr_rate);
152 if (err < 0) {
153 dev_err(&dice->unit->device,
154 "fail to get sampling rate\n");
155 goto end;
156 }
157 if (rate != curr_rate)
158 stop_stream(dice);
159
160 if (!amdtp_stream_running(&dice->rx_stream)) {
161 snd_dice_transaction_clear_enable(dice);
162
163 err = snd_dice_transaction_set_rate(dice, rate);
164 if (err < 0) {
165 dev_err(&dice->unit->device,
166 "fail to set sampling rate\n");
167 goto end;
168 }
169
170 /* Start stream. */
171 err = start_stream(dice, rate);
172 if (err < 0) {
173 dev_err(&dice->unit->device,
174 "fail to start AMDTP stream\n");
175 goto end;
176 }
177 err = snd_dice_transaction_set_enable(dice);
178 if (err < 0) {
179 dev_err(&dice->unit->device,
180 "fail to enable interface\n");
181 stop_stream(dice);
182 goto end;
183 }
184
185 if (!amdtp_stream_wait_callback(&dice->rx_stream,
186 CALLBACK_TIMEOUT)) {
187 snd_dice_transaction_clear_enable(dice);
188 stop_stream(dice);
189 err = -ETIMEDOUT;
190 }
191 }
192end:
193 return err;
194}
195
196void snd_dice_stream_stop(struct snd_dice *dice)
197{
198 snd_dice_transaction_clear_enable(dice);
199 stop_stream(dice);
119} 200}
120 201
121int snd_dice_stream_init(struct snd_dice *dice) 202int snd_dice_stream_init(struct snd_dice *dice)
@@ -145,8 +226,8 @@ error:
145 226
146void snd_dice_stream_destroy(struct snd_dice *dice) 227void snd_dice_stream_destroy(struct snd_dice *dice)
147{ 228{
148 amdtp_stream_pcm_abort(&dice->rx_stream); 229 snd_dice_transaction_clear_enable(dice);
149 snd_dice_stream_stop(dice); 230 stop_stream(dice);
150 amdtp_stream_destroy(&dice->rx_stream); 231 amdtp_stream_destroy(&dice->rx_stream);
151 fw_iso_resources_destroy(&dice->rx_resources); 232 fw_iso_resources_destroy(&dice->rx_resources);
152} 233}
@@ -163,8 +244,8 @@ void snd_dice_stream_update(struct snd_dice *dice)
163 */ 244 */
164 dice->global_enabled = false; 245 dice->global_enabled = false;
165 246
166 amdtp_stream_pcm_abort(&dice->rx_stream); 247 stop_stream(dice);
167 snd_dice_stream_stop_packets(dice); 248
168 fw_iso_resources_update(&dice->rx_resources); 249 fw_iso_resources_update(&dice->rx_resources);
169} 250}
170 251
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index 8e2c172de8a7..03a7988871b6 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -304,12 +304,8 @@ static void dice_remove(struct fw_unit *unit)
304 304
305 snd_card_disconnect(dice->card); 305 snd_card_disconnect(dice->card);
306 306
307 mutex_lock(&dice->mutex);
308
309 snd_dice_stream_destroy(dice); 307 snd_dice_stream_destroy(dice);
310 308
311 mutex_unlock(&dice->mutex);
312
313 snd_card_free_when_closed(dice->card); 309 snd_card_free_when_closed(dice->card);
314} 310}
315 311
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h
index 969189a6604f..8be530fe1c34 100644
--- a/sound/firewire/dice/dice.h
+++ b/sound/firewire/dice/dice.h
@@ -160,9 +160,7 @@ extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT];
160int snd_dice_stream_get_rate_mode(struct snd_dice *dice, 160int snd_dice_stream_get_rate_mode(struct snd_dice *dice,
161 unsigned int rate, unsigned int *mode); 161 unsigned int rate, unsigned int *mode);
162 162
163int snd_dice_stream_start_packets(struct snd_dice *dice); 163int snd_dice_stream_start(struct snd_dice *dice, unsigned int rate);
164int snd_dice_stream_start(struct snd_dice *dice);
165void snd_dice_stream_stop_packets(struct snd_dice *dice);
166void snd_dice_stream_stop(struct snd_dice *dice); 164void snd_dice_stream_stop(struct snd_dice *dice);
167int snd_dice_stream_init(struct snd_dice *dice); 165int snd_dice_stream_init(struct snd_dice *dice);
168void snd_dice_stream_destroy(struct snd_dice *dice); 166void snd_dice_stream_destroy(struct snd_dice *dice);