Linux-libre 4.19.8-gnu
[librecmc/linux-libre.git] / sound / firewire / fireface / ff-pcm.c
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         };
387         struct snd_pcm *pcm;
388         int err;
389
390         err = snd_pcm_new(ff->card, ff->card->driver, 0, 1, 1, &pcm);
391         if (err < 0)
392                 return err;
393
394         pcm->private_data = ff;
395         snprintf(pcm->name, sizeof(pcm->name),
396                  "%s PCM", ff->card->shortname);
397         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
398         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
399
400         return 0;
401 }