Linux-libre 4.17.3-gnu
[librecmc/linux-libre.git] / sound / firewire / dice / dice-pcm.c
1 /*
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
12 static int limit_channels_and_rates(struct snd_dice *dice,
13                                     struct snd_pcm_runtime *runtime,
14                                     enum amdtp_stream_direction dir,
15                                     unsigned int index, unsigned int size)
16 {
17         struct snd_pcm_hardware *hw = &runtime->hw;
18         struct amdtp_stream *stream;
19         unsigned int rate;
20         __be32 reg;
21         int err;
22
23         /*
24          * Retrieve current Multi Bit Linear Audio data channel and limit to
25          * it.
26          */
27         if (dir == AMDTP_IN_STREAM) {
28                 stream = &dice->tx_stream[index];
29                 err = snd_dice_transaction_read_tx(dice,
30                                 size * index + TX_NUMBER_AUDIO,
31                                 &reg, sizeof(reg));
32         } else {
33                 stream = &dice->rx_stream[index];
34                 err = snd_dice_transaction_read_rx(dice,
35                                 size * index + RX_NUMBER_AUDIO,
36                                 &reg, sizeof(reg));
37         }
38         if (err < 0)
39                 return err;
40
41         hw->channels_min = hw->channels_max = be32_to_cpu(reg);
42
43         /* Retrieve current sampling transfer frequency and limit to it. */
44         err = snd_dice_transaction_get_rate(dice, &rate);
45         if (err < 0)
46                 return err;
47
48         hw->rates = snd_pcm_rate_to_rate_bit(rate);
49         snd_pcm_limit_hw_rates(runtime);
50
51         return 0;
52 }
53
54 static int init_hw_info(struct snd_dice *dice,
55                         struct snd_pcm_substream *substream)
56 {
57         struct snd_pcm_runtime *runtime = substream->runtime;
58         struct snd_pcm_hardware *hw = &runtime->hw;
59         enum amdtp_stream_direction dir;
60         struct amdtp_stream *stream;
61         __be32 reg[2];
62         unsigned int count, size;
63         int err;
64
65         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
66                 hw->formats = AM824_IN_PCM_FORMAT_BITS;
67                 dir = AMDTP_IN_STREAM;
68                 stream = &dice->tx_stream[substream->pcm->device];
69                 err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg,
70                                                    sizeof(reg));
71         } else {
72                 hw->formats = AM824_OUT_PCM_FORMAT_BITS;
73                 dir = AMDTP_OUT_STREAM;
74                 stream = &dice->rx_stream[substream->pcm->device];
75                 err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg,
76                                                    sizeof(reg));
77         }
78
79         if (err < 0)
80                 return err;
81
82         count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
83         if (substream->pcm->device >= count)
84                 return -ENXIO;
85
86         size = be32_to_cpu(reg[1]) * 4;
87         err = limit_channels_and_rates(dice, substream->runtime, dir,
88                                        substream->pcm->device, size);
89         if (err < 0)
90                 return err;
91
92         return amdtp_am824_add_pcm_hw_constraints(stream, runtime);
93 }
94
95 static int pcm_open(struct snd_pcm_substream *substream)
96 {
97         struct snd_dice *dice = substream->private_data;
98         int err;
99
100         err = snd_dice_stream_lock_try(dice);
101         if (err < 0)
102                 goto end;
103
104         err = init_hw_info(dice, substream);
105         if (err < 0)
106                 goto err_locked;
107
108         snd_pcm_set_sync(substream);
109 end:
110         return err;
111 err_locked:
112         snd_dice_stream_lock_release(dice);
113         return err;
114 }
115
116 static int pcm_close(struct snd_pcm_substream *substream)
117 {
118         struct snd_dice *dice = substream->private_data;
119
120         snd_dice_stream_lock_release(dice);
121
122         return 0;
123 }
124
125 static int capture_hw_params(struct snd_pcm_substream *substream,
126                              struct snd_pcm_hw_params *hw_params)
127 {
128         struct snd_dice *dice = substream->private_data;
129         int err;
130
131         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
132                                                params_buffer_bytes(hw_params));
133         if (err < 0)
134                 return err;
135
136         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
137                 mutex_lock(&dice->mutex);
138                 dice->substreams_counter++;
139                 mutex_unlock(&dice->mutex);
140         }
141
142         return 0;
143 }
144 static int playback_hw_params(struct snd_pcm_substream *substream,
145                               struct snd_pcm_hw_params *hw_params)
146 {
147         struct snd_dice *dice = substream->private_data;
148         int err;
149
150         err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
151                                                params_buffer_bytes(hw_params));
152         if (err < 0)
153                 return err;
154
155         if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
156                 mutex_lock(&dice->mutex);
157                 dice->substreams_counter++;
158                 mutex_unlock(&dice->mutex);
159         }
160
161         return 0;
162 }
163
164 static int capture_hw_free(struct snd_pcm_substream *substream)
165 {
166         struct snd_dice *dice = substream->private_data;
167
168         mutex_lock(&dice->mutex);
169
170         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
171                 dice->substreams_counter--;
172
173         snd_dice_stream_stop_duplex(dice);
174
175         mutex_unlock(&dice->mutex);
176
177         return snd_pcm_lib_free_vmalloc_buffer(substream);
178 }
179
180 static int playback_hw_free(struct snd_pcm_substream *substream)
181 {
182         struct snd_dice *dice = substream->private_data;
183
184         mutex_lock(&dice->mutex);
185
186         if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
187                 dice->substreams_counter--;
188
189         snd_dice_stream_stop_duplex(dice);
190
191         mutex_unlock(&dice->mutex);
192
193         return snd_pcm_lib_free_vmalloc_buffer(substream);
194 }
195
196 static int capture_prepare(struct snd_pcm_substream *substream)
197 {
198         struct snd_dice *dice = substream->private_data;
199         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
200         int err;
201
202         mutex_lock(&dice->mutex);
203         err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
204         mutex_unlock(&dice->mutex);
205         if (err >= 0)
206                 amdtp_stream_pcm_prepare(stream);
207
208         return 0;
209 }
210 static int playback_prepare(struct snd_pcm_substream *substream)
211 {
212         struct snd_dice *dice = substream->private_data;
213         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
214         int err;
215
216         mutex_lock(&dice->mutex);
217         err = snd_dice_stream_start_duplex(dice, substream->runtime->rate);
218         mutex_unlock(&dice->mutex);
219         if (err >= 0)
220                 amdtp_stream_pcm_prepare(stream);
221
222         return err;
223 }
224
225 static int capture_trigger(struct snd_pcm_substream *substream, int cmd)
226 {
227         struct snd_dice *dice = substream->private_data;
228         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
229
230         switch (cmd) {
231         case SNDRV_PCM_TRIGGER_START:
232                 amdtp_stream_pcm_trigger(stream, substream);
233                 break;
234         case SNDRV_PCM_TRIGGER_STOP:
235                 amdtp_stream_pcm_trigger(stream, NULL);
236                 break;
237         default:
238                 return -EINVAL;
239         }
240
241         return 0;
242 }
243 static int playback_trigger(struct snd_pcm_substream *substream, int cmd)
244 {
245         struct snd_dice *dice = substream->private_data;
246         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
247
248         switch (cmd) {
249         case SNDRV_PCM_TRIGGER_START:
250                 amdtp_stream_pcm_trigger(stream, substream);
251                 break;
252         case SNDRV_PCM_TRIGGER_STOP:
253                 amdtp_stream_pcm_trigger(stream, NULL);
254                 break;
255         default:
256                 return -EINVAL;
257         }
258
259         return 0;
260 }
261
262 static snd_pcm_uframes_t capture_pointer(struct snd_pcm_substream *substream)
263 {
264         struct snd_dice *dice = substream->private_data;
265         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
266
267         return amdtp_stream_pcm_pointer(stream);
268 }
269 static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
270 {
271         struct snd_dice *dice = substream->private_data;
272         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
273
274         return amdtp_stream_pcm_pointer(stream);
275 }
276
277 static int capture_ack(struct snd_pcm_substream *substream)
278 {
279         struct snd_dice *dice = substream->private_data;
280         struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
281
282         return amdtp_stream_pcm_ack(stream);
283 }
284
285 static int playback_ack(struct snd_pcm_substream *substream)
286 {
287         struct snd_dice *dice = substream->private_data;
288         struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
289
290         return amdtp_stream_pcm_ack(stream);
291 }
292
293 int snd_dice_create_pcm(struct snd_dice *dice)
294 {
295         static const struct snd_pcm_ops capture_ops = {
296                 .open      = pcm_open,
297                 .close     = pcm_close,
298                 .ioctl     = snd_pcm_lib_ioctl,
299                 .hw_params = capture_hw_params,
300                 .hw_free   = capture_hw_free,
301                 .prepare   = capture_prepare,
302                 .trigger   = capture_trigger,
303                 .pointer   = capture_pointer,
304                 .ack       = capture_ack,
305                 .page      = snd_pcm_lib_get_vmalloc_page,
306                 .mmap      = snd_pcm_lib_mmap_vmalloc,
307         };
308         static const struct snd_pcm_ops playback_ops = {
309                 .open      = pcm_open,
310                 .close     = pcm_close,
311                 .ioctl     = snd_pcm_lib_ioctl,
312                 .hw_params = playback_hw_params,
313                 .hw_free   = playback_hw_free,
314                 .prepare   = playback_prepare,
315                 .trigger   = playback_trigger,
316                 .pointer   = playback_pointer,
317                 .ack       = playback_ack,
318                 .page      = snd_pcm_lib_get_vmalloc_page,
319                 .mmap      = snd_pcm_lib_mmap_vmalloc,
320         };
321         __be32 reg;
322         struct snd_pcm *pcm;
323         unsigned int i, max_capture, max_playback, capture, playback;
324         int err;
325
326         /* Check whether PCM substreams are required. */
327         if (dice->force_two_pcms) {
328                 max_capture = max_playback = 2;
329         } else {
330                 max_capture = max_playback = 0;
331                 err = snd_dice_transaction_read_tx(dice, TX_NUMBER, &reg,
332                                                    sizeof(reg));
333                 if (err < 0)
334                         return err;
335                 max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
336
337                 err = snd_dice_transaction_read_rx(dice, RX_NUMBER, &reg,
338                                                    sizeof(reg));
339                 if (err < 0)
340                         return err;
341                 max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
342         }
343
344         for (i = 0; i < MAX_STREAMS; i++) {
345                 capture = playback = 0;
346                 if (i < max_capture)
347                         capture = 1;
348                 if (i < max_playback)
349                         playback = 1;
350                 if (capture == 0 && playback == 0)
351                         break;
352
353                 err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
354                                   &pcm);
355                 if (err < 0)
356                         return err;
357                 pcm->private_data = dice;
358                 strcpy(pcm->name, dice->card->shortname);
359
360                 if (capture > 0)
361                         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
362                                         &capture_ops);
363
364                 if (playback > 0)
365                         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
366                                         &playback_ops);
367         }
368
369         return 0;
370 }