1 // SPDX-License-Identifier: GPL-2.0-only
3 * tascam-pcm.c - a part of driver for TASCAM FireWire series
5 * Copyright (c) 2015 Takashi Sakamoto
10 static int pcm_init_hw_params(struct snd_tscm
*tscm
,
11 struct snd_pcm_substream
*substream
)
13 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
14 struct snd_pcm_hardware
*hw
= &runtime
->hw
;
15 struct amdtp_stream
*stream
;
16 unsigned int pcm_channels
;
18 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
19 runtime
->hw
.formats
= SNDRV_PCM_FMTBIT_S32
;
20 stream
= &tscm
->tx_stream
;
21 pcm_channels
= tscm
->spec
->pcm_capture_analog_channels
;
23 runtime
->hw
.formats
= SNDRV_PCM_FMTBIT_S32
;
24 stream
= &tscm
->rx_stream
;
25 pcm_channels
= tscm
->spec
->pcm_playback_analog_channels
;
28 if (tscm
->spec
->has_adat
)
30 if (tscm
->spec
->has_spdif
)
32 runtime
->hw
.channels_min
= runtime
->hw
.channels_max
= pcm_channels
;
34 hw
->rates
= SNDRV_PCM_RATE_44100
|
35 SNDRV_PCM_RATE_48000
|
36 SNDRV_PCM_RATE_88200
|
38 snd_pcm_limit_hw_rates(runtime
);
40 return amdtp_tscm_add_pcm_hw_constraints(stream
, runtime
);
43 static int pcm_open(struct snd_pcm_substream
*substream
)
45 struct snd_tscm
*tscm
= substream
->private_data
;
46 struct amdtp_domain
*d
= &tscm
->domain
;
47 enum snd_tscm_clock clock
;
50 err
= snd_tscm_stream_lock_try(tscm
);
54 err
= pcm_init_hw_params(tscm
, substream
);
58 err
= snd_tscm_stream_get_clock(tscm
, &clock
);
62 mutex_lock(&tscm
->mutex
);
64 // When source of clock is not internal or any stream is reserved for
65 // transmission of PCM frames, the available sampling rate is limited
67 if (clock
!= SND_TSCM_CLOCK_INTERNAL
|| tscm
->substreams_counter
> 0) {
68 unsigned int frames_per_period
= d
->events_per_period
;
69 unsigned int frames_per_buffer
= d
->events_per_buffer
;
72 err
= snd_tscm_stream_get_rate(tscm
, &rate
);
74 mutex_unlock(&tscm
->mutex
);
77 substream
->runtime
->hw
.rate_min
= rate
;
78 substream
->runtime
->hw
.rate_max
= rate
;
80 err
= snd_pcm_hw_constraint_minmax(substream
->runtime
,
81 SNDRV_PCM_HW_PARAM_PERIOD_SIZE
,
82 frames_per_period
, frames_per_period
);
84 mutex_unlock(&tscm
->mutex
);
88 err
= snd_pcm_hw_constraint_minmax(substream
->runtime
,
89 SNDRV_PCM_HW_PARAM_BUFFER_SIZE
,
90 frames_per_buffer
, frames_per_buffer
);
92 mutex_unlock(&tscm
->mutex
);
97 mutex_unlock(&tscm
->mutex
);
99 snd_pcm_set_sync(substream
);
103 snd_tscm_stream_lock_release(tscm
);
107 static int pcm_close(struct snd_pcm_substream
*substream
)
109 struct snd_tscm
*tscm
= substream
->private_data
;
111 snd_tscm_stream_lock_release(tscm
);
116 static int pcm_hw_params(struct snd_pcm_substream
*substream
,
117 struct snd_pcm_hw_params
*hw_params
)
119 struct snd_tscm
*tscm
= substream
->private_data
;
122 if (substream
->runtime
->status
->state
== SNDRV_PCM_STATE_OPEN
) {
123 unsigned int rate
= params_rate(hw_params
);
124 unsigned int frames_per_period
= params_period_size(hw_params
);
125 unsigned int frames_per_buffer
= params_buffer_size(hw_params
);
127 mutex_lock(&tscm
->mutex
);
128 err
= snd_tscm_stream_reserve_duplex(tscm
, rate
,
129 frames_per_period
, frames_per_buffer
);
131 ++tscm
->substreams_counter
;
132 mutex_unlock(&tscm
->mutex
);
138 static int pcm_hw_free(struct snd_pcm_substream
*substream
)
140 struct snd_tscm
*tscm
= substream
->private_data
;
142 mutex_lock(&tscm
->mutex
);
144 if (substream
->runtime
->status
->state
!= SNDRV_PCM_STATE_OPEN
)
145 --tscm
->substreams_counter
;
147 snd_tscm_stream_stop_duplex(tscm
);
149 mutex_unlock(&tscm
->mutex
);
154 static int pcm_capture_prepare(struct snd_pcm_substream
*substream
)
156 struct snd_tscm
*tscm
= substream
->private_data
;
157 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
160 mutex_lock(&tscm
->mutex
);
162 err
= snd_tscm_stream_start_duplex(tscm
, runtime
->rate
);
164 amdtp_stream_pcm_prepare(&tscm
->tx_stream
);
166 mutex_unlock(&tscm
->mutex
);
171 static int pcm_playback_prepare(struct snd_pcm_substream
*substream
)
173 struct snd_tscm
*tscm
= substream
->private_data
;
174 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
177 mutex_lock(&tscm
->mutex
);
179 err
= snd_tscm_stream_start_duplex(tscm
, runtime
->rate
);
181 amdtp_stream_pcm_prepare(&tscm
->rx_stream
);
183 mutex_unlock(&tscm
->mutex
);
188 static int pcm_capture_trigger(struct snd_pcm_substream
*substream
, int cmd
)
190 struct snd_tscm
*tscm
= substream
->private_data
;
193 case SNDRV_PCM_TRIGGER_START
:
194 amdtp_stream_pcm_trigger(&tscm
->tx_stream
, substream
);
196 case SNDRV_PCM_TRIGGER_STOP
:
197 amdtp_stream_pcm_trigger(&tscm
->tx_stream
, NULL
);
206 static int pcm_playback_trigger(struct snd_pcm_substream
*substream
, int cmd
)
208 struct snd_tscm
*tscm
= substream
->private_data
;
211 case SNDRV_PCM_TRIGGER_START
:
212 amdtp_stream_pcm_trigger(&tscm
->rx_stream
, substream
);
214 case SNDRV_PCM_TRIGGER_STOP
:
215 amdtp_stream_pcm_trigger(&tscm
->rx_stream
, NULL
);
224 static snd_pcm_uframes_t
pcm_capture_pointer(struct snd_pcm_substream
*sbstrm
)
226 struct snd_tscm
*tscm
= sbstrm
->private_data
;
228 return amdtp_domain_stream_pcm_pointer(&tscm
->domain
, &tscm
->tx_stream
);
231 static snd_pcm_uframes_t
pcm_playback_pointer(struct snd_pcm_substream
*sbstrm
)
233 struct snd_tscm
*tscm
= sbstrm
->private_data
;
235 return amdtp_domain_stream_pcm_pointer(&tscm
->domain
, &tscm
->rx_stream
);
238 static int pcm_capture_ack(struct snd_pcm_substream
*substream
)
240 struct snd_tscm
*tscm
= substream
->private_data
;
242 return amdtp_domain_stream_pcm_ack(&tscm
->domain
, &tscm
->tx_stream
);
245 static int pcm_playback_ack(struct snd_pcm_substream
*substream
)
247 struct snd_tscm
*tscm
= substream
->private_data
;
249 return amdtp_domain_stream_pcm_ack(&tscm
->domain
, &tscm
->rx_stream
);
252 int snd_tscm_create_pcm_devices(struct snd_tscm
*tscm
)
254 static const struct snd_pcm_ops capture_ops
= {
257 .hw_params
= pcm_hw_params
,
258 .hw_free
= pcm_hw_free
,
259 .prepare
= pcm_capture_prepare
,
260 .trigger
= pcm_capture_trigger
,
261 .pointer
= pcm_capture_pointer
,
262 .ack
= pcm_capture_ack
,
264 static const struct snd_pcm_ops playback_ops
= {
267 .hw_params
= pcm_hw_params
,
268 .hw_free
= pcm_hw_free
,
269 .prepare
= pcm_playback_prepare
,
270 .trigger
= pcm_playback_trigger
,
271 .pointer
= pcm_playback_pointer
,
272 .ack
= pcm_playback_ack
,
277 err
= snd_pcm_new(tscm
->card
, tscm
->card
->driver
, 0, 1, 1, &pcm
);
281 pcm
->private_data
= tscm
;
282 snprintf(pcm
->name
, sizeof(pcm
->name
),
283 "%s PCM", tscm
->card
->shortname
);
284 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_PLAYBACK
, &playback_ops
);
285 snd_pcm_set_ops(pcm
, SNDRV_PCM_STREAM_CAPTURE
, &capture_ops
);
286 snd_pcm_set_managed_buffer_all(pcm
, SNDRV_DMA_TYPE_VMALLOC
, NULL
, 0, 0);