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 <clemens@ladisch.de>
6 * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
7 */
8
9#include "dice.h"
10
11static 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
49static 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
87static 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
125static 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
164static 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;
249err_locked:
250	snd_dice_stream_lock_release(dice);
251	return err;
252}
253
254static 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
263static 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
290static 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
306static 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}
320static 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
335static 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}
353static 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
372static 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}
379static 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
387static 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
395static 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
403int 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		strcpy(pcm->name, dice->card->shortname);
445
446		if (capture > 0)
447			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
448					&capture_ops);
449
450		if (playback > 0)
451			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
452					&playback_ops);
453
454		snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
455					       NULL, 0, 0);
456	}
457
458	return 0;
459}
460