Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/fireworks/fireworks_pcm.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* fireworks_pcm.c - a part of driver for Fireworks based devices
4
*
5
* Copyright (c) 2009-2010 Clemens Ladisch
6
* Copyright (c) 2013-2014 Takashi Sakamoto
7
*/
8
#include "./fireworks.h"
9
10
/*
11
* NOTE:
12
* Fireworks changes its AMDTP channels for PCM data according to its sampling
13
* rate. There are three modes. Here _XX is either _rx or _tx.
14
* 0: 32.0- 48.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels applied
15
* 1: 88.2- 96.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels_2x applied
16
* 2: 176.4-192.0 kHz then snd_efw_hwinfo.amdtp_XX_pcm_channels_4x applied
17
*
18
* The number of PCM channels for analog input and output are always fixed but
19
* the number of PCM channels for digital input and output are differed.
20
*
21
* Additionally, according to "AudioFire Owner's Manual Version 2.2", in some
22
* model, the number of PCM channels for digital input has more restriction
23
* depending on which digital interface is selected.
24
* - S/PDIF coaxial and optical : use input 1-2
25
* - ADAT optical at 32.0-48.0 kHz : use input 1-8
26
* - ADAT optical at 88.2-96.0 kHz : use input 1-4 (S/MUX format)
27
*
28
* The data in AMDTP channels for blank PCM channels are zero.
29
*/
30
static const unsigned int freq_table[] = {
31
/* multiplier mode 0 */
32
[0] = 32000,
33
[1] = 44100,
34
[2] = 48000,
35
/* multiplier mode 1 */
36
[3] = 88200,
37
[4] = 96000,
38
/* multiplier mode 2 */
39
[5] = 176400,
40
[6] = 192000,
41
};
42
43
static inline unsigned int
44
get_multiplier_mode_with_index(unsigned int index)
45
{
46
return ((int)index - 1) / 2;
47
}
48
49
int snd_efw_get_multiplier_mode(unsigned int sampling_rate, unsigned int *mode)
50
{
51
unsigned int i;
52
53
for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
54
if (freq_table[i] == sampling_rate) {
55
*mode = get_multiplier_mode_with_index(i);
56
return 0;
57
}
58
}
59
60
return -EINVAL;
61
}
62
63
static int
64
hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
65
{
66
unsigned int *pcm_channels = rule->private;
67
struct snd_interval *r =
68
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
69
const struct snd_interval *c =
70
hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
71
struct snd_interval t = {
72
.min = UINT_MAX, .max = 0, .integer = 1
73
};
74
unsigned int i, mode;
75
76
for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
77
mode = get_multiplier_mode_with_index(i);
78
if (!snd_interval_test(c, pcm_channels[mode]))
79
continue;
80
81
t.min = min(t.min, freq_table[i]);
82
t.max = max(t.max, freq_table[i]);
83
}
84
85
return snd_interval_refine(r, &t);
86
}
87
88
static int
89
hw_rule_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
90
{
91
unsigned int *pcm_channels = rule->private;
92
struct snd_interval *c =
93
hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
94
const struct snd_interval *r =
95
hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
96
struct snd_interval t = {
97
.min = UINT_MAX, .max = 0, .integer = 1
98
};
99
unsigned int i, mode;
100
101
for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
102
mode = get_multiplier_mode_with_index(i);
103
if (!snd_interval_test(r, freq_table[i]))
104
continue;
105
106
t.min = min(t.min, pcm_channels[mode]);
107
t.max = max(t.max, pcm_channels[mode]);
108
}
109
110
return snd_interval_refine(c, &t);
111
}
112
113
static void
114
limit_channels(struct snd_pcm_hardware *hw, unsigned int *pcm_channels)
115
{
116
unsigned int i, mode;
117
118
hw->channels_min = UINT_MAX;
119
hw->channels_max = 0;
120
121
for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
122
mode = get_multiplier_mode_with_index(i);
123
if (pcm_channels[mode] == 0)
124
continue;
125
126
hw->channels_min = min(hw->channels_min, pcm_channels[mode]);
127
hw->channels_max = max(hw->channels_max, pcm_channels[mode]);
128
}
129
}
130
131
static int
132
pcm_init_hw_params(struct snd_efw *efw,
133
struct snd_pcm_substream *substream)
134
{
135
struct snd_pcm_runtime *runtime = substream->runtime;
136
struct amdtp_stream *s;
137
unsigned int *pcm_channels;
138
int err;
139
140
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
141
runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS;
142
s = &efw->tx_stream;
143
pcm_channels = efw->pcm_capture_channels;
144
} else {
145
runtime->hw.formats = AM824_OUT_PCM_FORMAT_BITS;
146
s = &efw->rx_stream;
147
pcm_channels = efw->pcm_playback_channels;
148
}
149
150
/* limit rates */
151
runtime->hw.rates = efw->supported_sampling_rate;
152
snd_pcm_limit_hw_rates(runtime);
153
154
limit_channels(&runtime->hw, pcm_channels);
155
156
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
157
hw_rule_channels, pcm_channels,
158
SNDRV_PCM_HW_PARAM_RATE, -1);
159
if (err < 0)
160
goto end;
161
162
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
163
hw_rule_rate, pcm_channels,
164
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
165
if (err < 0)
166
goto end;
167
168
err = amdtp_am824_add_pcm_hw_constraints(s, runtime);
169
end:
170
return err;
171
}
172
173
static int pcm_open(struct snd_pcm_substream *substream)
174
{
175
struct snd_efw *efw = substream->private_data;
176
struct amdtp_domain *d = &efw->domain;
177
enum snd_efw_clock_source clock_source;
178
int err;
179
180
err = snd_efw_stream_lock_try(efw);
181
if (err < 0)
182
return err;
183
184
err = pcm_init_hw_params(efw, substream);
185
if (err < 0)
186
goto err_locked;
187
188
err = snd_efw_command_get_clock_source(efw, &clock_source);
189
if (err < 0)
190
goto err_locked;
191
192
mutex_lock(&efw->mutex);
193
194
// When source of clock is not internal or any stream is reserved for
195
// transmission of PCM frames, the available sampling rate is limited
196
// at current one.
197
if ((clock_source != SND_EFW_CLOCK_SOURCE_INTERNAL) ||
198
(efw->substreams_counter > 0 && d->events_per_period > 0)) {
199
unsigned int frames_per_period = d->events_per_period;
200
unsigned int frames_per_buffer = d->events_per_buffer;
201
unsigned int sampling_rate;
202
203
err = snd_efw_command_get_sampling_rate(efw, &sampling_rate);
204
if (err < 0) {
205
mutex_unlock(&efw->mutex);
206
goto err_locked;
207
}
208
substream->runtime->hw.rate_min = sampling_rate;
209
substream->runtime->hw.rate_max = sampling_rate;
210
211
if (frames_per_period > 0) {
212
err = snd_pcm_hw_constraint_minmax(substream->runtime,
213
SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
214
frames_per_period, frames_per_period);
215
if (err < 0) {
216
mutex_unlock(&efw->mutex);
217
goto err_locked;
218
}
219
220
err = snd_pcm_hw_constraint_minmax(substream->runtime,
221
SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
222
frames_per_buffer, frames_per_buffer);
223
if (err < 0) {
224
mutex_unlock(&efw->mutex);
225
goto err_locked;
226
}
227
}
228
}
229
230
mutex_unlock(&efw->mutex);
231
232
snd_pcm_set_sync(substream);
233
234
return 0;
235
err_locked:
236
snd_efw_stream_lock_release(efw);
237
return err;
238
}
239
240
static int pcm_close(struct snd_pcm_substream *substream)
241
{
242
struct snd_efw *efw = substream->private_data;
243
snd_efw_stream_lock_release(efw);
244
return 0;
245
}
246
247
static int pcm_hw_params(struct snd_pcm_substream *substream,
248
struct snd_pcm_hw_params *hw_params)
249
{
250
struct snd_efw *efw = substream->private_data;
251
int err = 0;
252
253
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
254
unsigned int rate = params_rate(hw_params);
255
unsigned int frames_per_period = params_period_size(hw_params);
256
unsigned int frames_per_buffer = params_buffer_size(hw_params);
257
258
mutex_lock(&efw->mutex);
259
err = snd_efw_stream_reserve_duplex(efw, rate,
260
frames_per_period, frames_per_buffer);
261
if (err >= 0)
262
++efw->substreams_counter;
263
mutex_unlock(&efw->mutex);
264
}
265
266
return err;
267
}
268
269
static int pcm_hw_free(struct snd_pcm_substream *substream)
270
{
271
struct snd_efw *efw = substream->private_data;
272
273
mutex_lock(&efw->mutex);
274
275
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
276
--efw->substreams_counter;
277
278
snd_efw_stream_stop_duplex(efw);
279
280
mutex_unlock(&efw->mutex);
281
282
return 0;
283
}
284
285
static int pcm_capture_prepare(struct snd_pcm_substream *substream)
286
{
287
struct snd_efw *efw = substream->private_data;
288
int err;
289
290
err = snd_efw_stream_start_duplex(efw);
291
if (err >= 0)
292
amdtp_stream_pcm_prepare(&efw->tx_stream);
293
294
return err;
295
}
296
static int pcm_playback_prepare(struct snd_pcm_substream *substream)
297
{
298
struct snd_efw *efw = substream->private_data;
299
int err;
300
301
err = snd_efw_stream_start_duplex(efw);
302
if (err >= 0)
303
amdtp_stream_pcm_prepare(&efw->rx_stream);
304
305
return err;
306
}
307
308
static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
309
{
310
struct snd_efw *efw = substream->private_data;
311
312
switch (cmd) {
313
case SNDRV_PCM_TRIGGER_START:
314
amdtp_stream_pcm_trigger(&efw->tx_stream, substream);
315
break;
316
case SNDRV_PCM_TRIGGER_STOP:
317
amdtp_stream_pcm_trigger(&efw->tx_stream, NULL);
318
break;
319
default:
320
return -EINVAL;
321
}
322
323
return 0;
324
}
325
static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
326
{
327
struct snd_efw *efw = substream->private_data;
328
329
switch (cmd) {
330
case SNDRV_PCM_TRIGGER_START:
331
amdtp_stream_pcm_trigger(&efw->rx_stream, substream);
332
break;
333
case SNDRV_PCM_TRIGGER_STOP:
334
amdtp_stream_pcm_trigger(&efw->rx_stream, NULL);
335
break;
336
default:
337
return -EINVAL;
338
}
339
340
return 0;
341
}
342
343
static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
344
{
345
struct snd_efw *efw = sbstrm->private_data;
346
347
return amdtp_domain_stream_pcm_pointer(&efw->domain, &efw->tx_stream);
348
}
349
static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
350
{
351
struct snd_efw *efw = sbstrm->private_data;
352
353
return amdtp_domain_stream_pcm_pointer(&efw->domain, &efw->rx_stream);
354
}
355
356
static int pcm_capture_ack(struct snd_pcm_substream *substream)
357
{
358
struct snd_efw *efw = substream->private_data;
359
360
return amdtp_domain_stream_pcm_ack(&efw->domain, &efw->tx_stream);
361
}
362
363
static int pcm_playback_ack(struct snd_pcm_substream *substream)
364
{
365
struct snd_efw *efw = substream->private_data;
366
367
return amdtp_domain_stream_pcm_ack(&efw->domain, &efw->rx_stream);
368
}
369
370
int snd_efw_create_pcm_devices(struct snd_efw *efw)
371
{
372
static const struct snd_pcm_ops capture_ops = {
373
.open = pcm_open,
374
.close = pcm_close,
375
.hw_params = pcm_hw_params,
376
.hw_free = pcm_hw_free,
377
.prepare = pcm_capture_prepare,
378
.trigger = pcm_capture_trigger,
379
.pointer = pcm_capture_pointer,
380
.ack = pcm_capture_ack,
381
};
382
static const struct snd_pcm_ops playback_ops = {
383
.open = pcm_open,
384
.close = pcm_close,
385
.hw_params = pcm_hw_params,
386
.hw_free = pcm_hw_free,
387
.prepare = pcm_playback_prepare,
388
.trigger = pcm_playback_trigger,
389
.pointer = pcm_playback_pointer,
390
.ack = pcm_playback_ack,
391
};
392
struct snd_pcm *pcm;
393
int err;
394
395
err = snd_pcm_new(efw->card, efw->card->driver, 0, 1, 1, &pcm);
396
if (err < 0)
397
goto end;
398
399
pcm->private_data = efw;
400
pcm->nonatomic = true;
401
snprintf(pcm->name, sizeof(pcm->name), "%s PCM", efw->card->shortname);
402
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
403
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
404
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
405
end:
406
return err;
407
}
408
409
410