blob: bb3ef5ff3488c83082206aaf497eff4cffc44722 [file] [log] [blame]
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001/*
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
12static 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 unsigned int index = substream->pcm->device;
18
19 const struct snd_interval *c =
20 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
21 struct snd_interval *r =
22 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
23 struct snd_interval rates = {
24 .min = UINT_MAX, .max = 0, .integer = 1
25 };
26 unsigned int *pcm_channels;
27 enum snd_dice_rate_mode mode;
28 unsigned int i, rate;
29
30 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
31 pcm_channels = dice->tx_pcm_chs[index];
32 else
33 pcm_channels = dice->rx_pcm_chs[index];
34
35 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
36 rate = snd_dice_rates[i];
37 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
38 continue;
39
40 if (!snd_interval_test(c, pcm_channels[mode]))
41 continue;
42
43 rates.min = min(rates.min, rate);
44 rates.max = max(rates.max, rate);
45 }
46
47 return snd_interval_refine(r, &rates);
48}
49
50static int dice_channels_constraint(struct snd_pcm_hw_params *params,
51 struct snd_pcm_hw_rule *rule)
52{
53 struct snd_pcm_substream *substream = rule->private;
54 struct snd_dice *dice = substream->private_data;
55 unsigned int index = substream->pcm->device;
56
57 const struct snd_interval *r =
58 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
59 struct snd_interval *c =
60 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
61 struct snd_interval channels = {
62 .min = UINT_MAX, .max = 0, .integer = 1
63 };
64 unsigned int *pcm_channels;
65 enum snd_dice_rate_mode mode;
66 unsigned int i, rate;
67
68 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
69 pcm_channels = dice->tx_pcm_chs[index];
70 else
71 pcm_channels = dice->rx_pcm_chs[index];
72
73 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
74 rate = snd_dice_rates[i];
75 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
76 continue;
77
78 if (!snd_interval_test(r, rate))
79 continue;
80
81 channels.min = min(channels.min, pcm_channels[mode]);
82 channels.max = max(channels.max, pcm_channels[mode]);
83 }
84
85 return snd_interval_refine(c, &channels);
86}
87
88static int limit_channels_and_rates(struct snd_dice *dice,
89 struct snd_pcm_runtime *runtime,
90 enum amdtp_stream_direction dir,
91 unsigned int index)
92{
93 struct snd_pcm_hardware *hw = &runtime->hw;
94 unsigned int *pcm_channels;
95 unsigned int i;
96
97 if (dir == AMDTP_IN_STREAM)
98 pcm_channels = dice->tx_pcm_chs[index];
99 else
100 pcm_channels = dice->rx_pcm_chs[index];
101
102 hw->channels_min = UINT_MAX;
103 hw->channels_max = 0;
104
105 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
106 enum snd_dice_rate_mode mode;
107 unsigned int rate, channels;
108
109 rate = snd_dice_rates[i];
110 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
111 continue;
112 hw->rates |= snd_pcm_rate_to_rate_bit(rate);
113
114 channels = pcm_channels[mode];
115 if (channels == 0)
116 continue;
117 hw->channels_min = min(hw->channels_min, channels);
118 hw->channels_max = max(hw->channels_max, channels);
119 }
120
121 snd_pcm_limit_hw_rates(runtime);
122
123 return 0;
124}
125
126static int init_hw_info(struct snd_dice *dice,
127 struct snd_pcm_substream *substream)
128{
129 struct snd_pcm_runtime *runtime = substream->runtime;
130 struct snd_pcm_hardware *hw = &runtime->hw;
131 unsigned int index = substream->pcm->device;
132 enum amdtp_stream_direction dir;
133 struct amdtp_stream *stream;
134 int err;
135
136 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
137 hw->formats = AM824_IN_PCM_FORMAT_BITS;
138 dir = AMDTP_IN_STREAM;
139 stream = &dice->tx_stream[index];
140 } else {
141 hw->formats = AM824_OUT_PCM_FORMAT_BITS;
142 dir = AMDTP_OUT_STREAM;
143 stream = &dice->rx_stream[index];
144 }
145
146 err = limit_channels_and_rates(dice, substream->runtime, dir,
147 index);
148 if (err < 0)
149 return err;
150
151 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
152 dice_rate_constraint, substream,
153 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
154 if (err < 0)
155 return err;
156 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
157 dice_channels_constraint, substream,
158 SNDRV_PCM_HW_PARAM_RATE, -1);
159 if (err < 0)
160 return err;
161
162 return amdtp_am824_add_pcm_hw_constraints(stream, runtime);
163}
164
165static int pcm_open(struct snd_pcm_substream *substream)
166{
167 struct snd_dice *dice = substream->private_data;
168 unsigned int source;
169 bool internal;
170 int err;
171
172 err = snd_dice_stream_lock_try(dice);
173 if (err < 0)
174 goto end;
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 /*
200 * When source of clock is not internal or any PCM streams are running,
201 * available sampling rate is limited at current sampling rate.
202 */
203 if (!internal ||
204 amdtp_stream_pcm_running(&dice->tx_stream[0]) ||
205 amdtp_stream_pcm_running(&dice->tx_stream[1]) ||
206 amdtp_stream_pcm_running(&dice->rx_stream[0]) ||
207 amdtp_stream_pcm_running(&dice->rx_stream[1])) {
208 unsigned int rate;
209
210 err = snd_dice_transaction_get_rate(dice, &rate);
211 if (err < 0)
212 goto err_locked;
213 substream->runtime->hw.rate_min = rate;
214 substream->runtime->hw.rate_max = rate;
215 }
216
217 snd_pcm_set_sync(substream);
218end:
219 return err;
220err_locked:
221 snd_dice_stream_lock_release(dice);
222 return err;
223}
224
225static int pcm_close(struct snd_pcm_substream *substream)
226{
227 struct snd_dice *dice = substream->private_data;
228
229 snd_dice_stream_lock_release(dice);
230
231 return 0;
232}
233
234static int capture_hw_params(struct snd_pcm_substream *substream,
235 struct snd_pcm_hw_params *hw_params)
236{
237 struct snd_dice *dice = substream->private_data;
238 int err;
239
240 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
241 params_buffer_bytes(hw_params));
242 if (err < 0)
243 return err;
244
245 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
246 mutex_lock(&dice->mutex);
247 dice->substreams_counter++;
248 mutex_unlock(&dice->mutex);
249 }
250
251 return 0;
252}
253static int playback_hw_params(struct snd_pcm_substream *substream,
254 struct snd_pcm_hw_params *hw_params)
255{
256 struct snd_dice *dice = substream->private_data;
257 int err;
258
259 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
260 params_buffer_bytes(hw_params));
261 if (err < 0)
262 return err;
263
264 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
265 mutex_lock(&dice->mutex);
266 dice->substreams_counter++;
267 mutex_unlock(&dice->mutex);
268 }
269
270 return 0;
271}
272
273static int capture_hw_free(struct snd_pcm_substream *substream)
274{
275 struct snd_dice *dice = substream->private_data;
276
277 mutex_lock(&dice->mutex);
278
279 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
280 dice->substreams_counter--;
281
282 snd_dice_stream_stop_duplex(dice);
283
284 mutex_unlock(&dice->mutex);
285
286 return snd_pcm_lib_free_vmalloc_buffer(substream);
287}
288
289static int playback_hw_free(struct snd_pcm_substream *substream)
290{
291 struct snd_dice *dice = substream->private_data;
292
293 mutex_lock(&dice->mutex);
294
295 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
296 dice->substreams_counter--;
297
298 snd_dice_stream_stop_duplex(dice);
299
300 mutex_unlock(&dice->mutex);
301
302 return snd_pcm_lib_free_vmalloc_buffer(substream);
303}
304
305static int capture_prepare(struct snd_pcm_substream *substream)
306{
307 struct snd_dice *dice = substream->private_data;
308 struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
309 int err;
310
311 mutex_lock(&dice->mutex);
312 err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
313 mutex_unlock(&dice->mutex);
314 if (err >= 0)
315 amdtp_stream_pcm_prepare(stream);
316
317 return 0;
318}
319static int playback_prepare(struct snd_pcm_substream *substream)
320{
321 struct snd_dice *dice = substream->private_data;
322 struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
323 int err;
324
325 mutex_lock(&dice->mutex);
326 err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
327 mutex_unlock(&dice->mutex);
328 if (err >= 0)
329 amdtp_stream_pcm_prepare(stream);
330
331 return err;
332}
333
334static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
335{
336 struct snd_dice *dice = substream->private_data;
337 struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
338
339 switch (cmd) {
340 case SNDRV_PCM_TRIGGER_START:
341 amdtp_stream_pcm_trigger(stream, substream);
342 break;
343 case SNDRV_PCM_TRIGGER_STOP:
344 amdtp_stream_pcm_trigger(stream, NULL);
345 break;
346 default:
347 return -EINVAL;
348 }
349
350 return 0;
351}
352static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
353{
354 struct snd_dice *dice = substream->private_data;
355 struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
356
357 switch (cmd) {
358 case SNDRV_PCM_TRIGGER_START:
359 amdtp_stream_pcm_trigger(stream, substream);
360 break;
361 case SNDRV_PCM_TRIGGER_STOP:
362 amdtp_stream_pcm_trigger(stream, NULL);
363 break;
364 default:
365 return -EINVAL;
366 }
367
368 return 0;
369}
370
371static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
372{
373 struct snd_dice *dice = substream->private_data;
374 struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
375
376 return amdtp_stream_pcm_pointer(stream);
377}
378static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
379{
380 struct snd_dice *dice = substream->private_data;
381 struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
382
383 return amdtp_stream_pcm_pointer(stream);
384}
385
386static int capture_ack(struct snd_pcm_substream *substream)
387{
388 struct snd_dice *dice = substream->private_data;
389 struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
390
391 return amdtp_stream_pcm_ack(stream);
392}
393
394static int playback_ack(struct snd_pcm_substream *substream)
395{
396 struct snd_dice *dice = substream->private_data;
397 struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
398
399 return amdtp_stream_pcm_ack(stream);
400}
401
402int snd_dice_create_pcm(struct snd_dice *dice)
403{
404 static const struct snd_pcm_ops capture_ops = {
405 .open = pcm_open,
406 .close = pcm_close,
407 .ioctl = snd_pcm_lib_ioctl,
408 .hw_params = capture_hw_params,
409 .hw_free = capture_hw_free,
410 .prepare = capture_prepare,
411 .trigger = capture_trigger,
412 .pointer = capture_pointer,
413 .ack = capture_ack,
414 .page = snd_pcm_lib_get_vmalloc_page,
415 };
416 static const struct snd_pcm_ops playback_ops = {
417 .open = pcm_open,
418 .close = pcm_close,
419 .ioctl = snd_pcm_lib_ioctl,
420 .hw_params = playback_hw_params,
421 .hw_free = playback_hw_free,
422 .prepare = playback_prepare,
423 .trigger = playback_trigger,
424 .pointer = playback_pointer,
425 .ack = playback_ack,
426 .page = snd_pcm_lib_get_vmalloc_page,
427 };
428 struct snd_pcm *pcm;
429 unsigned int capture, playback;
430 int i, j;
431 int err;
432
433 for (i = 0; i < MAX_STREAMS; i++) {
434 capture = playback = 0;
435 for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
436 if (dice->tx_pcm_chs[i][j] > 0)
437 capture = 1;
438 if (dice->rx_pcm_chs[i][j] > 0)
439 playback = 1;
440 }
441
442 err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
443 &pcm);
444 if (err < 0)
445 return err;
446 pcm->private_data = dice;
447 strcpy(pcm->name, dice->card->shortname);
448
449 if (capture > 0)
450 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
451 &capture_ops);
452
453 if (playback > 0)
454 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
455 &playback_ops);
456 }
457
458 return 0;
459}