arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / firewire / digi00x / digi00x-pcm.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * digi00x-pcm.c - a part of driver for Digidesign Digi 002/003 family
4  *
5  * Copyright (c) 2014-2015 Takashi Sakamoto
6  */
7
8 #include "digi00x.h"
9
10 static int hw_rule_rate(struct snd_pcm_hw_params *params,
11                         struct snd_pcm_hw_rule *rule)
12 {
13         struct snd_interval *r =
14                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
15         const struct snd_interval *c =
16                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
17         struct snd_interval t = {
18                 .min = UINT_MAX, .max = 0, .integer = 1,
19         };
20         unsigned int i;
21
22         for (i = 0; i < SND_DG00X_RATE_COUNT; i++) {
23                 if (!snd_interval_test(c,
24                                        snd_dg00x_stream_pcm_channels[i]))
25                         continue;
26
27                 t.min = min(t.min, snd_dg00x_stream_rates[i]);
28                 t.max = max(t.max, snd_dg00x_stream_rates[i]);
29         }
30
31         return snd_interval_refine(r, &t);
32 }
33
34 static int hw_rule_channels(struct snd_pcm_hw_params *params,
35                             struct snd_pcm_hw_rule *rule)
36 {
37         struct snd_interval *c =
38                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
39         const struct snd_interval *r =
40                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
41         struct snd_interval t = {
42                 .min = UINT_MAX, .max = 0, .integer = 1,
43         };
44         unsigned int i;
45
46         for (i = 0; i < SND_DG00X_RATE_COUNT; i++) {
47                 if (!snd_interval_test(r, snd_dg00x_stream_rates[i]))
48                         continue;
49
50                 t.min = min(t.min, snd_dg00x_stream_pcm_channels[i]);
51                 t.max = max(t.max, snd_dg00x_stream_pcm_channels[i]);
52         }
53
54         return snd_interval_refine(c, &t);
55 }
56
57 static int pcm_init_hw_params(struct snd_dg00x *dg00x,
58                               struct snd_pcm_substream *substream)
59 {
60         struct snd_pcm_runtime *runtime = substream->runtime;
61         struct snd_pcm_hardware *hw = &runtime->hw;
62         struct amdtp_stream *s;
63         int err;
64
65
66         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
67                 substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
68                 s = &dg00x->tx_stream;
69         } else {
70                 substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
71                 s = &dg00x->rx_stream;
72         }
73
74         hw->channels_min = 10;
75         hw->channels_max = 18;
76
77         hw->rates = SNDRV_PCM_RATE_44100 |
78                     SNDRV_PCM_RATE_48000 |
79                     SNDRV_PCM_RATE_88200 |
80                     SNDRV_PCM_RATE_96000;
81         snd_pcm_limit_hw_rates(runtime);
82
83         err = snd_pcm_hw_rule_add(substream->runtime, 0,
84                                   SNDRV_PCM_HW_PARAM_CHANNELS,
85                                   hw_rule_channels, NULL,
86                                   SNDRV_PCM_HW_PARAM_RATE, -1);
87         if (err < 0)
88                 return err;
89
90         err = snd_pcm_hw_rule_add(substream->runtime, 0,
91                                   SNDRV_PCM_HW_PARAM_RATE,
92                                   hw_rule_rate, NULL,
93                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
94         if (err < 0)
95                 return err;
96
97         return amdtp_dot_add_pcm_hw_constraints(s, substream->runtime);
98 }
99
100 static int pcm_open(struct snd_pcm_substream *substream)
101 {
102         struct snd_dg00x *dg00x = substream->private_data;
103         struct amdtp_domain *d = &dg00x->domain;
104         enum snd_dg00x_clock clock;
105         bool detect;
106         int err;
107
108         err = snd_dg00x_stream_lock_try(dg00x);
109         if (err < 0)
110                 return err;
111
112         err = pcm_init_hw_params(dg00x, substream);
113         if (err < 0)
114                 goto err_locked;
115
116         /* Check current clock source. */
117         err = snd_dg00x_stream_get_clock(dg00x, &clock);
118         if (err < 0)
119                 goto err_locked;
120         if (clock != SND_DG00X_CLOCK_INTERNAL) {
121                 err = snd_dg00x_stream_check_external_clock(dg00x, &detect);
122                 if (err < 0)
123                         goto err_locked;
124                 if (!detect) {
125                         err = -EBUSY;
126                         goto err_locked;
127                 }
128         }
129
130         mutex_lock(&dg00x->mutex);
131
132         // When source of clock is not internal or any stream is reserved for
133         // transmission of PCM frames, the available sampling rate is limited
134         // at current one.
135         if ((clock != SND_DG00X_CLOCK_INTERNAL) ||
136             (dg00x->substreams_counter > 0 && d->events_per_period > 0)) {
137                 unsigned int frames_per_period = d->events_per_period;
138                 unsigned int frames_per_buffer = d->events_per_buffer;
139                 unsigned int rate;
140
141                 err = snd_dg00x_stream_get_external_rate(dg00x, &rate);
142                 if (err < 0) {
143                         mutex_unlock(&dg00x->mutex);
144                         goto err_locked;
145                 }
146                 substream->runtime->hw.rate_min = rate;
147                 substream->runtime->hw.rate_max = rate;
148
149                 if (frames_per_period > 0) {
150                         err = snd_pcm_hw_constraint_minmax(substream->runtime,
151                                         SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
152                                         frames_per_period, frames_per_period);
153                         if (err < 0) {
154                                 mutex_unlock(&dg00x->mutex);
155                                 goto err_locked;
156                         }
157
158                         err = snd_pcm_hw_constraint_minmax(substream->runtime,
159                                         SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
160                                         frames_per_buffer, frames_per_buffer);
161                         if (err < 0) {
162                                 mutex_unlock(&dg00x->mutex);
163                                 goto err_locked;
164                         }
165                 }
166         }
167
168         mutex_unlock(&dg00x->mutex);
169
170         snd_pcm_set_sync(substream);
171
172         return 0;
173 err_locked:
174         snd_dg00x_stream_lock_release(dg00x);
175         return err;
176 }
177
178 static int pcm_close(struct snd_pcm_substream *substream)
179 {
180         struct snd_dg00x *dg00x = substream->private_data;
181
182         snd_dg00x_stream_lock_release(dg00x);
183
184         return 0;
185 }
186
187 static int pcm_hw_params(struct snd_pcm_substream *substream,
188                          struct snd_pcm_hw_params *hw_params)
189 {
190         struct snd_dg00x *dg00x = substream->private_data;
191         int err = 0;
192
193         if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
194                 unsigned int rate = params_rate(hw_params);
195                 unsigned int frames_per_period = params_period_size(hw_params);
196                 unsigned int frames_per_buffer = params_buffer_size(hw_params);
197
198                 mutex_lock(&dg00x->mutex);
199                 err = snd_dg00x_stream_reserve_duplex(dg00x, rate,
200                                         frames_per_period, frames_per_buffer);
201                 if (err >= 0)
202                         ++dg00x->substreams_counter;
203                 mutex_unlock(&dg00x->mutex);
204         }
205
206         return err;
207 }
208
209 static int pcm_hw_free(struct snd_pcm_substream *substream)
210 {
211         struct snd_dg00x *dg00x = substream->private_data;
212
213         mutex_lock(&dg00x->mutex);
214
215         if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
216                 --dg00x->substreams_counter;
217
218         snd_dg00x_stream_stop_duplex(dg00x);
219
220         mutex_unlock(&dg00x->mutex);
221
222         return 0;
223 }
224
225 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
226 {
227         struct snd_dg00x *dg00x = substream->private_data;
228         int err;
229
230         mutex_lock(&dg00x->mutex);
231
232         err = snd_dg00x_stream_start_duplex(dg00x);
233         if (err >= 0)
234                 amdtp_stream_pcm_prepare(&dg00x->tx_stream);
235
236         mutex_unlock(&dg00x->mutex);
237
238         return err;
239 }
240
241 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
242 {
243         struct snd_dg00x *dg00x = substream->private_data;
244         int err;
245
246         mutex_lock(&dg00x->mutex);
247
248         err = snd_dg00x_stream_start_duplex(dg00x);
249         if (err >= 0) {
250                 amdtp_stream_pcm_prepare(&dg00x->rx_stream);
251                 amdtp_dot_reset(&dg00x->rx_stream);
252         }
253
254         mutex_unlock(&dg00x->mutex);
255
256         return err;
257 }
258
259 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
260 {
261         struct snd_dg00x *dg00x = substream->private_data;
262
263         switch (cmd) {
264         case SNDRV_PCM_TRIGGER_START:
265                 amdtp_stream_pcm_trigger(&dg00x->tx_stream, substream);
266                 break;
267         case SNDRV_PCM_TRIGGER_STOP:
268                 amdtp_stream_pcm_trigger(&dg00x->tx_stream, NULL);
269                 break;
270         default:
271                 return -EINVAL;
272         }
273
274         return 0;
275 }
276
277 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
278 {
279         struct snd_dg00x *dg00x = substream->private_data;
280
281         switch (cmd) {
282         case SNDRV_PCM_TRIGGER_START:
283                 amdtp_stream_pcm_trigger(&dg00x->rx_stream, substream);
284                 break;
285         case SNDRV_PCM_TRIGGER_STOP:
286                 amdtp_stream_pcm_trigger(&dg00x->rx_stream, NULL);
287                 break;
288         default:
289                 return -EINVAL;
290         }
291
292         return 0;
293 }
294
295 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
296 {
297         struct snd_dg00x *dg00x = sbstrm->private_data;
298
299         return amdtp_domain_stream_pcm_pointer(&dg00x->domain, &dg00x->tx_stream);
300 }
301
302 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
303 {
304         struct snd_dg00x *dg00x = sbstrm->private_data;
305
306         return amdtp_domain_stream_pcm_pointer(&dg00x->domain, &dg00x->rx_stream);
307 }
308
309 static int pcm_capture_ack(struct snd_pcm_substream *substream)
310 {
311         struct snd_dg00x *dg00x = substream->private_data;
312
313         return amdtp_domain_stream_pcm_ack(&dg00x->domain, &dg00x->tx_stream);
314 }
315
316 static int pcm_playback_ack(struct snd_pcm_substream *substream)
317 {
318         struct snd_dg00x *dg00x = substream->private_data;
319
320         return amdtp_domain_stream_pcm_ack(&dg00x->domain, &dg00x->rx_stream);
321 }
322
323 int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
324 {
325         static const struct snd_pcm_ops capture_ops = {
326                 .open           = pcm_open,
327                 .close          = pcm_close,
328                 .hw_params      = pcm_hw_params,
329                 .hw_free        = pcm_hw_free,
330                 .prepare        = pcm_capture_prepare,
331                 .trigger        = pcm_capture_trigger,
332                 .pointer        = pcm_capture_pointer,
333                 .ack            = pcm_capture_ack,
334         };
335         static const struct snd_pcm_ops playback_ops = {
336                 .open           = pcm_open,
337                 .close          = pcm_close,
338                 .hw_params      = pcm_hw_params,
339                 .hw_free        = pcm_hw_free,
340                 .prepare        = pcm_playback_prepare,
341                 .trigger        = pcm_playback_trigger,
342                 .pointer        = pcm_playback_pointer,
343                 .ack            = pcm_playback_ack,
344         };
345         struct snd_pcm *pcm;
346         int err;
347
348         err = snd_pcm_new(dg00x->card, dg00x->card->driver, 0, 1, 1, &pcm);
349         if (err < 0)
350                 return err;
351
352         pcm->private_data = dg00x;
353         snprintf(pcm->name, sizeof(pcm->name),
354                  "%s PCM", dg00x->card->shortname);
355         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
356         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
357         snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
358
359         return 0;
360 }