xref: /openbmc/linux/sound/firewire/motu/motu-pcm.c (revision f3d7c2cd)
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->pcm_chunks[mode];
30 		if (!snd_interval_test(c, pcm_channels))
31 			continue;
32 
33 		rates.min = min(rates.min, rate);
34 		rates.max = max(rates.max, rate);
35 	}
36 
37 	return snd_interval_refine(r, &rates);
38 }
39 
40 static int motu_channels_constraint(struct snd_pcm_hw_params *params,
41 				    struct snd_pcm_hw_rule *rule)
42 {
43 	struct snd_motu_packet_format *formats = rule->private;
44 
45 	const struct snd_interval *r =
46 		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
47 	struct snd_interval *c =
48 		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
49 	struct snd_interval channels = {
50 		.min = UINT_MAX, .max = 0, .integer = 1
51 	};
52 	unsigned int i, pcm_channels, rate, mode;
53 
54 	for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
55 		rate = snd_motu_clock_rates[i];
56 		mode = i / 2;
57 
58 		if (!snd_interval_test(r, rate))
59 			continue;
60 
61 		pcm_channels = formats->pcm_chunks[mode];
62 		channels.min = min(channels.min, pcm_channels);
63 		channels.max = max(channels.max, pcm_channels);
64 	}
65 
66 	return snd_interval_refine(c, &channels);
67 }
68 
69 static void limit_channels_and_rates(struct snd_motu *motu,
70 				     struct snd_pcm_runtime *runtime,
71 				     struct snd_motu_packet_format *formats)
72 {
73 	struct snd_pcm_hardware *hw = &runtime->hw;
74 	unsigned int i, pcm_channels, rate, mode;
75 
76 	hw->channels_min = UINT_MAX;
77 	hw->channels_max = 0;
78 
79 	for (i = 0; i < ARRAY_SIZE(snd_motu_clock_rates); ++i) {
80 		rate = snd_motu_clock_rates[i];
81 		mode = i / 2;
82 
83 		pcm_channels = formats->pcm_chunks[mode];
84 		if (pcm_channels == 0)
85 			continue;
86 
87 		hw->rates |= snd_pcm_rate_to_rate_bit(rate);
88 		hw->channels_min = min(hw->channels_min, pcm_channels);
89 		hw->channels_max = max(hw->channels_max, pcm_channels);
90 	}
91 
92 	snd_pcm_limit_hw_rates(runtime);
93 }
94 
95 static int init_hw_info(struct snd_motu *motu,
96 			struct snd_pcm_substream *substream)
97 {
98 	struct snd_pcm_runtime *runtime = substream->runtime;
99 	struct snd_pcm_hardware *hw = &runtime->hw;
100 	struct amdtp_stream *stream;
101 	struct snd_motu_packet_format *formats;
102 	int err;
103 
104 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
105 		hw->formats = SNDRV_PCM_FMTBIT_S32;
106 		stream = &motu->tx_stream;
107 		formats = &motu->tx_packet_formats;
108 	} else {
109 		hw->formats = SNDRV_PCM_FMTBIT_S32;
110 		stream = &motu->rx_stream;
111 		formats = &motu->rx_packet_formats;
112 	}
113 
114 	limit_channels_and_rates(motu, runtime, formats);
115 
116 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
117 				  motu_rate_constraint, formats,
118 				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
119 	if (err < 0)
120 		return err;
121 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
122 				  motu_channels_constraint, formats,
123 				  SNDRV_PCM_HW_PARAM_RATE, -1);
124 	if (err < 0)
125 		return err;
126 
127 	return amdtp_motu_add_pcm_hw_constraints(stream, runtime);
128 }
129 
130 static int pcm_open(struct snd_pcm_substream *substream)
131 {
132 	struct snd_motu *motu = substream->private_data;
133 	struct amdtp_domain *d = &motu->domain;
134 	enum snd_motu_clock_source src;
135 	int err;
136 
137 	err = snd_motu_stream_lock_try(motu);
138 	if (err < 0)
139 		return err;
140 
141 	mutex_lock(&motu->mutex);
142 
143 	err = snd_motu_stream_cache_packet_formats(motu);
144 	if (err < 0)
145 		goto err_locked;
146 
147 	err = init_hw_info(motu, substream);
148 	if (err < 0)
149 		goto err_locked;
150 
151 	err = snd_motu_protocol_get_clock_source(motu, &src);
152 	if (err < 0)
153 		goto err_locked;
154 
155 	// When source of clock is not internal or any stream is reserved for
156 	// transmission of PCM frames, the available sampling rate is limited
157 	// at current one.
158 	if ((src != SND_MOTU_CLOCK_SOURCE_INTERNAL &&
159 	     src != SND_MOTU_CLOCK_SOURCE_SPH) ||
160 	    (motu->substreams_counter > 0 && d->events_per_period > 0)) {
161 		unsigned int frames_per_period = d->events_per_period;
162 		unsigned int frames_per_buffer = d->events_per_buffer;
163 		unsigned int rate;
164 
165 		err = snd_motu_protocol_get_clock_rate(motu, &rate);
166 		if (err < 0)
167 			goto err_locked;
168 
169 		substream->runtime->hw.rate_min = rate;
170 		substream->runtime->hw.rate_max = rate;
171 
172 		if (frames_per_period > 0) {
173 			err = snd_pcm_hw_constraint_minmax(substream->runtime,
174 					SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
175 					frames_per_period, frames_per_period);
176 			if (err < 0)
177 				goto err_locked;
178 
179 			err = snd_pcm_hw_constraint_minmax(substream->runtime,
180 					SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
181 					frames_per_buffer, frames_per_buffer);
182 			if (err < 0)
183 				goto err_locked;
184 		}
185 	}
186 
187 	snd_pcm_set_sync(substream);
188 
189 	mutex_unlock(&motu->mutex);
190 
191 	return 0;
192 err_locked:
193 	mutex_unlock(&motu->mutex);
194 	snd_motu_stream_lock_release(motu);
195 	return err;
196 }
197 
198 static int pcm_close(struct snd_pcm_substream *substream)
199 {
200 	struct snd_motu *motu = substream->private_data;
201 
202 	snd_motu_stream_lock_release(motu);
203 
204 	return 0;
205 }
206 
207 static int pcm_hw_params(struct snd_pcm_substream *substream,
208 			 struct snd_pcm_hw_params *hw_params)
209 {
210 	struct snd_motu *motu = substream->private_data;
211 	int err = 0;
212 
213 	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
214 		unsigned int rate = params_rate(hw_params);
215 		unsigned int frames_per_period = params_period_size(hw_params);
216 		unsigned int frames_per_buffer = params_buffer_size(hw_params);
217 
218 		mutex_lock(&motu->mutex);
219 		err = snd_motu_stream_reserve_duplex(motu, rate,
220 					frames_per_period, frames_per_buffer);
221 		if (err >= 0)
222 			++motu->substreams_counter;
223 		mutex_unlock(&motu->mutex);
224 	}
225 
226 	return err;
227 }
228 
229 static int pcm_hw_free(struct snd_pcm_substream *substream)
230 {
231 	struct snd_motu *motu = substream->private_data;
232 
233 	mutex_lock(&motu->mutex);
234 
235 	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
236 		--motu->substreams_counter;
237 
238 	snd_motu_stream_stop_duplex(motu);
239 
240 	mutex_unlock(&motu->mutex);
241 
242 	return 0;
243 }
244 
245 static int capture_prepare(struct snd_pcm_substream *substream)
246 {
247 	struct snd_motu *motu = substream->private_data;
248 	int err;
249 
250 	mutex_lock(&motu->mutex);
251 	err = snd_motu_stream_start_duplex(motu);
252 	mutex_unlock(&motu->mutex);
253 	if (err >= 0)
254 		amdtp_stream_pcm_prepare(&motu->tx_stream);
255 
256 	return 0;
257 }
258 static int playback_prepare(struct snd_pcm_substream *substream)
259 {
260 	struct snd_motu *motu = substream->private_data;
261 	int err;
262 
263 	mutex_lock(&motu->mutex);
264 	err = snd_motu_stream_start_duplex(motu);
265 	mutex_unlock(&motu->mutex);
266 	if (err >= 0)
267 		amdtp_stream_pcm_prepare(&motu->rx_stream);
268 
269 	return err;
270 }
271 
272 static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
273 {
274 	struct snd_motu *motu = substream->private_data;
275 
276 	switch (cmd) {
277 	case SNDRV_PCM_TRIGGER_START:
278 		amdtp_stream_pcm_trigger(&motu->tx_stream, substream);
279 		break;
280 	case SNDRV_PCM_TRIGGER_STOP:
281 		amdtp_stream_pcm_trigger(&motu->tx_stream, NULL);
282 		break;
283 	default:
284 		return -EINVAL;
285 	}
286 
287 	return 0;
288 }
289 static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
290 {
291 	struct snd_motu *motu = substream->private_data;
292 
293 	switch (cmd) {
294 	case SNDRV_PCM_TRIGGER_START:
295 		amdtp_stream_pcm_trigger(&motu->rx_stream, substream);
296 		break;
297 	case SNDRV_PCM_TRIGGER_STOP:
298 		amdtp_stream_pcm_trigger(&motu->rx_stream, NULL);
299 		break;
300 	default:
301 		return -EINVAL;
302 	}
303 
304 	return 0;
305 }
306 
307 static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
308 {
309 	struct snd_motu *motu = substream->private_data;
310 
311 	return amdtp_domain_stream_pcm_pointer(&motu->domain, &motu->tx_stream);
312 }
313 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
314 {
315 	struct snd_motu *motu = substream->private_data;
316 
317 	return amdtp_domain_stream_pcm_pointer(&motu->domain, &motu->rx_stream);
318 }
319 
320 static int capture_ack(struct snd_pcm_substream *substream)
321 {
322 	struct snd_motu *motu = substream->private_data;
323 
324 	return amdtp_domain_stream_pcm_ack(&motu->domain, &motu->tx_stream);
325 }
326 
327 static int playback_ack(struct snd_pcm_substream *substream)
328 {
329 	struct snd_motu *motu = substream->private_data;
330 
331 	return amdtp_domain_stream_pcm_ack(&motu->domain, &motu->rx_stream);
332 }
333 
334 int snd_motu_create_pcm_devices(struct snd_motu *motu)
335 {
336 	static const struct snd_pcm_ops capture_ops = {
337 		.open      = pcm_open,
338 		.close     = pcm_close,
339 		.hw_params = pcm_hw_params,
340 		.hw_free   = pcm_hw_free,
341 		.prepare   = capture_prepare,
342 		.trigger   = capture_trigger,
343 		.pointer   = capture_pointer,
344 		.ack       = capture_ack,
345 	};
346 	static const struct snd_pcm_ops playback_ops = {
347 		.open      = pcm_open,
348 		.close     = pcm_close,
349 		.hw_params = pcm_hw_params,
350 		.hw_free   = pcm_hw_free,
351 		.prepare   = playback_prepare,
352 		.trigger   = playback_trigger,
353 		.pointer   = playback_pointer,
354 		.ack       = playback_ack,
355 	};
356 	struct snd_pcm *pcm;
357 	int err;
358 
359 	err = snd_pcm_new(motu->card, motu->card->driver, 0, 1, 1, &pcm);
360 	if (err < 0)
361 		return err;
362 	pcm->private_data = motu;
363 	strcpy(pcm->name, motu->card->shortname);
364 
365 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
366 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
367 	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
368 
369 	return 0;
370 }
371