Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/dice/dice-pcm.c
26451 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* dice_pcm.c - a part of driver for DICE based devices
4
*
5
* Copyright (c) Clemens Ladisch <[email protected]>
6
* Copyright (c) 2014 Takashi Sakamoto <[email protected]>
7
*/
8
9
#include "dice.h"
10
11
static int dice_rate_constraint(struct snd_pcm_hw_params *params,
12
struct snd_pcm_hw_rule *rule)
13
{
14
struct snd_pcm_substream *substream = rule->private;
15
struct snd_dice *dice = substream->private_data;
16
unsigned int index = substream->pcm->device;
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 *pcm_channels;
26
enum snd_dice_rate_mode mode;
27
unsigned int i, rate;
28
29
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
30
pcm_channels = dice->tx_pcm_chs[index];
31
else
32
pcm_channels = dice->rx_pcm_chs[index];
33
34
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
35
rate = snd_dice_rates[i];
36
if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
37
continue;
38
39
if (!snd_interval_test(c, pcm_channels[mode]))
40
continue;
41
42
rates.min = min(rates.min, rate);
43
rates.max = max(rates.max, rate);
44
}
45
46
return snd_interval_refine(r, &rates);
47
}
48
49
static int dice_channels_constraint(struct snd_pcm_hw_params *params,
50
struct snd_pcm_hw_rule *rule)
51
{
52
struct snd_pcm_substream *substream = rule->private;
53
struct snd_dice *dice = substream->private_data;
54
unsigned int index = substream->pcm->device;
55
56
const struct snd_interval *r =
57
hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
58
struct snd_interval *c =
59
hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
60
struct snd_interval channels = {
61
.min = UINT_MAX, .max = 0, .integer = 1
62
};
63
unsigned int *pcm_channels;
64
enum snd_dice_rate_mode mode;
65
unsigned int i, rate;
66
67
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
68
pcm_channels = dice->tx_pcm_chs[index];
69
else
70
pcm_channels = dice->rx_pcm_chs[index];
71
72
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
73
rate = snd_dice_rates[i];
74
if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
75
continue;
76
77
if (!snd_interval_test(r, rate))
78
continue;
79
80
channels.min = min(channels.min, pcm_channels[mode]);
81
channels.max = max(channels.max, pcm_channels[mode]);
82
}
83
84
return snd_interval_refine(c, &channels);
85
}
86
87
static int limit_channels_and_rates(struct snd_dice *dice,
88
struct snd_pcm_runtime *runtime,
89
enum amdtp_stream_direction dir,
90
unsigned int index)
91
{
92
struct snd_pcm_hardware *hw = &runtime->hw;
93
unsigned int *pcm_channels;
94
unsigned int i;
95
96
if (dir == AMDTP_IN_STREAM)
97
pcm_channels = dice->tx_pcm_chs[index];
98
else
99
pcm_channels = dice->rx_pcm_chs[index];
100
101
hw->channels_min = UINT_MAX;
102
hw->channels_max = 0;
103
104
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
105
enum snd_dice_rate_mode mode;
106
unsigned int rate, channels;
107
108
rate = snd_dice_rates[i];
109
if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
110
continue;
111
hw->rates |= snd_pcm_rate_to_rate_bit(rate);
112
113
channels = pcm_channels[mode];
114
if (channels == 0)
115
continue;
116
hw->channels_min = min(hw->channels_min, channels);
117
hw->channels_max = max(hw->channels_max, channels);
118
}
119
120
snd_pcm_limit_hw_rates(runtime);
121
122
return 0;
123
}
124
125
static int init_hw_info(struct snd_dice *dice,
126
struct snd_pcm_substream *substream)
127
{
128
struct snd_pcm_runtime *runtime = substream->runtime;
129
struct snd_pcm_hardware *hw = &runtime->hw;
130
unsigned int index = substream->pcm->device;
131
enum amdtp_stream_direction dir;
132
struct amdtp_stream *stream;
133
int err;
134
135
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
136
hw->formats = AM824_IN_PCM_FORMAT_BITS;
137
dir = AMDTP_IN_STREAM;
138
stream = &dice->tx_stream[index];
139
} else {
140
hw->formats = AM824_OUT_PCM_FORMAT_BITS;
141
dir = AMDTP_OUT_STREAM;
142
stream = &dice->rx_stream[index];
143
}
144
145
err = limit_channels_and_rates(dice, substream->runtime, dir,
146
index);
147
if (err < 0)
148
return err;
149
150
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
151
dice_rate_constraint, substream,
152
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
153
if (err < 0)
154
return err;
155
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
156
dice_channels_constraint, substream,
157
SNDRV_PCM_HW_PARAM_RATE, -1);
158
if (err < 0)
159
return err;
160
161
return amdtp_am824_add_pcm_hw_constraints(stream, runtime);
162
}
163
164
static int pcm_open(struct snd_pcm_substream *substream)
165
{
166
struct snd_dice *dice = substream->private_data;
167
struct amdtp_domain *d = &dice->domain;
168
unsigned int source;
169
bool internal;
170
int err;
171
172
err = snd_dice_stream_lock_try(dice);
173
if (err < 0)
174
return err;
175
176
err = init_hw_info(dice, substream);
177
if (err < 0)
178
goto err_locked;
179
180
err = snd_dice_transaction_get_clock_source(dice, &source);
181
if (err < 0)
182
goto err_locked;
183
switch (source) {
184
case CLOCK_SOURCE_AES1:
185
case CLOCK_SOURCE_AES2:
186
case CLOCK_SOURCE_AES3:
187
case CLOCK_SOURCE_AES4:
188
case CLOCK_SOURCE_AES_ANY:
189
case CLOCK_SOURCE_ADAT:
190
case CLOCK_SOURCE_TDIF:
191
case CLOCK_SOURCE_WC:
192
internal = false;
193
break;
194
default:
195
internal = true;
196
break;
197
}
198
199
mutex_lock(&dice->mutex);
200
201
// When source of clock is not internal or any stream is reserved for
202
// transmission of PCM frames, the available sampling rate is limited
203
// at current one.
204
if (!internal ||
205
(dice->substreams_counter > 0 && d->events_per_period > 0)) {
206
unsigned int frames_per_period = d->events_per_period;
207
unsigned int frames_per_buffer = d->events_per_buffer;
208
unsigned int rate;
209
210
err = snd_dice_transaction_get_rate(dice, &rate);
211
if (err < 0) {
212
mutex_unlock(&dice->mutex);
213
goto err_locked;
214
}
215
216
substream->runtime->hw.rate_min = rate;
217
substream->runtime->hw.rate_max = rate;
218
219
if (frames_per_period > 0) {
220
// For double_pcm_frame quirk.
221
if (rate > 96000 && !dice->disable_double_pcm_frames) {
222
frames_per_period *= 2;
223
frames_per_buffer *= 2;
224
}
225
226
err = snd_pcm_hw_constraint_minmax(substream->runtime,
227
SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
228
frames_per_period, frames_per_period);
229
if (err < 0) {
230
mutex_unlock(&dice->mutex);
231
goto err_locked;
232
}
233
234
err = snd_pcm_hw_constraint_minmax(substream->runtime,
235
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
236
frames_per_buffer, frames_per_buffer);
237
if (err < 0) {
238
mutex_unlock(&dice->mutex);
239
goto err_locked;
240
}
241
}
242
}
243
244
mutex_unlock(&dice->mutex);
245
246
snd_pcm_set_sync(substream);
247
248
return 0;
249
err_locked:
250
snd_dice_stream_lock_release(dice);
251
return err;
252
}
253
254
static int pcm_close(struct snd_pcm_substream *substream)
255
{
256
struct snd_dice *dice = substream->private_data;
257
258
snd_dice_stream_lock_release(dice);
259
260
return 0;
261
}
262
263
static int pcm_hw_params(struct snd_pcm_substream *substream,
264
struct snd_pcm_hw_params *hw_params)
265
{
266
struct snd_dice *dice = substream->private_data;
267
int err = 0;
268
269
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
270
unsigned int rate = params_rate(hw_params);
271
unsigned int events_per_period = params_period_size(hw_params);
272
unsigned int events_per_buffer = params_buffer_size(hw_params);
273
274
mutex_lock(&dice->mutex);
275
// For double_pcm_frame quirk.
276
if (rate > 96000 && !dice->disable_double_pcm_frames) {
277
events_per_period /= 2;
278
events_per_buffer /= 2;
279
}
280
err = snd_dice_stream_reserve_duplex(dice, rate,
281
events_per_period, events_per_buffer);
282
if (err >= 0)
283
++dice->substreams_counter;
284
mutex_unlock(&dice->mutex);
285
}
286
287
return err;
288
}
289
290
static int pcm_hw_free(struct snd_pcm_substream *substream)
291
{
292
struct snd_dice *dice = substream->private_data;
293
294
mutex_lock(&dice->mutex);
295
296
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
297
--dice->substreams_counter;
298
299
snd_dice_stream_stop_duplex(dice);
300
301
mutex_unlock(&dice->mutex);
302
303
return 0;
304
}
305
306
static int capture_prepare(struct snd_pcm_substream *substream)
307
{
308
struct snd_dice *dice = substream->private_data;
309
struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
310
int err;
311
312
mutex_lock(&dice->mutex);
313
err = snd_dice_stream_start_duplex(dice);
314
mutex_unlock(&dice->mutex);
315
if (err >= 0)
316
amdtp_stream_pcm_prepare(stream);
317
318
return 0;
319
}
320
static int playback_prepare(struct snd_pcm_substream *substream)
321
{
322
struct snd_dice *dice = substream->private_data;
323
struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
324
int err;
325
326
mutex_lock(&dice->mutex);
327
err = snd_dice_stream_start_duplex(dice);
328
mutex_unlock(&dice->mutex);
329
if (err >= 0)
330
amdtp_stream_pcm_prepare(stream);
331
332
return err;
333
}
334
335
static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
336
{
337
struct snd_dice *dice = substream->private_data;
338
struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
339
340
switch (cmd) {
341
case SNDRV_PCM_TRIGGER_START:
342
amdtp_stream_pcm_trigger(stream, substream);
343
break;
344
case SNDRV_PCM_TRIGGER_STOP:
345
amdtp_stream_pcm_trigger(stream, NULL);
346
break;
347
default:
348
return -EINVAL;
349
}
350
351
return 0;
352
}
353
static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
354
{
355
struct snd_dice *dice = substream->private_data;
356
struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
357
358
switch (cmd) {
359
case SNDRV_PCM_TRIGGER_START:
360
amdtp_stream_pcm_trigger(stream, substream);
361
break;
362
case SNDRV_PCM_TRIGGER_STOP:
363
amdtp_stream_pcm_trigger(stream, NULL);
364
break;
365
default:
366
return -EINVAL;
367
}
368
369
return 0;
370
}
371
372
static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
373
{
374
struct snd_dice *dice = substream->private_data;
375
struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
376
377
return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
378
}
379
static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
380
{
381
struct snd_dice *dice = substream->private_data;
382
struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
383
384
return amdtp_domain_stream_pcm_pointer(&dice->domain, stream);
385
}
386
387
static int capture_ack(struct snd_pcm_substream *substream)
388
{
389
struct snd_dice *dice = substream->private_data;
390
struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
391
392
return amdtp_domain_stream_pcm_ack(&dice->domain, stream);
393
}
394
395
static int playback_ack(struct snd_pcm_substream *substream)
396
{
397
struct snd_dice *dice = substream->private_data;
398
struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
399
400
return amdtp_domain_stream_pcm_ack(&dice->domain, stream);
401
}
402
403
int snd_dice_create_pcm(struct snd_dice *dice)
404
{
405
static const struct snd_pcm_ops capture_ops = {
406
.open = pcm_open,
407
.close = pcm_close,
408
.hw_params = pcm_hw_params,
409
.hw_free = pcm_hw_free,
410
.prepare = capture_prepare,
411
.trigger = capture_trigger,
412
.pointer = capture_pointer,
413
.ack = capture_ack,
414
};
415
static const struct snd_pcm_ops playback_ops = {
416
.open = pcm_open,
417
.close = pcm_close,
418
.hw_params = pcm_hw_params,
419
.hw_free = pcm_hw_free,
420
.prepare = playback_prepare,
421
.trigger = playback_trigger,
422
.pointer = playback_pointer,
423
.ack = playback_ack,
424
};
425
struct snd_pcm *pcm;
426
unsigned int capture, playback;
427
int i, j;
428
int err;
429
430
for (i = 0; i < MAX_STREAMS; i++) {
431
capture = playback = 0;
432
for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
433
if (dice->tx_pcm_chs[i][j] > 0)
434
capture = 1;
435
if (dice->rx_pcm_chs[i][j] > 0)
436
playback = 1;
437
}
438
439
err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
440
&pcm);
441
if (err < 0)
442
return err;
443
pcm->private_data = dice;
444
pcm->nonatomic = true;
445
strscpy(pcm->name, dice->card->shortname);
446
447
if (capture > 0)
448
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
449
&capture_ops);
450
451
if (playback > 0)
452
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
453
&playback_ops);
454
455
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
456
NULL, 0, 0);
457
}
458
459
return 0;
460
}
461
462