xref: /openbmc/linux/sound/firewire/motu/motu-pcm.c (revision 4f727ecefefbd180de10e25b3e74c03dce3f1e75)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * motu-pcm.c - a part of driver for MOTU FireWire series
4  *
5  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6  */
7 
8 #include <sound/pcm_params.h>
9 #include "motu.h"
10 
11 static int motu_rate_constraint(struct snd_pcm_hw_params *params,
12 				struct snd_pcm_hw_rule *rule)
13 {
14 	struct snd_motu_packet_format *formats = rule->private;
15 
16 	const struct snd_interval *c =
17 		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
18 	struct snd_interval *r =
19 		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
20 	struct snd_interval rates = {
21 		.min = UINT_MAX, .max = 0, .integer = 1
22 	};
23 	unsigned int i, pcm_channels, rate, mode;
24 
25 	for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
26 		rate = snd_motu_clock_rates[i];
27 		mode = i / 2;
28 
29 		pcm_channels = formats->fixed_part_pcm_chunks[mode] +
30 			       formats->differed_part_pcm_chunks[mode];
31 		if (!snd_interval_test(c, pcm_channels))
32 			continue;
33 
34 		rates.min = min(rates.min, rate);
35 		rates.max = max(rates.max, rate);
36 	}
37 
38 	return snd_interval_refine(r, &rates);
39 }
40 
41 static int motu_channels_constraint(struct snd_pcm_hw_params *params,
42 				    struct snd_pcm_hw_rule *rule)
43 {
44 	struct snd_motu_packet_format *formats = rule->private;
45 
46 	const struct snd_interval *r =
47 		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
48 	struct snd_interval *c =
49 		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
50 	struct snd_interval channels = {
51 		.min = UINT_MAX, .max = 0, .integer = 1
52 	};
53 	unsigned int i, pcm_channels, rate, mode;
54 
55 	for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
56 		rate = snd_motu_clock_rates[i];
57 		mode = i / 2;
58 
59 		if (!snd_interval_test(r, rate))
60 			continue;
61 
62 		pcm_channels = formats->fixed_part_pcm_chunks[mode] +
63 			       formats->differed_part_pcm_chunks[mode];
64 		channels.min = min(channels.min, pcm_channels);
65 		channels.max = max(channels.max, pcm_channels);
66 	}
67 
68 	return snd_interval_refine(c, &channels);
69 }
70 
71 static void limit_channels_and_rates(struct snd_motu *motu,
72 				     struct snd_pcm_runtime *runtime,
73 				     struct snd_motu_packet_format *formats)
74 {
75 	struct snd_pcm_hardware *hw = &runtime->hw;
76 	unsigned int i, pcm_channels, rate, mode;
77 
78 	hw->channels_min = UINT_MAX;
79 	hw->channels_max = 0;
80 
81 	for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
82 		rate = snd_motu_clock_rates[i];
83 		mode = i / 2;
84 
85 		pcm_channels = formats->fixed_part_pcm_chunks[mode] +
86 			       formats->differed_part_pcm_chunks[mode];
87 		if (pcm_channels == 0)
88 			continue;
89 
90 		hw->rates |= snd_pcm_rate_to_rate_bit(rate);
91 		hw->channels_min = min(hw->channels_min, pcm_channels);
92 		hw->channels_max = max(hw->channels_max, pcm_channels);
93 	}
94 
95 	snd_pcm_limit_hw_rates(runtime);
96 }
97 
98 static int init_hw_info(struct snd_motu *motu,
99 			struct snd_pcm_substream *substream)
100 {
101 	struct snd_pcm_runtime *runtime = substream->runtime;
102 	struct snd_pcm_hardware *hw = &runtime->hw;
103 	struct amdtp_stream *stream;
104 	struct snd_motu_packet_format *formats;
105 	int err;
106 
107 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
108 		hw->formats = SNDRV_PCM_FMTBIT_S32;
109 		stream = &motu->tx_stream;
110 		formats = &motu->tx_packet_formats;
111 	} else {
112 		hw->formats = SNDRV_PCM_FMTBIT_S32;
113 		stream = &motu->rx_stream;
114 		formats = &motu->rx_packet_formats;
115 	}
116 
117 	limit_channels_and_rates(motu, runtime, formats);
118 
119 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
120 				  motu_rate_constraint, formats,
121 				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
122 	if (err < 0)
123 		return err;
124 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
125 				  motu_channels_constraint, formats,
126 				  SNDRV_PCM_HW_PARAM_RATE, -1);
127 	if (err < 0)
128 		return err;
129 
130 	return amdtp_motu_add_pcm_hw_constraints(stream, runtime);
131 }
132 
133 static int pcm_open(struct snd_pcm_substream *substream)
134 {
135 	struct snd_motu *motu = substream->private_data;
136 	const struct snd_motu_protocol *const protocol = motu->spec->protocol;
137 	enum snd_motu_clock_source src;
138 	unsigned int rate;
139 	int err;
140 
141 	err = snd_motu_stream_lock_try(motu);
142 	if (err < 0)
143 		return err;
144 
145 	mutex_lock(&motu->mutex);
146 
147 	err = snd_motu_stream_cache_packet_formats(motu);
148 	if (err < 0)
149 		goto err_locked;
150 
151 	err = init_hw_info(motu, substream);
152 	if (err < 0)
153 		goto err_locked;
154 
155 	/*
156 	 * When source of clock is not internal or any PCM streams are running,
157 	 * available sampling rate is limited at current sampling rate.
158 	 */
159 	err = protocol->get_clock_source(motu, &src);
160 	if (err < 0)
161 		goto err_locked;
162 	if (src != SND_MOTU_CLOCK_SOURCE_INTERNAL ||
163 	    amdtp_stream_pcm_running(&motu->tx_stream) ||
164 	    amdtp_stream_pcm_running(&motu->rx_stream)) {
165 		err = protocol->get_clock_rate(motu, &rate);
166 		if (err < 0)
167 			goto err_locked;
168 		substream->runtime->hw.rate_min = rate;
169 		substream->runtime->hw.rate_max = rate;
170 	}
171 
172 	snd_pcm_set_sync(substream);
173 
174 	mutex_unlock(&motu->mutex);
175 
176 	return err;
177 err_locked:
178 	mutex_unlock(&motu->mutex);
179 	snd_motu_stream_lock_release(motu);
180 	return err;
181 }
182 
183 static int pcm_close(struct snd_pcm_substream *substream)
184 {
185 	struct snd_motu *motu = substream->private_data;
186 
187 	snd_motu_stream_lock_release(motu);
188 
189 	return 0;
190 }
191 
192 static int capture_hw_params(struct snd_pcm_substream *substream,
193 			     struct snd_pcm_hw_params *hw_params)
194 {
195 	struct snd_motu *motu = substream->private_data;
196 	int err;
197 
198 	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
199 					       params_buffer_bytes(hw_params));
200 	if (err < 0)
201 		return err;
202 
203 	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
204 		mutex_lock(&motu->mutex);
205 		motu->capture_substreams++;
206 		mutex_unlock(&motu->mutex);
207 	}
208 
209 	return 0;
210 }
211 static int playback_hw_params(struct snd_pcm_substream *substream,
212 			      struct snd_pcm_hw_params *hw_params)
213 {
214 	struct snd_motu *motu = substream->private_data;
215 	int err;
216 
217 	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
218 					       params_buffer_bytes(hw_params));
219 	if (err < 0)
220 		return err;
221 
222 	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
223 		mutex_lock(&motu->mutex);
224 		motu->playback_substreams++;
225 		mutex_unlock(&motu->mutex);
226 	}
227 
228 	return 0;
229 }
230 
231 static int capture_hw_free(struct snd_pcm_substream *substream)
232 {
233 	struct snd_motu *motu = substream->private_data;
234 
235 	mutex_lock(&motu->mutex);
236 
237 	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
238 		motu->capture_substreams--;
239 
240 	snd_motu_stream_stop_duplex(motu);
241 
242 	mutex_unlock(&motu->mutex);
243 
244 	return snd_pcm_lib_free_vmalloc_buffer(substream);
245 }
246 
247 static int playback_hw_free(struct snd_pcm_substream *substream)
248 {
249 	struct snd_motu *motu = substream->private_data;
250 
251 	mutex_lock(&motu->mutex);
252 
253 	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
254 		motu->playback_substreams--;
255 
256 	snd_motu_stream_stop_duplex(motu);
257 
258 	mutex_unlock(&motu->mutex);
259 
260 	return snd_pcm_lib_free_vmalloc_buffer(substream);
261 }
262 
263 static int capture_prepare(struct snd_pcm_substream *substream)
264 {
265 	struct snd_motu *motu = substream->private_data;
266 	int err;
267 
268 	mutex_lock(&motu->mutex);
269 	err = snd_motu_stream_start_duplex(motu, substream->runtime->rate);
270 	mutex_unlock(&motu->mutex);
271 	if (err >= 0)
272 		amdtp_stream_pcm_prepare(&motu->tx_stream);
273 
274 	return 0;
275 }
276 static int playback_prepare(struct snd_pcm_substream *substream)
277 {
278 	struct snd_motu *motu = substream->private_data;
279 	int err;
280 
281 	mutex_lock(&motu->mutex);
282 	err = snd_motu_stream_start_duplex(motu, substream->runtime->rate);
283 	mutex_unlock(&motu->mutex);
284 	if (err >= 0)
285 		amdtp_stream_pcm_prepare(&motu->rx_stream);
286 
287 	return err;
288 }
289 
290 static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
291 {
292 	struct snd_motu *motu = substream->private_data;
293 
294 	switch (cmd) {
295 	case SNDRV_PCM_TRIGGER_START:
296 		amdtp_stream_pcm_trigger(&motu->tx_stream, substream);
297 		break;
298 	case SNDRV_PCM_TRIGGER_STOP:
299 		amdtp_stream_pcm_trigger(&motu->tx_stream, NULL);
300 		break;
301 	default:
302 		return -EINVAL;
303 	}
304 
305 	return 0;
306 }
307 static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
308 {
309 	struct snd_motu *motu = substream->private_data;
310 
311 	switch (cmd) {
312 	case SNDRV_PCM_TRIGGER_START:
313 		amdtp_stream_pcm_trigger(&motu->rx_stream, substream);
314 		break;
315 	case SNDRV_PCM_TRIGGER_STOP:
316 		amdtp_stream_pcm_trigger(&motu->rx_stream, NULL);
317 		break;
318 	default:
319 		return -EINVAL;
320 	}
321 
322 	return 0;
323 }
324 
325 static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
326 {
327 	struct snd_motu *motu = substream->private_data;
328 
329 	return amdtp_stream_pcm_pointer(&motu->tx_stream);
330 }
331 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
332 {
333 	struct snd_motu *motu = substream->private_data;
334 
335 	return amdtp_stream_pcm_pointer(&motu->rx_stream);
336 }
337 
338 static int capture_ack(struct snd_pcm_substream *substream)
339 {
340 	struct snd_motu *motu = substream->private_data;
341 
342 	return amdtp_stream_pcm_ack(&motu->tx_stream);
343 }
344 
345 static int playback_ack(struct snd_pcm_substream *substream)
346 {
347 	struct snd_motu *motu = substream->private_data;
348 
349 	return amdtp_stream_pcm_ack(&motu->rx_stream);
350 }
351 
352 int snd_motu_create_pcm_devices(struct snd_motu *motu)
353 {
354 	static const struct snd_pcm_ops capture_ops = {
355 		.open      = pcm_open,
356 		.close     = pcm_close,
357 		.ioctl     = snd_pcm_lib_ioctl,
358 		.hw_params = capture_hw_params,
359 		.hw_free   = capture_hw_free,
360 		.prepare   = capture_prepare,
361 		.trigger   = capture_trigger,
362 		.pointer   = capture_pointer,
363 		.ack       = capture_ack,
364 		.page      = snd_pcm_lib_get_vmalloc_page,
365 	};
366 	static const struct snd_pcm_ops playback_ops = {
367 		.open      = pcm_open,
368 		.close     = pcm_close,
369 		.ioctl     = snd_pcm_lib_ioctl,
370 		.hw_params = playback_hw_params,
371 		.hw_free   = playback_hw_free,
372 		.prepare   = playback_prepare,
373 		.trigger   = playback_trigger,
374 		.pointer   = playback_pointer,
375 		.ack       = playback_ack,
376 		.page      = snd_pcm_lib_get_vmalloc_page,
377 	};
378 	struct snd_pcm *pcm;
379 	int err;
380 
381 	err = snd_pcm_new(motu->card, motu->card->driver, 0, 1, 1, &pcm);
382 	if (err < 0)
383 		return err;
384 	pcm->private_data = motu;
385 	strcpy(pcm->name, motu->card->shortname);
386 
387 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
388 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
389 
390 	return 0;
391 }
392