xref: /linux/sound/firewire/tascam/tascam-pcm.c (revision 05a54fa773284d1a7923cdfdd8f0c8dabb98bd26)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * tascam-pcm.c - a part of driver for TASCAM FireWire series
4  *
5  * Copyright (c) 2015 Takashi Sakamoto
6  */
7 
8 #include "tascam.h"
9 
10 static int pcm_init_hw_params(struct snd_tscm *tscm,
11 			      struct snd_pcm_substream *substream)
12 {
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;
17 
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;
22 	} else {
23 		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
24 		stream = &tscm->rx_stream;
25 		pcm_channels = tscm->spec->pcm_playback_analog_channels;
26 	}
27 
28 	if (tscm->spec->has_adat)
29 		pcm_channels += 8;
30 	if (tscm->spec->has_spdif)
31 		pcm_channels += 2;
32 	runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels;
33 
34 	hw->rates = SNDRV_PCM_RATE_44100 |
35 		    SNDRV_PCM_RATE_48000 |
36 		    SNDRV_PCM_RATE_88200 |
37 		    SNDRV_PCM_RATE_96000;
38 	snd_pcm_limit_hw_rates(runtime);
39 
40 	return amdtp_tscm_add_pcm_hw_constraints(stream, runtime);
41 }
42 
43 static int pcm_open(struct snd_pcm_substream *substream)
44 {
45 	struct snd_tscm *tscm = substream->private_data;
46 	struct amdtp_domain *d = &tscm->domain;
47 	enum snd_tscm_clock clock;
48 	int err;
49 
50 	err = snd_tscm_stream_lock_try(tscm);
51 	if (err < 0)
52 		return err;
53 
54 	err = pcm_init_hw_params(tscm, substream);
55 	if (err < 0)
56 		goto err_locked;
57 
58 	err = snd_tscm_stream_get_clock(tscm, &clock);
59 	if (err < 0)
60 		goto err_locked;
61 
62 	scoped_guard(mutex, &tscm->mutex) {
63 		// When source of clock is not internal or any stream is reserved for
64 		// transmission of PCM frames, the available sampling rate is limited
65 		// at current one.
66 		if (clock != SND_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) {
67 			unsigned int frames_per_period = d->events_per_period;
68 			unsigned int frames_per_buffer = d->events_per_buffer;
69 			unsigned int rate;
70 
71 			err = snd_tscm_stream_get_rate(tscm, &rate);
72 			if (err < 0)
73 				goto err_locked;
74 			substream->runtime->hw.rate_min = rate;
75 			substream->runtime->hw.rate_max = rate;
76 
77 			err = snd_pcm_hw_constraint_minmax(substream->runtime,
78 							   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
79 							   frames_per_period, frames_per_period);
80 			if (err < 0)
81 				goto err_locked;
82 
83 			err = snd_pcm_hw_constraint_minmax(substream->runtime,
84 							   SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
85 							   frames_per_buffer, frames_per_buffer);
86 			if (err < 0)
87 				goto err_locked;
88 		}
89 	}
90 
91 	snd_pcm_set_sync(substream);
92 
93 	return 0;
94 err_locked:
95 	snd_tscm_stream_lock_release(tscm);
96 	return err;
97 }
98 
99 static int pcm_close(struct snd_pcm_substream *substream)
100 {
101 	struct snd_tscm *tscm = substream->private_data;
102 
103 	snd_tscm_stream_lock_release(tscm);
104 
105 	return 0;
106 }
107 
108 static int pcm_hw_params(struct snd_pcm_substream *substream,
109 			 struct snd_pcm_hw_params *hw_params)
110 {
111 	struct snd_tscm *tscm = substream->private_data;
112 	int err = 0;
113 
114 	if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
115 		unsigned int rate = params_rate(hw_params);
116 		unsigned int frames_per_period = params_period_size(hw_params);
117 		unsigned int frames_per_buffer = params_buffer_size(hw_params);
118 
119 		guard(mutex)(&tscm->mutex);
120 		err = snd_tscm_stream_reserve_duplex(tscm, rate,
121 					frames_per_period, frames_per_buffer);
122 		if (err >= 0)
123 			++tscm->substreams_counter;
124 	}
125 
126 	return err;
127 }
128 
129 static int pcm_hw_free(struct snd_pcm_substream *substream)
130 {
131 	struct snd_tscm *tscm = substream->private_data;
132 
133 	guard(mutex)(&tscm->mutex);
134 
135 	if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
136 		--tscm->substreams_counter;
137 
138 	snd_tscm_stream_stop_duplex(tscm);
139 
140 	return 0;
141 }
142 
143 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
144 {
145 	struct snd_tscm *tscm = substream->private_data;
146 	struct snd_pcm_runtime *runtime = substream->runtime;
147 	int err;
148 
149 	guard(mutex)(&tscm->mutex);
150 
151 	err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
152 	if (err >= 0)
153 		amdtp_stream_pcm_prepare(&tscm->tx_stream);
154 
155 	return err;
156 }
157 
158 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
159 {
160 	struct snd_tscm *tscm = substream->private_data;
161 	struct snd_pcm_runtime *runtime = substream->runtime;
162 	int err;
163 
164 	guard(mutex)(&tscm->mutex);
165 
166 	err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
167 	if (err >= 0)
168 		amdtp_stream_pcm_prepare(&tscm->rx_stream);
169 
170 	return err;
171 }
172 
173 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
174 {
175 	struct snd_tscm *tscm = substream->private_data;
176 
177 	switch (cmd) {
178 	case SNDRV_PCM_TRIGGER_START:
179 		amdtp_stream_pcm_trigger(&tscm->tx_stream, substream);
180 		break;
181 	case SNDRV_PCM_TRIGGER_STOP:
182 		amdtp_stream_pcm_trigger(&tscm->tx_stream, NULL);
183 		break;
184 	default:
185 		return -EINVAL;
186 	}
187 
188 	return 0;
189 }
190 
191 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
192 {
193 	struct snd_tscm *tscm = substream->private_data;
194 
195 	switch (cmd) {
196 	case SNDRV_PCM_TRIGGER_START:
197 		amdtp_stream_pcm_trigger(&tscm->rx_stream, substream);
198 		break;
199 	case SNDRV_PCM_TRIGGER_STOP:
200 		amdtp_stream_pcm_trigger(&tscm->rx_stream, NULL);
201 		break;
202 	default:
203 		return -EINVAL;
204 	}
205 
206 	return 0;
207 }
208 
209 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
210 {
211 	struct snd_tscm *tscm = sbstrm->private_data;
212 
213 	return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->tx_stream);
214 }
215 
216 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
217 {
218 	struct snd_tscm *tscm = sbstrm->private_data;
219 
220 	return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->rx_stream);
221 }
222 
223 static int pcm_capture_ack(struct snd_pcm_substream *substream)
224 {
225 	struct snd_tscm *tscm = substream->private_data;
226 
227 	return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->tx_stream);
228 }
229 
230 static int pcm_playback_ack(struct snd_pcm_substream *substream)
231 {
232 	struct snd_tscm *tscm = substream->private_data;
233 
234 	return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->rx_stream);
235 }
236 
237 int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
238 {
239 	static const struct snd_pcm_ops capture_ops = {
240 		.open		= pcm_open,
241 		.close		= pcm_close,
242 		.hw_params	= pcm_hw_params,
243 		.hw_free	= pcm_hw_free,
244 		.prepare	= pcm_capture_prepare,
245 		.trigger	= pcm_capture_trigger,
246 		.pointer	= pcm_capture_pointer,
247 		.ack		= pcm_capture_ack,
248 	};
249 	static const struct snd_pcm_ops playback_ops = {
250 		.open		= pcm_open,
251 		.close		= pcm_close,
252 		.hw_params	= pcm_hw_params,
253 		.hw_free	= pcm_hw_free,
254 		.prepare	= pcm_playback_prepare,
255 		.trigger	= pcm_playback_trigger,
256 		.pointer	= pcm_playback_pointer,
257 		.ack		= pcm_playback_ack,
258 	};
259 	struct snd_pcm *pcm;
260 	int err;
261 
262 	err = snd_pcm_new(tscm->card, tscm->card->driver, 0, 1, 1, &pcm);
263 	if (err < 0)
264 		return err;
265 
266 	pcm->private_data = tscm;
267 	pcm->nonatomic = true;
268 	snprintf(pcm->name, sizeof(pcm->name),
269 		 "%s PCM", tscm->card->shortname);
270 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
271 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
272 	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
273 
274 	return 0;
275 }
276