xref: /openbmc/linux/sound/firewire/fireface/ff-pcm.c (revision 3fc41476)
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_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 		unsigned int rate = params_rate(hw_params);
215 
216 		mutex_lock(&ff->mutex);
217 		err = snd_ff_stream_reserve_duplex(ff, rate);
218 		if (err >= 0)
219 			++ff->substreams_counter;
220 		mutex_unlock(&ff->mutex);
221 	}
222 
223 	return 0;
224 }
225 
226 static int pcm_hw_free(struct snd_pcm_substream *substream)
227 {
228 	struct snd_ff *ff = substream->private_data;
229 
230 	mutex_lock(&ff->mutex);
231 
232 	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
233 		--ff->substreams_counter;
234 
235 	snd_ff_stream_stop_duplex(ff);
236 
237 	mutex_unlock(&ff->mutex);
238 
239 	return snd_pcm_lib_free_vmalloc_buffer(substream);
240 }
241 
242 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
243 {
244 	struct snd_ff *ff = substream->private_data;
245 	struct snd_pcm_runtime *runtime = substream->runtime;
246 	int err;
247 
248 	mutex_lock(&ff->mutex);
249 
250 	err = snd_ff_stream_start_duplex(ff, runtime->rate);
251 	if (err >= 0)
252 		amdtp_stream_pcm_prepare(&ff->tx_stream);
253 
254 	mutex_unlock(&ff->mutex);
255 
256 	return err;
257 }
258 
259 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
260 {
261 	struct snd_ff *ff = substream->private_data;
262 	struct snd_pcm_runtime *runtime = substream->runtime;
263 	int err;
264 
265 	mutex_lock(&ff->mutex);
266 
267 	err = snd_ff_stream_start_duplex(ff, runtime->rate);
268 	if (err >= 0)
269 		amdtp_stream_pcm_prepare(&ff->rx_stream);
270 
271 	mutex_unlock(&ff->mutex);
272 
273 	return err;
274 }
275 
276 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
277 {
278 	struct snd_ff *ff = substream->private_data;
279 
280 	switch (cmd) {
281 	case SNDRV_PCM_TRIGGER_START:
282 		amdtp_stream_pcm_trigger(&ff->tx_stream, substream);
283 		break;
284 	case SNDRV_PCM_TRIGGER_STOP:
285 		amdtp_stream_pcm_trigger(&ff->tx_stream, NULL);
286 		break;
287 	default:
288 		return -EINVAL;
289 	}
290 
291 	return 0;
292 }
293 
294 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
295 {
296 	struct snd_ff *ff = substream->private_data;
297 
298 	switch (cmd) {
299 	case SNDRV_PCM_TRIGGER_START:
300 		amdtp_stream_pcm_trigger(&ff->rx_stream, substream);
301 		break;
302 	case SNDRV_PCM_TRIGGER_STOP:
303 		amdtp_stream_pcm_trigger(&ff->rx_stream, NULL);
304 		break;
305 	default:
306 		return -EINVAL;
307 	}
308 
309 	return 0;
310 }
311 
312 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
313 {
314 	struct snd_ff *ff = sbstrm->private_data;
315 
316 	return amdtp_stream_pcm_pointer(&ff->tx_stream);
317 }
318 
319 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
320 {
321 	struct snd_ff *ff = sbstrm->private_data;
322 
323 	return amdtp_stream_pcm_pointer(&ff->rx_stream);
324 }
325 
326 static int pcm_capture_ack(struct snd_pcm_substream *substream)
327 {
328 	struct snd_ff *ff = substream->private_data;
329 
330 	return amdtp_stream_pcm_ack(&ff->tx_stream);
331 }
332 
333 static int pcm_playback_ack(struct snd_pcm_substream *substream)
334 {
335 	struct snd_ff *ff = substream->private_data;
336 
337 	return amdtp_stream_pcm_ack(&ff->rx_stream);
338 }
339 
340 int snd_ff_create_pcm_devices(struct snd_ff *ff)
341 {
342 	static const struct snd_pcm_ops pcm_capture_ops = {
343 		.open		= pcm_open,
344 		.close		= pcm_close,
345 		.ioctl		= snd_pcm_lib_ioctl,
346 		.hw_params	= pcm_hw_params,
347 		.hw_free	= pcm_hw_free,
348 		.prepare	= pcm_capture_prepare,
349 		.trigger	= pcm_capture_trigger,
350 		.pointer	= pcm_capture_pointer,
351 		.ack		= pcm_capture_ack,
352 		.page		= snd_pcm_lib_get_vmalloc_page,
353 	};
354 	static const struct snd_pcm_ops pcm_playback_ops = {
355 		.open		= pcm_open,
356 		.close		= pcm_close,
357 		.ioctl		= snd_pcm_lib_ioctl,
358 		.hw_params	= pcm_hw_params,
359 		.hw_free	= pcm_hw_free,
360 		.prepare	= pcm_playback_prepare,
361 		.trigger	= pcm_playback_trigger,
362 		.pointer	= pcm_playback_pointer,
363 		.ack		= pcm_playback_ack,
364 		.page		= snd_pcm_lib_get_vmalloc_page,
365 	};
366 	struct snd_pcm *pcm;
367 	int err;
368 
369 	err = snd_pcm_new(ff->card, ff->card->driver, 0, 1, 1, &pcm);
370 	if (err < 0)
371 		return err;
372 
373 	pcm->private_data = ff;
374 	snprintf(pcm->name, sizeof(pcm->name),
375 		 "%s PCM", ff->card->shortname);
376 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
377 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
378 
379 	return 0;
380 }
381