1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * tascam-pcm.c - a part of driver for TASCAM FireWire series
4  *
5  * Copyright (c) 2015 Takashi Sakamoto
6  */
7 
8 #include "tascam.h"
9 
10 static int pcm_init_hw_params(struct snd_tscm *tscm,
11 			      struct snd_pcm_substream *substream)
12 {
13 	struct snd_pcm_runtime *runtime = substream->runtime;
14 	struct snd_pcm_hardware *hw = &runtime->hw;
15 	struct amdtp_stream *stream;
16 	unsigned int pcm_channels;
17 
18 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
19 		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
20 		stream = &tscm->tx_stream;
21 		pcm_channels = tscm->spec->pcm_capture_analog_channels;
22 	} else {
23 		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
24 		stream = &tscm->rx_stream;
25 		pcm_channels = tscm->spec->pcm_playback_analog_channels;
26 	}
27 
28 	if (tscm->spec->has_adat)
29 		pcm_channels += 8;
30 	if (tscm->spec->has_spdif)
31 		pcm_channels += 2;
32 	runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels;
33 
34 	hw->rates = SNDRV_PCM_RATE_44100 |
35 		    SNDRV_PCM_RATE_48000 |
36 		    SNDRV_PCM_RATE_88200 |
37 		    SNDRV_PCM_RATE_96000;
38 	snd_pcm_limit_hw_rates(runtime);
39 
40 	return amdtp_tscm_add_pcm_hw_constraints(stream, runtime);
41 }
42 
43 static int pcm_open(struct snd_pcm_substream *substream)
44 {
45 	struct snd_tscm *tscm = substream->private_data;
46 	struct amdtp_domain *d = &tscm->domain;
47 	enum snd_tscm_clock clock;
48 	int err;
49 
50 	err = snd_tscm_stream_lock_try(tscm);
51 	if (err < 0)
52 		return err;
53 
54 	err = pcm_init_hw_params(tscm, substream);
55 	if (err < 0)
56 		goto err_locked;
57 
58 	err = snd_tscm_stream_get_clock(tscm, &clock);
59 	if (err < 0)
60 		goto err_locked;
61 
62 	mutex_lock(&tscm->mutex);
63 
64 	// When source of clock is not internal or any stream is reserved for
65 	// transmission of PCM frames, the available sampling rate is limited
66 	// at current one.
67 	if (clock != SND_TSCM_CLOCK_INTERNAL || tscm->substreams_counter > 0) {
68 		unsigned int frames_per_period = d->events_per_period;
69 		unsigned int frames_per_buffer = d->events_per_buffer;
70 		unsigned int rate;
71 
72 		err = snd_tscm_stream_get_rate(tscm, &rate);
73 		if (err < 0) {
74 			mutex_unlock(&tscm->mutex);
75 			goto err_locked;
76 		}
77 		substream->runtime->hw.rate_min = rate;
78 		substream->runtime->hw.rate_max = rate;
79 
80 		err = snd_pcm_hw_constraint_minmax(substream->runtime,
81 					SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
82 					frames_per_period, frames_per_period);
83 		if (err < 0) {
84 			mutex_unlock(&tscm->mutex);
85 			goto err_locked;
86 		}
87 
88 		err = snd_pcm_hw_constraint_minmax(substream->runtime,
89 					SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
90 					frames_per_buffer, frames_per_buffer);
91 		if (err < 0) {
92 			mutex_unlock(&tscm->mutex);
93 			goto err_locked;
94 		}
95 	}
96 
97 	mutex_unlock(&tscm->mutex);
98 
99 	snd_pcm_set_sync(substream);
100 
101 	return 0;
102 err_locked:
103 	snd_tscm_stream_lock_release(tscm);
104 	return err;
105 }
106 
107 static int pcm_close(struct snd_pcm_substream *substream)
108 {
109 	struct snd_tscm *tscm = substream->private_data;
110 
111 	snd_tscm_stream_lock_release(tscm);
112 
113 	return 0;
114 }
115 
116 static int pcm_hw_params(struct snd_pcm_substream *substream,
117 			 struct snd_pcm_hw_params *hw_params)
118 {
119 	struct snd_tscm *tscm = substream->private_data;
120 	int err;
121 
122 	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
123 	if (err < 0)
124 		return err;
125 
126 	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
127 		unsigned int rate = params_rate(hw_params);
128 		unsigned int frames_per_period = params_period_size(hw_params);
129 		unsigned int frames_per_buffer = params_buffer_size(hw_params);
130 
131 		mutex_lock(&tscm->mutex);
132 		err = snd_tscm_stream_reserve_duplex(tscm, rate,
133 					frames_per_period, frames_per_buffer);
134 		if (err >= 0)
135 			++tscm->substreams_counter;
136 		mutex_unlock(&tscm->mutex);
137 	}
138 
139 	return err;
140 }
141 
142 static int pcm_hw_free(struct snd_pcm_substream *substream)
143 {
144 	struct snd_tscm *tscm = substream->private_data;
145 
146 	mutex_lock(&tscm->mutex);
147 
148 	if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
149 		--tscm->substreams_counter;
150 
151 	snd_tscm_stream_stop_duplex(tscm);
152 
153 	mutex_unlock(&tscm->mutex);
154 
155 	return snd_pcm_lib_free_pages(substream);
156 }
157 
158 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
159 {
160 	struct snd_tscm *tscm = substream->private_data;
161 	struct snd_pcm_runtime *runtime = substream->runtime;
162 	int err;
163 
164 	mutex_lock(&tscm->mutex);
165 
166 	err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
167 	if (err >= 0)
168 		amdtp_stream_pcm_prepare(&tscm->tx_stream);
169 
170 	mutex_unlock(&tscm->mutex);
171 
172 	return err;
173 }
174 
175 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
176 {
177 	struct snd_tscm *tscm = substream->private_data;
178 	struct snd_pcm_runtime *runtime = substream->runtime;
179 	int err;
180 
181 	mutex_lock(&tscm->mutex);
182 
183 	err = snd_tscm_stream_start_duplex(tscm, runtime->rate);
184 	if (err >= 0)
185 		amdtp_stream_pcm_prepare(&tscm->rx_stream);
186 
187 	mutex_unlock(&tscm->mutex);
188 
189 	return err;
190 }
191 
192 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
193 {
194 	struct snd_tscm *tscm = substream->private_data;
195 
196 	switch (cmd) {
197 	case SNDRV_PCM_TRIGGER_START:
198 		amdtp_stream_pcm_trigger(&tscm->tx_stream, substream);
199 		break;
200 	case SNDRV_PCM_TRIGGER_STOP:
201 		amdtp_stream_pcm_trigger(&tscm->tx_stream, NULL);
202 		break;
203 	default:
204 		return -EINVAL;
205 	}
206 
207 	return 0;
208 }
209 
210 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
211 {
212 	struct snd_tscm *tscm = substream->private_data;
213 
214 	switch (cmd) {
215 	case SNDRV_PCM_TRIGGER_START:
216 		amdtp_stream_pcm_trigger(&tscm->rx_stream, substream);
217 		break;
218 	case SNDRV_PCM_TRIGGER_STOP:
219 		amdtp_stream_pcm_trigger(&tscm->rx_stream, NULL);
220 		break;
221 	default:
222 		return -EINVAL;
223 	}
224 
225 	return 0;
226 }
227 
228 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
229 {
230 	struct snd_tscm *tscm = sbstrm->private_data;
231 
232 	return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->tx_stream);
233 }
234 
235 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
236 {
237 	struct snd_tscm *tscm = sbstrm->private_data;
238 
239 	return amdtp_domain_stream_pcm_pointer(&tscm->domain, &tscm->rx_stream);
240 }
241 
242 static int pcm_capture_ack(struct snd_pcm_substream *substream)
243 {
244 	struct snd_tscm *tscm = substream->private_data;
245 
246 	return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->tx_stream);
247 }
248 
249 static int pcm_playback_ack(struct snd_pcm_substream *substream)
250 {
251 	struct snd_tscm *tscm = substream->private_data;
252 
253 	return amdtp_domain_stream_pcm_ack(&tscm->domain, &tscm->rx_stream);
254 }
255 
256 int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
257 {
258 	static const struct snd_pcm_ops capture_ops = {
259 		.open		= pcm_open,
260 		.close		= pcm_close,
261 		.ioctl		= snd_pcm_lib_ioctl,
262 		.hw_params	= pcm_hw_params,
263 		.hw_free	= pcm_hw_free,
264 		.prepare	= pcm_capture_prepare,
265 		.trigger	= pcm_capture_trigger,
266 		.pointer	= pcm_capture_pointer,
267 		.ack		= pcm_capture_ack,
268 	};
269 	static const struct snd_pcm_ops playback_ops = {
270 		.open		= pcm_open,
271 		.close		= pcm_close,
272 		.ioctl		= snd_pcm_lib_ioctl,
273 		.hw_params	= pcm_hw_params,
274 		.hw_free	= pcm_hw_free,
275 		.prepare	= pcm_playback_prepare,
276 		.trigger	= pcm_playback_trigger,
277 		.pointer	= pcm_playback_pointer,
278 		.ack		= pcm_playback_ack,
279 	};
280 	struct snd_pcm *pcm;
281 	int err;
282 
283 	err = snd_pcm_new(tscm->card, tscm->card->driver, 0, 1, 1, &pcm);
284 	if (err < 0)
285 		return err;
286 
287 	pcm->private_data = tscm;
288 	snprintf(pcm->name, sizeof(pcm->name),
289 		 "%s PCM", tscm->card->shortname);
290 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
291 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
292 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
293 					      NULL, 0, 0);
294 
295 	return 0;
296 }
297