synclink_gt(): fix compat_ioctl()
[linux/fpc-iii.git] / sound / firewire / fireface / ff-pcm.c
blobbf47f9ec87039543ebc9c6aab50513ccbb6f1924
1 /*
2 * ff-pcm.c - a part of driver for RME Fireface series
4 * Copyright (c) 2015-2017 Takashi Sakamoto
6 * Licensed under the terms of the GNU General Public License, version 2.
7 */
9 #include "ff.h"
11 static inline unsigned int get_multiplier_mode_with_index(unsigned int index)
13 return ((int)index - 1) / 2;
16 static int hw_rule_rate(struct snd_pcm_hw_params *params,
17 struct snd_pcm_hw_rule *rule)
19 const unsigned int *pcm_channels = rule->private;
20 struct snd_interval *r =
21 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
22 const struct snd_interval *c =
23 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
24 struct snd_interval t = {
25 .min = UINT_MAX, .max = 0, .integer = 1
27 unsigned int i, mode;
29 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
30 mode = get_multiplier_mode_with_index(i);
31 if (!snd_interval_test(c, pcm_channels[mode]))
32 continue;
34 t.min = min(t.min, amdtp_rate_table[i]);
35 t.max = max(t.max, amdtp_rate_table[i]);
38 return snd_interval_refine(r, &t);
41 static int hw_rule_channels(struct snd_pcm_hw_params *params,
42 struct snd_pcm_hw_rule *rule)
44 const unsigned int *pcm_channels = rule->private;
45 struct snd_interval *c =
46 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
47 const struct snd_interval *r =
48 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
49 struct snd_interval t = {
50 .min = UINT_MAX, .max = 0, .integer = 1
52 unsigned int i, mode;
54 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
55 mode = get_multiplier_mode_with_index(i);
56 if (!snd_interval_test(r, amdtp_rate_table[i]))
57 continue;
59 t.min = min(t.min, pcm_channels[mode]);
60 t.max = max(t.max, pcm_channels[mode]);
63 return snd_interval_refine(c, &t);
66 static void limit_channels_and_rates(struct snd_pcm_hardware *hw,
67 const unsigned int *pcm_channels)
69 unsigned int mode;
70 unsigned int rate, channels;
71 int i;
73 hw->channels_min = UINT_MAX;
74 hw->channels_max = 0;
75 hw->rate_min = UINT_MAX;
76 hw->rate_max = 0;
78 for (i = 0; i < ARRAY_SIZE(amdtp_rate_table); i++) {
79 mode = get_multiplier_mode_with_index(i);
81 channels = pcm_channels[mode];
82 if (pcm_channels[mode] == 0)
83 continue;
84 hw->channels_min = min(hw->channels_min, channels);
85 hw->channels_max = max(hw->channels_max, channels);
87 rate = amdtp_rate_table[i];
88 hw->rates |= snd_pcm_rate_to_rate_bit(rate);
89 hw->rate_min = min(hw->rate_min, rate);
90 hw->rate_max = max(hw->rate_max, rate);
94 static int pcm_init_hw_params(struct snd_ff *ff,
95 struct snd_pcm_substream *substream)
97 struct snd_pcm_runtime *runtime = substream->runtime;
98 struct amdtp_stream *s;
99 const unsigned int *pcm_channels;
100 int err;
102 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
103 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
104 s = &ff->tx_stream;
105 pcm_channels = ff->spec->pcm_capture_channels;
106 } else {
107 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
108 s = &ff->rx_stream;
109 pcm_channels = ff->spec->pcm_playback_channels;
112 limit_channels_and_rates(&runtime->hw, pcm_channels);
114 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
115 hw_rule_channels, (void *)pcm_channels,
116 SNDRV_PCM_HW_PARAM_RATE, -1);
117 if (err < 0)
118 return err;
120 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
121 hw_rule_rate, (void *)pcm_channels,
122 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
123 if (err < 0)
124 return err;
126 return amdtp_ff_add_pcm_hw_constraints(s, runtime);
129 static int pcm_open(struct snd_pcm_substream *substream)
131 struct snd_ff *ff = substream->private_data;
132 unsigned int rate;
133 enum snd_ff_clock_src src;
134 int i, err;
136 err = snd_ff_stream_lock_try(ff);
137 if (err < 0)
138 return err;
140 err = pcm_init_hw_params(ff, substream);
141 if (err < 0)
142 goto release_lock;
144 err = ff->spec->protocol->get_clock(ff, &rate, &src);
145 if (err < 0)
146 goto release_lock;
148 if (src != SND_FF_CLOCK_SRC_INTERNAL) {
149 for (i = 0; i < CIP_SFC_COUNT; ++i) {
150 if (amdtp_rate_table[i] == rate)
151 break;
154 * The unit is configured at sampling frequency which packet
155 * streaming engine can't support.
157 if (i >= CIP_SFC_COUNT) {
158 err = -EIO;
159 goto release_lock;
162 substream->runtime->hw.rate_min = rate;
163 substream->runtime->hw.rate_max = rate;
164 } else {
165 if (amdtp_stream_pcm_running(&ff->rx_stream) ||
166 amdtp_stream_pcm_running(&ff->tx_stream)) {
167 rate = amdtp_rate_table[ff->rx_stream.sfc];
168 substream->runtime->hw.rate_min = rate;
169 substream->runtime->hw.rate_max = rate;
173 snd_pcm_set_sync(substream);
175 return 0;
177 release_lock:
178 snd_ff_stream_lock_release(ff);
179 return err;
182 static int pcm_close(struct snd_pcm_substream *substream)
184 struct snd_ff *ff = substream->private_data;
186 snd_ff_stream_lock_release(ff);
188 return 0;
191 static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
192 struct snd_pcm_hw_params *hw_params)
194 struct snd_ff *ff = substream->private_data;
195 int err;
197 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
198 params_buffer_bytes(hw_params));
199 if (err < 0)
200 return err;
202 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
203 mutex_lock(&ff->mutex);
204 ff->substreams_counter++;
205 mutex_unlock(&ff->mutex);
208 return 0;
211 static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
212 struct snd_pcm_hw_params *hw_params)
214 struct snd_ff *ff = substream->private_data;
215 int err;
217 err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
218 params_buffer_bytes(hw_params));
219 if (err < 0)
220 return err;
222 if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
223 mutex_lock(&ff->mutex);
224 ff->substreams_counter++;
225 mutex_unlock(&ff->mutex);
228 return 0;
231 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
233 struct snd_ff *ff = substream->private_data;
235 mutex_lock(&ff->mutex);
237 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
238 ff->substreams_counter--;
240 snd_ff_stream_stop_duplex(ff);
242 mutex_unlock(&ff->mutex);
244 return snd_pcm_lib_free_vmalloc_buffer(substream);
247 static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
249 struct snd_ff *ff = substream->private_data;
251 mutex_lock(&ff->mutex);
253 if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
254 ff->substreams_counter--;
256 snd_ff_stream_stop_duplex(ff);
258 mutex_unlock(&ff->mutex);
260 return snd_pcm_lib_free_vmalloc_buffer(substream);
263 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
265 struct snd_ff *ff = substream->private_data;
266 struct snd_pcm_runtime *runtime = substream->runtime;
267 int err;
269 mutex_lock(&ff->mutex);
271 err = snd_ff_stream_start_duplex(ff, runtime->rate);
272 if (err >= 0)
273 amdtp_stream_pcm_prepare(&ff->tx_stream);
275 mutex_unlock(&ff->mutex);
277 return err;
280 static int pcm_playback_prepare(struct snd_pcm_substream *substream)
282 struct snd_ff *ff = substream->private_data;
283 struct snd_pcm_runtime *runtime = substream->runtime;
284 int err;
286 mutex_lock(&ff->mutex);
288 err = snd_ff_stream_start_duplex(ff, runtime->rate);
289 if (err >= 0)
290 amdtp_stream_pcm_prepare(&ff->rx_stream);
292 mutex_unlock(&ff->mutex);
294 return err;
297 static int pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
299 struct snd_ff *ff = substream->private_data;
301 switch (cmd) {
302 case SNDRV_PCM_TRIGGER_START:
303 amdtp_stream_pcm_trigger(&ff->tx_stream, substream);
304 break;
305 case SNDRV_PCM_TRIGGER_STOP:
306 amdtp_stream_pcm_trigger(&ff->tx_stream, NULL);
307 break;
308 default:
309 return -EINVAL;
312 return 0;
315 static int pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
317 struct snd_ff *ff = substream->private_data;
319 switch (cmd) {
320 case SNDRV_PCM_TRIGGER_START:
321 amdtp_stream_pcm_trigger(&ff->rx_stream, substream);
322 break;
323 case SNDRV_PCM_TRIGGER_STOP:
324 amdtp_stream_pcm_trigger(&ff->rx_stream, NULL);
325 break;
326 default:
327 return -EINVAL;
330 return 0;
333 static snd_pcm_uframes_t pcm_capture_pointer(struct snd_pcm_substream *sbstrm)
335 struct snd_ff *ff = sbstrm->private_data;
337 return amdtp_stream_pcm_pointer(&ff->tx_stream);
340 static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
342 struct snd_ff *ff = sbstrm->private_data;
344 return amdtp_stream_pcm_pointer(&ff->rx_stream);
347 static int pcm_capture_ack(struct snd_pcm_substream *substream)
349 struct snd_ff *ff = substream->private_data;
351 return amdtp_stream_pcm_ack(&ff->tx_stream);
354 static int pcm_playback_ack(struct snd_pcm_substream *substream)
356 struct snd_ff *ff = substream->private_data;
358 return amdtp_stream_pcm_ack(&ff->rx_stream);
361 int snd_ff_create_pcm_devices(struct snd_ff *ff)
363 static const struct snd_pcm_ops pcm_capture_ops = {
364 .open = pcm_open,
365 .close = pcm_close,
366 .ioctl = snd_pcm_lib_ioctl,
367 .hw_params = pcm_capture_hw_params,
368 .hw_free = pcm_capture_hw_free,
369 .prepare = pcm_capture_prepare,
370 .trigger = pcm_capture_trigger,
371 .pointer = pcm_capture_pointer,
372 .ack = pcm_capture_ack,
373 .page = snd_pcm_lib_get_vmalloc_page,
375 static const struct snd_pcm_ops pcm_playback_ops = {
376 .open = pcm_open,
377 .close = pcm_close,
378 .ioctl = snd_pcm_lib_ioctl,
379 .hw_params = pcm_playback_hw_params,
380 .hw_free = pcm_playback_hw_free,
381 .prepare = pcm_playback_prepare,
382 .trigger = pcm_playback_trigger,
383 .pointer = pcm_playback_pointer,
384 .ack = pcm_playback_ack,
385 .page = snd_pcm_lib_get_vmalloc_page,
387 struct snd_pcm *pcm;
388 int err;
390 err = snd_pcm_new(ff->card, ff->card->driver, 0, 1, 1, &pcm);
391 if (err < 0)
392 return err;
394 pcm->private_data = ff;
395 snprintf(pcm->name, sizeof(pcm->name),
396 "%s PCM", ff->card->shortname);
397 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
398 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
400 return 0;