2 * tascam-pcm.c - a part of driver for TASCAM FireWire series
4 * Copyright (c) 2015 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
11 static void set_buffer_params(struct snd_pcm_hardware *hw)
13 hw->period_bytes_min = 4 * hw->channels_min;
14 hw->period_bytes_max = hw->period_bytes_min * 2048;
15 hw->buffer_bytes_max = hw->period_bytes_max * 2;
18 hw->periods_max = UINT_MAX;
21 static int pcm_init_hw_params(struct snd_tscm *tscm,
22 struct snd_pcm_substream *substream)
24 static const struct snd_pcm_hardware hardware = {
25 .info = SNDRV_PCM_INFO_BATCH |
26 SNDRV_PCM_INFO_BLOCK_TRANSFER |
27 SNDRV_PCM_INFO_INTERLEAVED |
28 SNDRV_PCM_INFO_JOINT_DUPLEX |
30 SNDRV_PCM_INFO_MMAP_VALID,
31 .rates = SNDRV_PCM_RATE_44100 |
32 SNDRV_PCM_RATE_48000 |
33 SNDRV_PCM_RATE_88200 |
40 struct snd_pcm_runtime *runtime = substream->runtime;
41 struct amdtp_stream *stream;
42 unsigned int pcm_channels;
44 runtime->hw = hardware;
46 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
47 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
48 stream = &tscm->tx_stream;
49 pcm_channels = tscm->spec->pcm_capture_analog_channels;
52 SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32;
53 stream = &tscm->rx_stream;
54 pcm_channels = tscm->spec->pcm_playback_analog_channels;
57 if (tscm->spec->has_adat)
59 if (tscm->spec->has_spdif)
61 runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels;
63 set_buffer_params(&runtime->hw);
65 return amdtp_tscm_add_pcm_hw_constraints(stream, runtime);
68 static int pcm_open(struct snd_pcm_substream *substream)
70 struct snd_tscm *tscm = substream->private_data;
71 enum snd_tscm_clock clock;
75 err = snd_tscm_stream_lock_try(tscm);
79 err = pcm_init_hw_params(tscm, substream);
83 err = snd_tscm_stream_get_clock(tscm, &clock);
87 if (clock != SND_TSCM_CLOCK_INTERNAL ||
88 amdtp_stream_pcm_running(&tscm->rx_stream) ||
89 amdtp_stream_pcm_running(&tscm->tx_stream)) {
90 err = snd_tscm_stream_get_rate(tscm, &rate);
93 substream->runtime->hw.rate_min = rate;
94 substream->runtime->hw.rate_max = rate;
97 snd_pcm_set_sync(substream);
101 snd_tscm_stream_lock_release(tscm);
105 static int pcm_close(struct snd_pcm_substream *substream)
107 struct snd_tscm *tscm = substream->private_data;
109 snd_tscm_stream_lock_release(tscm);
114 static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
115 struct snd_pcm_hw_params *hw_params)
117 struct snd_tscm *tscm = substream->private_data;
120 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
121 params_buffer_bytes(hw_params));
125 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
126 mutex_lock(&tscm->mutex);
127 tscm->substreams_counter++;
128 mutex_unlock(&tscm->mutex);
131 amdtp_tscm_set_pcm_format(&tscm->tx_stream, params_format(hw_params));
136 static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
137 struct snd_pcm_hw_params *hw_params)
139 struct snd_tscm *tscm = substream->private_data;
142 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
143 params_buffer_bytes(hw_params));
147 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
148 mutex_lock(&tscm->mutex);
149 tscm->substreams_counter++;
150 mutex_unlock(&tscm->mutex);
153 amdtp_tscm_set_pcm_format(&tscm->rx_stream, params_format(hw_params));
158 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
160 struct snd_tscm *tscm = substream->private_data;
162 mutex_lock(&tscm->mutex);
164 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
165 tscm->substreams_counter--;
167 snd_tscm_stream_stop_duplex(tscm);
169 mutex_unlock(&tscm->mutex);
171 return snd_pcm_lib_free_vmalloc_buffer(substream);
174 static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
176 struct snd_tscm *tscm = substream->private_data;
178 mutex_lock(&tscm->mutex);
180 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
181 tscm->substreams_counter--;
183 snd_tscm_stream_stop_duplex(tscm);
185 mutex_unlock(&tscm->mutex);
187 return snd_pcm_lib_free_vmalloc_buffer(substream);
190 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
192 struct snd_tscm *tscm = substream->private_data;
193 struct snd_pcm_runtime *runtime = substream->runtime;
196 mutex_lock(&tscm->mutex);
198 err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
200 amdtp_stream_pcm_prepare(&tscm->tx_stream);
202 mutex_unlock(&tscm->mutex);
207 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
209 struct snd_tscm *tscm = substream->private_data;
210 struct snd_pcm_runtime *runtime = substream->runtime;
213 mutex_lock(&tscm->mutex);
215 err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
217 amdtp_stream_pcm_prepare(&tscm->rx_stream);
219 mutex_unlock(&tscm->mutex);
224 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
226 struct snd_tscm *tscm = substream->private_data;
229 case SNDRV_PCM_TRIGGER_START:
230 amdtp_stream_pcm_trigger(&tscm->tx_stream, substream);
232 case SNDRV_PCM_TRIGGER_STOP:
233 amdtp_stream_pcm_trigger(&tscm->tx_stream, NULL);
242 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
244 struct snd_tscm *tscm = substream->private_data;
247 case SNDRV_PCM_TRIGGER_START:
248 amdtp_stream_pcm_trigger(&tscm->rx_stream, substream);
250 case SNDRV_PCM_TRIGGER_STOP:
251 amdtp_stream_pcm_trigger(&tscm->rx_stream, NULL);
260 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
262 struct snd_tscm *tscm = sbstrm->private_data;
264 return amdtp_stream_pcm_pointer(&tscm->tx_stream);
267 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
269 struct snd_tscm *tscm = sbstrm->private_data;
271 return amdtp_stream_pcm_pointer(&tscm->rx_stream);
274 static struct snd_pcm_ops pcm_capture_ops = {
277 .ioctl = snd_pcm_lib_ioctl,
278 .hw_params = pcm_capture_hw_params,
279 .hw_free = pcm_capture_hw_free,
280 .prepare = pcm_capture_prepare,
281 .trigger = pcm_capture_trigger,
282 .pointer = pcm_capture_pointer,
283 .page = snd_pcm_lib_get_vmalloc_page,
286 static struct snd_pcm_ops pcm_playback_ops = {
289 .ioctl = snd_pcm_lib_ioctl,
290 .hw_params = pcm_playback_hw_params,
291 .hw_free = pcm_playback_hw_free,
292 .prepare = pcm_playback_prepare,
293 .trigger = pcm_playback_trigger,
294 .pointer = pcm_playback_pointer,
295 .page = snd_pcm_lib_get_vmalloc_page,
296 .mmap = snd_pcm_lib_mmap_vmalloc,
299 int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
304 err = snd_pcm_new(tscm->card, tscm->card->driver, 0, 1, 1, &pcm);
308 pcm->private_data = tscm;
309 snprintf(pcm->name, sizeof(pcm->name),
310 "%s PCM", tscm->card->shortname);
311 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
312 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);