xref: /openbmc/linux/sound/firewire/fireface/ff-pcm.c (revision d003d772)
1 /*
2  * ff-pcm.c - a part of driver for RME Fireface series
3  *
4  * Copyright (c) 2015-2017 Takashi Sakamoto
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8 
9 #include "ff.h"
10 
11 static int hw_rule_rate(struct snd_pcm_hw_params *params,
12 			struct snd_pcm_hw_rule *rule)
13 {
14 	const unsigned int *pcm_channels = rule->private;
15 	struct snd_interval *r =
16 		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
17 	const struct snd_interval *c =
18 		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
19 	struct snd_interval t = {
20 		.min = UINT_MAX, .max = 0, .integer = 1
21 	};
22 	unsigned int i;
23 
24 	for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
25 		enum snd_ff_stream_mode mode;
26 		int err;
27 
28 		err = snd_ff_stream_get_multiplier_mode(i, &mode);
29 		if (err < 0)
30 			continue;
31 
32 		if (!snd_interval_test(c, pcm_channels[mode]))
33 			continue;
34 
35 		t.min = min(t.min, amdtp_rate_table[i]);
36 		t.max = max(t.max, amdtp_rate_table[i]);
37 	}
38 
39 	return snd_interval_refine(r, &t);
40 }
41 
42 static int hw_rule_channels(struct snd_pcm_hw_params *params,
43 			    struct snd_pcm_hw_rule *rule)
44 {
45 	const unsigned int *pcm_channels = rule->private;
46 	struct snd_interval *c =
47 		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
48 	const struct snd_interval *r =
49 		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
50 	struct snd_interval t = {
51 		.min = UINT_MAX, .max = 0, .integer = 1
52 	};
53 	unsigned int i;
54 
55 	for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
56 		enum snd_ff_stream_mode mode;
57 		int err;
58 
59 		err = snd_ff_stream_get_multiplier_mode(i, &mode);
60 		if (err < 0)
61 			continue;
62 
63 		if (!snd_interval_test(r, amdtp_rate_table[i]))
64 			continue;
65 
66 		t.min = min(t.min, pcm_channels[mode]);
67 		t.max = max(t.max, pcm_channels[mode]);
68 	}
69 
70 	return snd_interval_refine(c, &t);
71 }
72 
73 static void limit_channels_and_rates(struct snd_pcm_hardware *hw,
74 				     const unsigned int *pcm_channels)
75 {
76 	unsigned int rate, channels;
77 	int i;
78 
79 	hw->channels_min = UINT_MAX;
80 	hw->channels_max = 0;
81 	hw->rate_min = UINT_MAX;
82 	hw->rate_max = 0;
83 
84 	for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
85 		enum snd_ff_stream_mode mode;
86 		int err;
87 
88 		err = snd_ff_stream_get_multiplier_mode(i, &mode);
89 		if (err < 0)
90 			continue;
91 
92 		channels = pcm_channels[mode];
93 		if (pcm_channels[mode] == 0)
94 			continue;
95 		hw->channels_min = min(hw->channels_min, channels);
96 		hw->channels_max = max(hw->channels_max, channels);
97 
98 		rate = amdtp_rate_table[i];
99 		hw->rates |= snd_pcm_rate_to_rate_bit(rate);
100 		hw->rate_min = min(hw->rate_min, rate);
101 		hw->rate_max = max(hw->rate_max, rate);
102 	}
103 }
104 
105 static int pcm_init_hw_params(struct snd_ff *ff,
106 			      struct snd_pcm_substream *substream)
107 {
108 	struct snd_pcm_runtime *runtime = substream->runtime;
109 	struct amdtp_stream *s;
110 	const unsigned int *pcm_channels;
111 	int err;
112 
113 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
114 		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
115 		s = &ff->tx_stream;
116 		pcm_channels = ff->spec->pcm_capture_channels;
117 	} else {
118 		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
119 		s = &ff->rx_stream;
120 		pcm_channels = ff->spec->pcm_playback_channels;
121 	}
122 
123 	limit_channels_and_rates(&runtime->hw, pcm_channels);
124 
125 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
126 				  hw_rule_channels, (void *)pcm_channels,
127 				  SNDRV_PCM_HW_PARAM_RATE, -1);
128 	if (err < 0)
129 		return err;
130 
131 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
132 				  hw_rule_rate, (void *)pcm_channels,
133 				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
134 	if (err < 0)
135 		return err;
136 
137 	return amdtp_ff_add_pcm_hw_constraints(s, runtime);
138 }
139 
140 static int pcm_open(struct snd_pcm_substream *substream)
141 {
142 	struct snd_ff *ff = substream->private_data;
143 	unsigned int rate;
144 	enum snd_ff_clock_src src;
145 	int i, err;
146 
147 	err = snd_ff_stream_lock_try(ff);
148 	if (err < 0)
149 		return err;
150 
151 	err = pcm_init_hw_params(ff, substream);
152 	if (err < 0)
153 		goto release_lock;
154 
155 	err = ff->spec->protocol->get_clock(ff, &rate, &src);
156 	if (err < 0)
157 		goto release_lock;
158 
159 	if (src != SND_FF_CLOCK_SRC_INTERNAL) {
160 		for (i = 0; i < CIP_SFC_COUNT; ++i) {
161 			if (amdtp_rate_table[i] == rate)
162 				break;
163 		}
164 		/*
165 		 * The unit is configured at sampling frequency which packet
166 		 * streaming engine can't support.
167 		 */
168 		if (i >= CIP_SFC_COUNT) {
169 			err = -EIO;
170 			goto release_lock;
171 		}
172 
173 		substream->runtime->hw.rate_min = rate;
174 		substream->runtime->hw.rate_max = rate;
175 	} else {
176 		if (amdtp_stream_pcm_running(&ff->rx_stream) ||
177 		    amdtp_stream_pcm_running(&ff->tx_stream)) {
178 			rate = amdtp_rate_table[ff->rx_stream.sfc];
179 			substream->runtime->hw.rate_min = rate;
180 			substream->runtime->hw.rate_max = rate;
181 		}
182 	}
183 
184 	snd_pcm_set_sync(substream);
185 
186 	return 0;
187 
188 release_lock:
189 	snd_ff_stream_lock_release(ff);
190 	return err;
191 }
192 
193 static int pcm_close(struct snd_pcm_substream *substream)
194 {
195 	struct snd_ff *ff = substream->private_data;
196 
197 	snd_ff_stream_lock_release(ff);
198 
199 	return 0;
200 }
201 
202 static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
203 				 struct snd_pcm_hw_params *hw_params)
204 {
205 	struct snd_ff *ff = substream->private_data;
206 	int err;
207 
208 	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
209 					       params_buffer_bytes(hw_params));
210 	if (err < 0)
211 		return err;
212 
213 	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
214 		mutex_lock(&ff->mutex);
215 		ff->substreams_counter++;
216 		mutex_unlock(&ff->mutex);
217 	}
218 
219 	return 0;
220 }
221 
222 static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
223 				  struct snd_pcm_hw_params *hw_params)
224 {
225 	struct snd_ff *ff = substream->private_data;
226 	int err;
227 
228 	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
229 					       params_buffer_bytes(hw_params));
230 	if (err < 0)
231 		return err;
232 
233 	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
234 		mutex_lock(&ff->mutex);
235 		ff->substreams_counter++;
236 		mutex_unlock(&ff->mutex);
237 	}
238 
239 	return 0;
240 }
241 
242 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
243 {
244 	struct snd_ff *ff = substream->private_data;
245 
246 	mutex_lock(&ff->mutex);
247 
248 	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
249 		ff->substreams_counter--;
250 
251 	snd_ff_stream_stop_duplex(ff);
252 
253 	mutex_unlock(&ff->mutex);
254 
255 	return snd_pcm_lib_free_vmalloc_buffer(substream);
256 }
257 
258 static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
259 {
260 	struct snd_ff *ff = substream->private_data;
261 
262 	mutex_lock(&ff->mutex);
263 
264 	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
265 		ff->substreams_counter--;
266 
267 	snd_ff_stream_stop_duplex(ff);
268 
269 	mutex_unlock(&ff->mutex);
270 
271 	return snd_pcm_lib_free_vmalloc_buffer(substream);
272 }
273 
274 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
275 {
276 	struct snd_ff *ff = substream->private_data;
277 	struct snd_pcm_runtime *runtime = substream->runtime;
278 	int err;
279 
280 	mutex_lock(&ff->mutex);
281 
282 	err = snd_ff_stream_start_duplex(ff, runtime->rate);
283 	if (err >= 0)
284 		amdtp_stream_pcm_prepare(&ff->tx_stream);
285 
286 	mutex_unlock(&ff->mutex);
287 
288 	return err;
289 }
290 
291 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
292 {
293 	struct snd_ff *ff = substream->private_data;
294 	struct snd_pcm_runtime *runtime = substream->runtime;
295 	int err;
296 
297 	mutex_lock(&ff->mutex);
298 
299 	err = snd_ff_stream_start_duplex(ff, runtime->rate);
300 	if (err >= 0)
301 		amdtp_stream_pcm_prepare(&ff->rx_stream);
302 
303 	mutex_unlock(&ff->mutex);
304 
305 	return err;
306 }
307 
308 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
309 {
310 	struct snd_ff *ff = substream->private_data;
311 
312 	switch (cmd) {
313 	case SNDRV_PCM_TRIGGER_START:
314 		amdtp_stream_pcm_trigger(&ff->tx_stream, substream);
315 		break;
316 	case SNDRV_PCM_TRIGGER_STOP:
317 		amdtp_stream_pcm_trigger(&ff->tx_stream, NULL);
318 		break;
319 	default:
320 		return -EINVAL;
321 	}
322 
323 	return 0;
324 }
325 
326 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
327 {
328 	struct snd_ff *ff = substream->private_data;
329 
330 	switch (cmd) {
331 	case SNDRV_PCM_TRIGGER_START:
332 		amdtp_stream_pcm_trigger(&ff->rx_stream, substream);
333 		break;
334 	case SNDRV_PCM_TRIGGER_STOP:
335 		amdtp_stream_pcm_trigger(&ff->rx_stream, NULL);
336 		break;
337 	default:
338 		return -EINVAL;
339 	}
340 
341 	return 0;
342 }
343 
344 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
345 {
346 	struct snd_ff *ff = sbstrm->private_data;
347 
348 	return amdtp_stream_pcm_pointer(&ff->tx_stream);
349 }
350 
351 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
352 {
353 	struct snd_ff *ff = sbstrm->private_data;
354 
355 	return amdtp_stream_pcm_pointer(&ff->rx_stream);
356 }
357 
358 static int pcm_capture_ack(struct snd_pcm_substream *substream)
359 {
360 	struct snd_ff *ff = substream->private_data;
361 
362 	return amdtp_stream_pcm_ack(&ff->tx_stream);
363 }
364 
365 static int pcm_playback_ack(struct snd_pcm_substream *substream)
366 {
367 	struct snd_ff *ff = substream->private_data;
368 
369 	return amdtp_stream_pcm_ack(&ff->rx_stream);
370 }
371 
372 int snd_ff_create_pcm_devices(struct snd_ff *ff)
373 {
374 	static const struct snd_pcm_ops pcm_capture_ops = {
375 		.open		= pcm_open,
376 		.close		= pcm_close,
377 		.ioctl		= snd_pcm_lib_ioctl,
378 		.hw_params	= pcm_capture_hw_params,
379 		.hw_free	= pcm_capture_hw_free,
380 		.prepare	= pcm_capture_prepare,
381 		.trigger	= pcm_capture_trigger,
382 		.pointer	= pcm_capture_pointer,
383 		.ack		= pcm_capture_ack,
384 		.page		= snd_pcm_lib_get_vmalloc_page,
385 	};
386 	static const struct snd_pcm_ops pcm_playback_ops = {
387 		.open		= pcm_open,
388 		.close		= pcm_close,
389 		.ioctl		= snd_pcm_lib_ioctl,
390 		.hw_params	= pcm_playback_hw_params,
391 		.hw_free	= pcm_playback_hw_free,
392 		.prepare	= pcm_playback_prepare,
393 		.trigger	= pcm_playback_trigger,
394 		.pointer	= pcm_playback_pointer,
395 		.ack		= pcm_playback_ack,
396 		.page		= snd_pcm_lib_get_vmalloc_page,
397 	};
398 	struct snd_pcm *pcm;
399 	int err;
400 
401 	err = snd_pcm_new(ff->card, ff->card->driver, 0, 1, 1, &pcm);
402 	if (err < 0)
403 		return err;
404 
405 	pcm->private_data = ff;
406 	snprintf(pcm->name, sizeof(pcm->name),
407 		 "%s PCM", ff->card->shortname);
408 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
409 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
410 
411 	return 0;
412 }
413