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
);
84 if (clock
!= SND_TSCM_CLOCK_INTERNAL
||
85 amdtp_stream_pcm_running(&tscm
->rx_stream
) ||
86 amdtp_stream_pcm_running(&tscm
->tx_stream
)) {
87 err
= snd_tscm_stream_get_rate(tscm
, &rate
);
90 substream
->runtime
->hw
.rate_min
= rate
;
91 substream
->runtime
->hw
.rate_max
= rate
;
94 snd_pcm_set_sync(substream
);
98 snd_tscm_stream_lock_release(tscm
);
102 static int pcm_close(struct snd_pcm_substream
*substream
)
104 struct snd_tscm
*tscm
= substream
->private_data
;
106 snd_tscm_stream_lock_release(tscm
);
111 static int pcm_capture_hw_params(struct snd_pcm_substream
*substream
,
112 struct snd_pcm_hw_params
*hw_params
)
114 struct snd_tscm
*tscm
= substream
->private_data
;
117 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
118 params_buffer_bytes(hw_params
));
122 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
123 mutex_lock(&tscm
->mutex
);
124 tscm
->substreams_counter
++;
125 mutex_unlock(&tscm
->mutex
);
128 amdtp_tscm_set_pcm_format(&tscm
->tx_stream
, params_format(hw_params
));
133 static int pcm_playback_hw_params(struct snd_pcm_substream
*substream
,
134 struct snd_pcm_hw_params
*hw_params
)
136 struct snd_tscm
*tscm
= substream
->private_data
;
139 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
140 params_buffer_bytes(hw_params
));
144 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
145 mutex_lock(&tscm
->mutex
);
146 tscm
->substreams_counter
++;
147 mutex_unlock(&tscm
->mutex
);
150 amdtp_tscm_set_pcm_format(&tscm
->rx_stream
, params_format(hw_params
));
155 static int pcm_capture_hw_free(struct snd_pcm_substream
*substream
)
157 struct snd_tscm
*tscm
= substream
->private_data
;
159 mutex_lock(&tscm
->mutex
);
161 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
162 tscm
->substreams_counter
--;
164 snd_tscm_stream_stop_duplex(tscm
);
166 mutex_unlock(&tscm
->mutex
);
168 return snd_pcm_lib_free_vmalloc_buffer(substream
);
171 static int pcm_playback_hw_free(struct snd_pcm_substream
*substream
)
173 struct snd_tscm
*tscm
= substream
->private_data
;
175 mutex_lock(&tscm
->mutex
);
177 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
178 tscm
->substreams_counter
--;
180 snd_tscm_stream_stop_duplex(tscm
);
182 mutex_unlock(&tscm
->mutex
);
184 return snd_pcm_lib_free_vmalloc_buffer(substream
);
187 static int pcm_capture_prepare(struct snd_pcm_substream
*substream
)
189 struct snd_tscm
*tscm
= substream
->private_data
;
190 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
193 mutex_lock(&tscm
->mutex
);
195 err
= snd_tscm_stream_start_duplex(tscm
, runtime
->rate
);
197 amdtp_stream_pcm_prepare(&tscm
->tx_stream
);
199 mutex_unlock(&tscm
->mutex
);
204 static int pcm_playback_prepare(struct snd_pcm_substream
*substream
)
206 struct snd_tscm
*tscm
= substream
->private_data
;
207 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
210 mutex_lock(&tscm
->mutex
);
212 err
= snd_tscm_stream_start_duplex(tscm
, runtime
->rate
);
214 amdtp_stream_pcm_prepare(&tscm
->rx_stream
);
216 mutex_unlock(&tscm
->mutex
);
221 static int pcm_capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
223 struct snd_tscm
*tscm
= substream
->private_data
;
226 case SNDRV_PCM_TRIGGER_START
:
227 amdtp_stream_pcm_trigger(&tscm
->tx_stream
, substream
);
229 case SNDRV_PCM_TRIGGER_STOP
:
230 amdtp_stream_pcm_trigger(&tscm
->tx_stream
, NULL
);
239 static int pcm_playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
241 struct snd_tscm
*tscm
= substream
->private_data
;
244 case SNDRV_PCM_TRIGGER_START
:
245 amdtp_stream_pcm_trigger(&tscm
->rx_stream
, substream
);
247 case SNDRV_PCM_TRIGGER_STOP
:
248 amdtp_stream_pcm_trigger(&tscm
->rx_stream
, NULL
);
257 static snd_pcm_uframes_t
pcm_capture_pointer(struct snd_pcm_substream
*sbstrm
)
259 struct snd_tscm
*tscm
= sbstrm
->private_data
;
261 return amdtp_stream_pcm_pointer(&tscm
->tx_stream
);
264 static snd_pcm_uframes_t
pcm_playback_pointer(struct snd_pcm_substream
*sbstrm
)
266 struct snd_tscm
*tscm
= sbstrm
->private_data
;
268 return amdtp_stream_pcm_pointer(&tscm
->rx_stream
);
271 static const struct snd_pcm_ops pcm_capture_ops
= {
274 .ioctl
= snd_pcm_lib_ioctl
,
275 .hw_params
= pcm_capture_hw_params
,
276 .hw_free
= pcm_capture_hw_free
,
277 .prepare
= pcm_capture_prepare
,
278 .trigger
= pcm_capture_trigger
,
279 .pointer
= pcm_capture_pointer
,
280 .page
= snd_pcm_lib_get_vmalloc_page
,
283 static const struct snd_pcm_ops pcm_playback_ops
= {
286 .ioctl
= snd_pcm_lib_ioctl
,
287 .hw_params
= pcm_playback_hw_params
,
288 .hw_free
= pcm_playback_hw_free
,
289 .prepare
= pcm_playback_prepare
,
290 .trigger
= pcm_playback_trigger
,
291 .pointer
= pcm_playback_pointer
,
292 .page
= snd_pcm_lib_get_vmalloc_page
,
293 .mmap
= snd_pcm_lib_mmap_vmalloc
,
296 int snd_tscm_create_pcm_devices(struct snd_tscm
*tscm
)
301 err
= snd_pcm_new(tscm
->card
, tscm
->card
->driver
, 0, 1, 1, &pcm
);
305 pcm
->private_data
= tscm
;
306 snprintf(pcm
->name
, sizeof(pcm
->name
),
307 "%s PCM", tscm
->card
->shortname
);
308 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &pcm_playback_ops
);
309 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &pcm_capture_ops
);