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
get_multiplier_mode_with_index(unsigned int index)11 static inline unsigned int get_multiplier_mode_with_index(unsigned int index)
12 {
13 return ((int)index - 1) / 2;
14 }
15
hw_rule_rate(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)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
hw_rule_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)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
limit_channels_and_rates(struct snd_pcm_hardware * hw,const unsigned int * pcm_channels)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
pcm_init_hw_params(struct snd_ff * ff,struct snd_pcm_substream * substream)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
pcm_open(struct snd_pcm_substream * substream)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
pcm_close(struct snd_pcm_substream * substream)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
pcm_capture_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)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
pcm_playback_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)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
pcm_capture_hw_free(struct snd_pcm_substream * substream)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
pcm_playback_hw_free(struct snd_pcm_substream * substream)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
pcm_capture_prepare(struct snd_pcm_substream * substream)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
pcm_playback_prepare(struct snd_pcm_substream * substream)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
pcm_capture_trigger(struct snd_pcm_substream * substream,int cmd)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
pcm_playback_trigger(struct snd_pcm_substream * substream,int cmd)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
pcm_capture_pointer(struct snd_pcm_substream * sbstrm)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
pcm_playback_pointer(struct snd_pcm_substream * sbstrm)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
pcm_capture_ack(struct snd_pcm_substream * substream)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
pcm_playback_ack(struct snd_pcm_substream * substream)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
snd_ff_create_pcm_devices(struct snd_ff * ff)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