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