aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/dice/dice-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/dice/dice-pcm.c')
-rw-r--r--sound/firewire/dice/dice-pcm.c75
1 files changed, 6 insertions, 69 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)