treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 345
[linux-2.6-block.git] / sound / firewire / bebob / bebob_pcm.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * bebob_pcm.c - a part of driver for BeBoB based devices
4  *
5  * Copyright (c) 2013-2014 Takashi Sakamoto
6  */
7
8 #include "./bebob.h"
9
10 static int
11 hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
12 {
13         struct snd_bebob_stream_formation *formations = rule->private;
14         struct snd_interval *r =
15                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
16         const struct snd_interval *c =
17                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
18         struct snd_interval t = {
19                 .min = UINT_MAX, .max = 0, .integer = 1
20         };
21         unsigned int i;
22
23         for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
24                 /* entry is invalid */
25                 if (formations[i].pcm == 0)
26                         continue;
27
28                 if (!snd_interval_test(c, formations[i].pcm))
29                         continue;
30
31                 t.min = min(t.min, snd_bebob_rate_table[i]);
32                 t.max = max(t.max, snd_bebob_rate_table[i]);
33
34         }
35         return snd_interval_refine(r, &t);
36 }
37
38 static int
39 hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
40 {
41         struct snd_bebob_stream_formation *formations = rule->private;
42         struct snd_interval *c =
43                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
44         const struct snd_interval *r =
45                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
46         struct snd_interval t = {
47                 .min = UINT_MAX, .max = 0, .integer = 1
48         };
49
50         unsigned int i;
51
52         for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
53                 /* entry is invalid */
54                 if (formations[i].pcm == 0)
55                         continue;
56
57                 if (!snd_interval_test(r, snd_bebob_rate_table[i]))
58                         continue;
59
60                 t.min = min(t.min, formations[i].pcm);
61                 t.max = max(t.max, formations[i].pcm);
62         }
63
64         return snd_interval_refine(c, &t);
65 }
66
67 static void
68 limit_channels_and_rates(struct snd_pcm_hardware *hw,
69                          struct snd_bebob_stream_formation *formations)
70 {
71         unsigned int i;
72
73         hw->channels_min = UINT_MAX;
74         hw->channels_max = 0;
75
76         hw->rate_min = UINT_MAX;
77         hw->rate_max = 0;
78         hw->rates = 0;
79
80         for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
81                 /* entry has no PCM channels */
82                 if (formations[i].pcm == 0)
83                         continue;
84
85                 hw->channels_min = min(hw->channels_min, formations[i].pcm);
86                 hw->channels_max = max(hw->channels_max, formations[i].pcm);
87
88                 hw->rate_min = min(hw->rate_min, snd_bebob_rate_table[i]);
89                 hw->rate_max = max(hw->rate_max, snd_bebob_rate_table[i]);
90                 hw->rates |= snd_pcm_rate_to_rate_bit(snd_bebob_rate_table[i]);
91         }
92 }
93
94 static int
95 pcm_init_hw_params(struct snd_bebob *bebob,
96                    struct snd_pcm_substream *substream)
97 {
98         struct snd_pcm_runtime *runtime = substream->runtime;
99         struct amdtp_stream *s;
100         struct snd_bebob_stream_formation *formations;
101         int err;
102
103         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
104                 runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS;
105                 s = &bebob->tx_stream;
106                 formations = bebob->tx_stream_formations;
107         } else {
108                 runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS;
109                 s = &bebob->rx_stream;
110                 formations = bebob->rx_stream_formations;
111         }
112
113         limit_channels_and_rates(&runtime->hw, formations);
114
115         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
116                                   hw_rule_channels, formations,
117                                   SNDRV_PCM_HW_PARAM_RATE, -1);
118         if (err < 0)
119                 goto end;
120
121         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
122                                   hw_rule_rate, formations,
123                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
124         if (err < 0)
125                 goto end;
126
127         err = amdtp_am824_add_pcm_hw_constraints(s, runtime);
128 end:
129         return err;
130 }
131
132 static int
133 pcm_open(struct snd_pcm_substream *substream)
134 {
135         struct snd_bebob *bebob = substream->private_data;
136         const struct snd_bebob_rate_spec *spec = bebob->spec->rate;
137         unsigned int sampling_rate;
138         enum snd_bebob_clock_type src;
139         int err;
140
141         err = snd_bebob_stream_lock_try(bebob);
142         if (err < 0)
143                 goto end;
144
145         err = pcm_init_hw_params(bebob, substream);
146         if (err < 0)
147                 goto err_locked;
148
149         err = snd_bebob_stream_get_clock_src(bebob, &src);
150         if (err < 0)
151                 goto err_locked;
152
153         /*
154          * When source of clock is internal or any PCM stream are running,
155          * the available sampling rate is limited at current sampling rate.
156          */
157         if (src == SND_BEBOB_CLOCK_TYPE_EXTERNAL ||
158             amdtp_stream_pcm_running(&bebob->tx_stream) ||
159             amdtp_stream_pcm_running(&bebob->rx_stream)) {
160                 err = spec->get(bebob, &sampling_rate);
161                 if (err < 0) {
162                         dev_err(&bebob->unit->device,
163                                 "fail to get sampling rate: %d\n", err);
164                         goto err_locked;
165                 }
166
167                 substream->runtime->hw.rate_min = sampling_rate;
168                 substream->runtime->hw.rate_max = sampling_rate;
169         }
170
171         snd_pcm_set_sync(substream);
172 end:
173         return err;
174 err_locked:
175         snd_bebob_stream_lock_release(bebob);
176         return err;
177 }
178
179 static int
180 pcm_close(struct snd_pcm_substream *substream)
181 {
182         struct snd_bebob *bebob = substream->private_data;
183         snd_bebob_stream_lock_release(bebob);
184         return 0;
185 }
186
187 static int
188 pcm_capture_hw_params(struct snd_pcm_substream *substream,
189                       struct snd_pcm_hw_params *hw_params)
190 {
191         struct snd_bebob *bebob = substream->private_data;
192         int err;
193
194         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
195                                                params_buffer_bytes(hw_params));
196         if (err < 0)
197                 return err;
198
199         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
200                 mutex_lock(&bebob->mutex);
201                 bebob->substreams_counter++;
202                 mutex_unlock(&bebob->mutex);
203         }
204
205         return 0;
206 }
207 static int
208 pcm_playback_hw_params(struct snd_pcm_substream *substream,
209                        struct snd_pcm_hw_params *hw_params)
210 {
211         struct snd_bebob *bebob = substream->private_data;
212         int err;
213
214         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
215                                                params_buffer_bytes(hw_params));
216         if (err < 0)
217                 return err;
218
219         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
220                 mutex_lock(&bebob->mutex);
221                 bebob->substreams_counter++;
222                 mutex_unlock(&bebob->mutex);
223         }
224
225         return 0;
226 }
227
228 static int
229 pcm_capture_hw_free(struct snd_pcm_substream *substream)
230 {
231         struct snd_bebob *bebob = substream->private_data;
232
233         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) {
234                 mutex_lock(&bebob->mutex);
235                 bebob->substreams_counter--;
236                 mutex_unlock(&bebob->mutex);
237         }
238
239         snd_bebob_stream_stop_duplex(bebob);
240
241         return snd_pcm_lib_free_vmalloc_buffer(substream);
242 }
243 static int
244 pcm_playback_hw_free(struct snd_pcm_substream *substream)
245 {
246         struct snd_bebob *bebob = substream->private_data;
247
248         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) {
249                 mutex_lock(&bebob->mutex);
250                 bebob->substreams_counter--;
251                 mutex_unlock(&bebob->mutex);
252         }
253
254         snd_bebob_stream_stop_duplex(bebob);
255
256         return snd_pcm_lib_free_vmalloc_buffer(substream);
257 }
258
259 static int
260 pcm_capture_prepare(struct snd_pcm_substream *substream)
261 {
262         struct snd_bebob *bebob = substream->private_data;
263         struct snd_pcm_runtime *runtime = substream->runtime;
264         int err;
265
266         err = snd_bebob_stream_start_duplex(bebob, runtime->rate);
267         if (err >= 0)
268                 amdtp_stream_pcm_prepare(&bebob->tx_stream);
269
270         return err;
271 }
272 static int
273 pcm_playback_prepare(struct snd_pcm_substream *substream)
274 {
275         struct snd_bebob *bebob = substream->private_data;
276         struct snd_pcm_runtime *runtime = substream->runtime;
277         int err;
278
279         err = snd_bebob_stream_start_duplex(bebob, runtime->rate);
280         if (err >= 0)
281                 amdtp_stream_pcm_prepare(&bebob->rx_stream);
282
283         return err;
284 }
285
286 static int
287 pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
288 {
289         struct snd_bebob *bebob = substream->private_data;
290
291         switch (cmd) {
292         case SNDRV_PCM_TRIGGER_START:
293                 amdtp_stream_pcm_trigger(&bebob->tx_stream, substream);
294                 break;
295         case SNDRV_PCM_TRIGGER_STOP:
296                 amdtp_stream_pcm_trigger(&bebob->tx_stream, NULL);
297                 break;
298         default:
299                 return -EINVAL;
300         }
301
302         return 0;
303 }
304 static int
305 pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
306 {
307         struct snd_bebob *bebob = substream->private_data;
308
309         switch (cmd) {
310         case SNDRV_PCM_TRIGGER_START:
311                 amdtp_stream_pcm_trigger(&bebob->rx_stream, substream);
312                 break;
313         case SNDRV_PCM_TRIGGER_STOP:
314                 amdtp_stream_pcm_trigger(&bebob->rx_stream, NULL);
315                 break;
316         default:
317                 return -EINVAL;
318         }
319
320         return 0;
321 }
322
323 static snd_pcm_uframes_t
324 pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
325 {
326         struct snd_bebob *bebob = sbstrm->private_data;
327         return amdtp_stream_pcm_pointer(&bebob->tx_stream);
328 }
329 static snd_pcm_uframes_t
330 pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
331 {
332         struct snd_bebob *bebob = sbstrm->private_data;
333         return amdtp_stream_pcm_pointer(&bebob->rx_stream);
334 }
335
336 static int pcm_capture_ack(struct snd_pcm_substream *substream)
337 {
338         struct snd_bebob *bebob = substream->private_data;
339
340         return amdtp_stream_pcm_ack(&bebob->tx_stream);
341 }
342
343 static int pcm_playback_ack(struct snd_pcm_substream *substream)
344 {
345         struct snd_bebob *bebob = substream->private_data;
346
347         return amdtp_stream_pcm_ack(&bebob->rx_stream);
348 }
349
350 int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
351 {
352         static const struct snd_pcm_ops capture_ops = {
353                 .open           = pcm_open,
354                 .close          = pcm_close,
355                 .ioctl          = snd_pcm_lib_ioctl,
356                 .hw_params      = pcm_capture_hw_params,
357                 .hw_free        = pcm_capture_hw_free,
358                 .prepare        = pcm_capture_prepare,
359                 .trigger        = pcm_capture_trigger,
360                 .pointer        = pcm_capture_pointer,
361                 .ack            = pcm_capture_ack,
362                 .page           = snd_pcm_lib_get_vmalloc_page,
363         };
364         static const struct snd_pcm_ops playback_ops = {
365                 .open           = pcm_open,
366                 .close          = pcm_close,
367                 .ioctl          = snd_pcm_lib_ioctl,
368                 .hw_params      = pcm_playback_hw_params,
369                 .hw_free        = pcm_playback_hw_free,
370                 .prepare        = pcm_playback_prepare,
371                 .trigger        = pcm_playback_trigger,
372                 .pointer        = pcm_playback_pointer,
373                 .ack            = pcm_playback_ack,
374                 .page           = snd_pcm_lib_get_vmalloc_page,
375         };
376         struct snd_pcm *pcm;
377         int err;
378
379         err = snd_pcm_new(bebob->card, bebob->card->driver, 0, 1, 1, &pcm);
380         if (err < 0)
381                 goto end;
382
383         pcm->private_data = bebob;
384         snprintf(pcm->name, sizeof(pcm->name),
385                  "%s PCM", bebob->card->shortname);
386         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
387         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
388 end:
389         return err;
390 }