]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - sound/firewire/dice/dice-pcm.c
Merge remote-tracking branch 'sound-current/for-linus'
[karo-tx-linux.git] / sound / firewire / dice / dice-pcm.c
1 /*
2  * dice_pcm.c - a part of driver for DICE based devices
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6  *
7  * Licensed under the terms of the GNU General Public License, version 2.
8  */
9
10 #include "dice.h"
11
12 static int dice_rate_constraint(struct snd_pcm_hw_params *params,
13                                 struct snd_pcm_hw_rule *rule)
14 {
15         struct snd_pcm_substream *substream = rule->private;
16         struct snd_dice *dice = substream->private_data;
17
18         const struct snd_interval *c =
19                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
20         struct snd_interval *r =
21                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
22         struct snd_interval rates = {
23                 .min = UINT_MAX, .max = 0, .integer = 1
24         };
25         unsigned int i, rate, mode, *pcm_channels;
26
27         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
28                 pcm_channels = dice->tx_channels;
29         else
30                 pcm_channels = dice->rx_channels;
31
32         for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
33                 rate = snd_dice_rates[i];
34                 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
35                         continue;
36
37                 if (!snd_interval_test(c, pcm_channels[mode]))
38                         continue;
39
40                 rates.min = min(rates.min, rate);
41                 rates.max = max(rates.max, rate);
42         }
43
44         return snd_interval_refine(r, &rates);
45 }
46
47 static int dice_channels_constraint(struct snd_pcm_hw_params *params,
48                                     struct snd_pcm_hw_rule *rule)
49 {
50         struct snd_pcm_substream *substream = rule->private;
51         struct snd_dice *dice = substream->private_data;
52
53         const struct snd_interval *r =
54                 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
55         struct snd_interval *c =
56                 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
57         struct snd_interval channels = {
58                 .min = UINT_MAX, .max = 0, .integer = 1
59         };
60         unsigned int i, rate, mode, *pcm_channels;
61
62         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
63                 pcm_channels = dice->tx_channels;
64         else
65                 pcm_channels = dice->rx_channels;
66
67         for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
68                 rate = snd_dice_rates[i];
69                 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
70                         continue;
71
72                 if (!snd_interval_test(r, rate))
73                         continue;
74
75                 channels.min = min(channels.min, pcm_channels[mode]);
76                 channels.max = max(channels.max, pcm_channels[mode]);
77         }
78
79         return snd_interval_refine(c, &channels);
80 }
81
82 static void limit_channels_and_rates(struct snd_dice *dice,
83                                      struct snd_pcm_runtime *runtime,
84                                      unsigned int *pcm_channels)
85 {
86         struct snd_pcm_hardware *hw = &runtime->hw;
87         unsigned int i, rate, mode;
88
89         hw->channels_min = UINT_MAX;
90         hw->channels_max = 0;
91
92         for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
93                 rate = snd_dice_rates[i];
94                 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
95                         continue;
96                 hw->rates |= snd_pcm_rate_to_rate_bit(rate);
97
98                 if (pcm_channels[mode] == 0)
99                         continue;
100                 hw->channels_min = min(hw->channels_min, pcm_channels[mode]);
101                 hw->channels_max = max(hw->channels_max, pcm_channels[mode]);
102         }
103
104         snd_pcm_limit_hw_rates(runtime);
105 }
106
107 static void limit_period_and_buffer(struct snd_pcm_hardware *hw)
108 {
109         hw->periods_min = 2;                    /* SNDRV_PCM_INFO_BATCH */
110         hw->periods_max = UINT_MAX;
111
112         hw->period_bytes_min = 4 * hw->channels_max;    /* byte for a frame */
113
114         /* Just to prevent from allocating much pages. */
115         hw->period_bytes_max = hw->period_bytes_min * 2048;
116         hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min;
117 }
118
119 static int init_hw_info(struct snd_dice *dice,
120                         struct snd_pcm_substream *substream)
121 {
122         struct snd_pcm_runtime *runtime = substream->runtime;
123         struct snd_pcm_hardware *hw = &runtime->hw;
124         struct amdtp_stream *stream;
125         unsigned int *pcm_channels;
126         int err;
127
128         hw->info = SNDRV_PCM_INFO_MMAP |
129                    SNDRV_PCM_INFO_MMAP_VALID |
130                    SNDRV_PCM_INFO_BATCH |
131                    SNDRV_PCM_INFO_INTERLEAVED |
132                    SNDRV_PCM_INFO_JOINT_DUPLEX |
133                    SNDRV_PCM_INFO_BLOCK_TRANSFER;
134
135         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
136                 hw->formats = AM824_IN_PCM_FORMAT_BITS;
137                 stream = &dice->tx_stream;
138                 pcm_channels = dice->tx_channels;
139         } else {
140                 hw->formats = AM824_OUT_PCM_FORMAT_BITS;
141                 stream = &dice->rx_stream;
142                 pcm_channels = dice->rx_channels;
143         }
144
145         limit_channels_and_rates(dice, runtime, pcm_channels);
146         limit_period_and_buffer(hw);
147
148         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
149                                   dice_rate_constraint, substream,
150                                   SNDRV_PCM_HW_PARAM_CHANNELS, -1);
151         if (err < 0)
152                 goto end;
153         err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
154                                   dice_channels_constraint, substream,
155                                   SNDRV_PCM_HW_PARAM_RATE, -1);
156         if (err < 0)
157                 goto end;
158
159         err = amdtp_am824_add_pcm_hw_constraints(stream, runtime);
160 end:
161         return err;
162 }
163
164 static int pcm_open(struct snd_pcm_substream *substream)
165 {
166         struct snd_dice *dice = substream->private_data;
167         unsigned int source, rate;
168         bool internal;
169         int err;
170
171         err = snd_dice_stream_lock_try(dice);
172         if (err < 0)
173                 goto end;
174
175         err = init_hw_info(dice, substream);
176         if (err < 0)
177                 goto err_locked;
178
179         err = snd_dice_transaction_get_clock_source(dice, &source);
180         if (err < 0)
181                 goto err_locked;
182         switch (source) {
183         case CLOCK_SOURCE_AES1:
184         case CLOCK_SOURCE_AES2:
185         case CLOCK_SOURCE_AES3:
186         case CLOCK_SOURCE_AES4:
187         case CLOCK_SOURCE_AES_ANY:
188         case CLOCK_SOURCE_ADAT:
189         case CLOCK_SOURCE_TDIF:
190         case CLOCK_SOURCE_WC:
191                 internal = false;
192                 break;
193         default:
194                 internal = true;
195                 break;
196         }
197
198         /*
199          * When source of clock is not internal or any PCM streams are running,
200          * available sampling rate is limited at current sampling rate.
201          */
202         if (!internal ||
203             amdtp_stream_pcm_running(&dice->tx_stream) ||
204             amdtp_stream_pcm_running(&dice->rx_stream)) {
205                 err = snd_dice_transaction_get_rate(dice, &rate);
206                 if (err < 0)
207                         goto err_locked;
208                 substream->runtime->hw.rate_min = rate;
209                 substream->runtime->hw.rate_max = rate;
210         }
211
212         snd_pcm_set_sync(substream);
213 end:
214         return err;
215 err_locked:
216         snd_dice_stream_lock_release(dice);
217         return err;
218 }
219
220 static int pcm_close(struct snd_pcm_substream *substream)
221 {
222         struct snd_dice *dice = substream->private_data;
223
224         snd_dice_stream_lock_release(dice);
225
226         return 0;
227 }
228
229 static int capture_hw_params(struct snd_pcm_substream *substream,
230                              struct snd_pcm_hw_params *hw_params)
231 {
232         struct snd_dice *dice = substream->private_data;
233         int err;
234
235         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
236                                                params_buffer_bytes(hw_params));
237         if (err < 0)
238                 return err;
239
240         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
241                 mutex_lock(&dice->mutex);
242                 dice->substreams_counter++;
243                 mutex_unlock(&dice->mutex);
244         }
245
246         amdtp_am824_set_pcm_format(&dice->tx_stream, params_format(hw_params));
247
248         return 0;
249 }
250 static int playback_hw_params(struct snd_pcm_substream *substream,
251                               struct snd_pcm_hw_params *hw_params)
252 {
253         struct snd_dice *dice = substream->private_data;
254         int err;
255
256         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
257                                                params_buffer_bytes(hw_params));
258         if (err < 0)
259                 return err;
260
261         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
262                 mutex_lock(&dice->mutex);
263                 dice->substreams_counter++;
264                 mutex_unlock(&dice->mutex);
265         }
266
267         amdtp_am824_set_pcm_format(&dice->rx_stream, params_format(hw_params));
268
269         return 0;
270 }
271
272 static int capture_hw_free(struct snd_pcm_substream *substream)
273 {
274         struct snd_dice *dice = substream->private_data;
275
276         mutex_lock(&dice->mutex);
277
278         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
279                 dice->substreams_counter--;
280
281         snd_dice_stream_stop_duplex(dice);
282
283         mutex_unlock(&dice->mutex);
284
285         return snd_pcm_lib_free_vmalloc_buffer(substream);
286 }
287
288 static int playback_hw_free(struct snd_pcm_substream *substream)
289 {
290         struct snd_dice *dice = substream->private_data;
291
292         mutex_lock(&dice->mutex);
293
294         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
295                 dice->substreams_counter--;
296
297         snd_dice_stream_stop_duplex(dice);
298
299         mutex_unlock(&dice->mutex);
300
301         return snd_pcm_lib_free_vmalloc_buffer(substream);
302 }
303
304 static int capture_prepare(struct snd_pcm_substream *substream)
305 {
306         struct snd_dice *dice = substream->private_data;
307         int err;
308
309         mutex_lock(&dice->mutex);
310         err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
311         mutex_unlock(&dice->mutex);
312         if (err >= 0)
313                 amdtp_stream_pcm_prepare(&dice->tx_stream);
314
315         return 0;
316 }
317 static int playback_prepare(struct snd_pcm_substream *substream)
318 {
319         struct snd_dice *dice = substream->private_data;
320         int err;
321
322         mutex_lock(&dice->mutex);
323         err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
324         mutex_unlock(&dice->mutex);
325         if (err >= 0)
326                 amdtp_stream_pcm_prepare(&dice->rx_stream);
327
328         return err;
329 }
330
331 static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
332 {
333         struct snd_dice *dice = substream->private_data;
334
335         switch (cmd) {
336         case SNDRV_PCM_TRIGGER_START:
337                 amdtp_stream_pcm_trigger(&dice->tx_stream, substream);
338                 break;
339         case SNDRV_PCM_TRIGGER_STOP:
340                 amdtp_stream_pcm_trigger(&dice->tx_stream, NULL);
341                 break;
342         default:
343                 return -EINVAL;
344         }
345
346         return 0;
347 }
348 static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
349 {
350         struct snd_dice *dice = substream->private_data;
351
352         switch (cmd) {
353         case SNDRV_PCM_TRIGGER_START:
354                 amdtp_stream_pcm_trigger(&dice->rx_stream, substream);
355                 break;
356         case SNDRV_PCM_TRIGGER_STOP:
357                 amdtp_stream_pcm_trigger(&dice->rx_stream, NULL);
358                 break;
359         default:
360                 return -EINVAL;
361         }
362
363         return 0;
364 }
365
366 static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
367 {
368         struct snd_dice *dice = substream->private_data;
369
370         return amdtp_stream_pcm_pointer(&dice->tx_stream);
371 }
372 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
373 {
374         struct snd_dice *dice = substream->private_data;
375
376         return amdtp_stream_pcm_pointer(&dice->rx_stream);
377 }
378
379 int snd_dice_create_pcm(struct snd_dice *dice)
380 {
381         static struct snd_pcm_ops capture_ops = {
382                 .open      = pcm_open,
383                 .close     = pcm_close,
384                 .ioctl     = snd_pcm_lib_ioctl,
385                 .hw_params = capture_hw_params,
386                 .hw_free   = capture_hw_free,
387                 .prepare   = capture_prepare,
388                 .trigger   = capture_trigger,
389                 .pointer   = capture_pointer,
390                 .page      = snd_pcm_lib_get_vmalloc_page,
391                 .mmap      = snd_pcm_lib_mmap_vmalloc,
392         };
393         static struct snd_pcm_ops playback_ops = {
394                 .open      = pcm_open,
395                 .close     = pcm_close,
396                 .ioctl     = snd_pcm_lib_ioctl,
397                 .hw_params = playback_hw_params,
398                 .hw_free   = playback_hw_free,
399                 .prepare   = playback_prepare,
400                 .trigger   = playback_trigger,
401                 .pointer   = playback_pointer,
402                 .page      = snd_pcm_lib_get_vmalloc_page,
403                 .mmap      = snd_pcm_lib_mmap_vmalloc,
404         };
405         struct snd_pcm *pcm;
406         unsigned int i, capture, playback;
407         int err;
408
409         capture = playback = 0;
410         for (i = 0; i < 3; i++) {
411                 if (dice->tx_channels[i] > 0)
412                         capture = 1;
413                 if (dice->rx_channels[i] > 0)
414                         playback = 1;
415         }
416
417         err = snd_pcm_new(dice->card, "DICE", 0, playback, capture, &pcm);
418         if (err < 0)
419                 return err;
420         pcm->private_data = dice;
421         strcpy(pcm->name, dice->card->shortname);
422
423         if (capture > 0)
424                 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
425
426         if (playback > 0)
427                 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
428
429         return 0;
430 }