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