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 int pcm_init_hw_params(struct snd_tscm
*tscm
,
12 struct snd_pcm_substream
*substream
)
14 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
15 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
16 struct amdtp_stream
*stream
;
17 unsigned int pcm_channels
;
19 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
20 runtime
->hw
.formats
= SNDRV_PCM_FMTBIT_S32
;
21 stream
= &tscm
->tx_stream
;
22 pcm_channels
= tscm
->spec
->pcm_capture_analog_channels
;
24 runtime
->hw
.formats
= SNDRV_PCM_FMTBIT_S32
;
25 stream
= &tscm
->rx_stream
;
26 pcm_channels
= tscm
->spec
->pcm_playback_analog_channels
;
29 if (tscm
->spec
->has_adat
)
31 if (tscm
->spec
->has_spdif
)
33 runtime
->hw
.channels_min
= runtime
->hw
.channels_max
= pcm_channels
;
35 hw
->rates
= SNDRV_PCM_RATE_44100
|
36 SNDRV_PCM_RATE_48000
|
37 SNDRV_PCM_RATE_88200
|
39 snd_pcm_limit_hw_rates(runtime
);
41 return amdtp_tscm_add_pcm_hw_constraints(stream
, runtime
);
44 static int pcm_open(struct snd_pcm_substream
*substream
)
46 struct snd_tscm
*tscm
= substream
->private_data
;
47 enum snd_tscm_clock clock
;
51 err
= snd_tscm_stream_lock_try(tscm
);
55 err
= pcm_init_hw_params(tscm
, substream
);
59 err
= snd_tscm_stream_get_clock(tscm
, &clock
);
60 if (clock
!= SND_TSCM_CLOCK_INTERNAL
||
61 amdtp_stream_pcm_running(&tscm
->rx_stream
) ||
62 amdtp_stream_pcm_running(&tscm
->tx_stream
)) {
63 err
= snd_tscm_stream_get_rate(tscm
, &rate
);
66 substream
->runtime
->hw
.rate_min
= rate
;
67 substream
->runtime
->hw
.rate_max
= rate
;
70 snd_pcm_set_sync(substream
);
74 snd_tscm_stream_lock_release(tscm
);
78 static int pcm_close(struct snd_pcm_substream
*substream
)
80 struct snd_tscm
*tscm
= substream
->private_data
;
82 snd_tscm_stream_lock_release(tscm
);
87 static int pcm_capture_hw_params(struct snd_pcm_substream
*substream
,
88 struct snd_pcm_hw_params
*hw_params
)
90 struct snd_tscm
*tscm
= substream
->private_data
;
93 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
94 params_buffer_bytes(hw_params
));
98 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
99 mutex_lock(&tscm
->mutex
);
100 tscm
->substreams_counter
++;
101 mutex_unlock(&tscm
->mutex
);
107 static int pcm_playback_hw_params(struct snd_pcm_substream
*substream
,
108 struct snd_pcm_hw_params
*hw_params
)
110 struct snd_tscm
*tscm
= substream
->private_data
;
113 err
= snd_pcm_lib_alloc_vmalloc_buffer(substream
,
114 params_buffer_bytes(hw_params
));
118 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
119 mutex_lock(&tscm
->mutex
);
120 tscm
->substreams_counter
++;
121 mutex_unlock(&tscm
->mutex
);
127 static int pcm_capture_hw_free(struct snd_pcm_substream
*substream
)
129 struct snd_tscm
*tscm
= substream
->private_data
;
131 mutex_lock(&tscm
->mutex
);
133 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
134 tscm
->substreams_counter
--;
136 snd_tscm_stream_stop_duplex(tscm
);
138 mutex_unlock(&tscm
->mutex
);
140 return snd_pcm_lib_free_vmalloc_buffer(substream
);
143 static int pcm_playback_hw_free(struct snd_pcm_substream
*substream
)
145 struct snd_tscm
*tscm
= substream
->private_data
;
147 mutex_lock(&tscm
->mutex
);
149 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
150 tscm
->substreams_counter
--;
152 snd_tscm_stream_stop_duplex(tscm
);
154 mutex_unlock(&tscm
->mutex
);
156 return snd_pcm_lib_free_vmalloc_buffer(substream
);
159 static int pcm_capture_prepare(struct snd_pcm_substream
*substream
)
161 struct snd_tscm
*tscm
= substream
->private_data
;
162 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
165 mutex_lock(&tscm
->mutex
);
167 err
= snd_tscm_stream_start_duplex(tscm
, runtime
->rate
);
169 amdtp_stream_pcm_prepare(&tscm
->tx_stream
);
171 mutex_unlock(&tscm
->mutex
);
176 static int pcm_playback_prepare(struct snd_pcm_substream
*substream
)
178 struct snd_tscm
*tscm
= substream
->private_data
;
179 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
182 mutex_lock(&tscm
->mutex
);
184 err
= snd_tscm_stream_start_duplex(tscm
, runtime
->rate
);
186 amdtp_stream_pcm_prepare(&tscm
->rx_stream
);
188 mutex_unlock(&tscm
->mutex
);
193 static int pcm_capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
195 struct snd_tscm
*tscm
= substream
->private_data
;
198 case SNDRV_PCM_TRIGGER_START
:
199 amdtp_stream_pcm_trigger(&tscm
->tx_stream
, substream
);
201 case SNDRV_PCM_TRIGGER_STOP
:
202 amdtp_stream_pcm_trigger(&tscm
->tx_stream
, NULL
);
211 static int pcm_playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
213 struct snd_tscm
*tscm
= substream
->private_data
;
216 case SNDRV_PCM_TRIGGER_START
:
217 amdtp_stream_pcm_trigger(&tscm
->rx_stream
, substream
);
219 case SNDRV_PCM_TRIGGER_STOP
:
220 amdtp_stream_pcm_trigger(&tscm
->rx_stream
, NULL
);
229 static snd_pcm_uframes_t
pcm_capture_pointer(struct snd_pcm_substream
*sbstrm
)
231 struct snd_tscm
*tscm
= sbstrm
->private_data
;
233 return amdtp_stream_pcm_pointer(&tscm
->tx_stream
);
236 static snd_pcm_uframes_t
pcm_playback_pointer(struct snd_pcm_substream
*sbstrm
)
238 struct snd_tscm
*tscm
= sbstrm
->private_data
;
240 return amdtp_stream_pcm_pointer(&tscm
->rx_stream
);
243 static int pcm_capture_ack(struct snd_pcm_substream
*substream
)
245 struct snd_tscm
*tscm
= substream
->private_data
;
247 return amdtp_stream_pcm_ack(&tscm
->tx_stream
);
250 static int pcm_playback_ack(struct snd_pcm_substream
*substream
)
252 struct snd_tscm
*tscm
= substream
->private_data
;
254 return amdtp_stream_pcm_ack(&tscm
->rx_stream
);
257 int snd_tscm_create_pcm_devices(struct snd_tscm
*tscm
)
259 static const struct snd_pcm_ops capture_ops
= {
262 .ioctl
= snd_pcm_lib_ioctl
,
263 .hw_params
= pcm_capture_hw_params
,
264 .hw_free
= pcm_capture_hw_free
,
265 .prepare
= pcm_capture_prepare
,
266 .trigger
= pcm_capture_trigger
,
267 .pointer
= pcm_capture_pointer
,
268 .ack
= pcm_capture_ack
,
269 .page
= snd_pcm_lib_get_vmalloc_page
,
271 static const struct snd_pcm_ops playback_ops
= {
274 .ioctl
= snd_pcm_lib_ioctl
,
275 .hw_params
= pcm_playback_hw_params
,
276 .hw_free
= pcm_playback_hw_free
,
277 .prepare
= pcm_playback_prepare
,
278 .trigger
= pcm_playback_trigger
,
279 .pointer
= pcm_playback_pointer
,
280 .ack
= pcm_playback_ack
,
281 .page
= snd_pcm_lib_get_vmalloc_page
,
282 .mmap
= snd_pcm_lib_mmap_vmalloc
,
287 err
= snd_pcm_new(tscm
->card
, tscm
->card
->driver
, 0, 1, 1, &pcm
);
291 pcm
->private_data
= tscm
;
292 snprintf(pcm
->name
, sizeof(pcm
->name
),
293 "%s PCM", tscm
->card
->shortname
);
294 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &playback_ops
);
295 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &capture_ops
);