]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
staging: bcm2835-audio: constify snd_pcm_ops structures
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / vc04_services / bcm2835-audio / bcm2835-pcm.c
CommitLineData
23b028c8
MZ
1/*****************************************************************************
2 * Copyright 2011 Broadcom Corporation. All rights reserved.
3 *
4 * Unless you and Broadcom execute a separate written software license
5 * agreement governing use of this software, this software is licensed to you
6 * under the terms of the GNU General Public License version 2, available at
7 * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8 *
9 * Notwithstanding the above, under no circumstances may you combine this
10 * software in any way with any other Broadcom software provided under a
11 * license other than the GPL, without Broadcom's express prior written
12 * consent.
13 *****************************************************************************/
14
15#include <linux/interrupt.h>
16#include <linux/slab.h>
17
18#include <sound/asoundef.h>
19
20#include "bcm2835.h"
21
22/* hardware definition */
23static struct snd_pcm_hardware snd_bcm2835_playback_hw = {
24 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
25 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
26 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
27 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
28 .rate_min = 8000,
29 .rate_max = 48000,
30 .channels_min = 1,
31 .channels_max = 2,
32 .buffer_bytes_max = 128 * 1024,
33 .period_bytes_min = 1 * 1024,
34 .period_bytes_max = 128 * 1024,
35 .periods_min = 1,
36 .periods_max = 128,
37};
38
39static struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
40 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
41 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
42 .formats = SNDRV_PCM_FMTBIT_S16_LE,
43 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
44 SNDRV_PCM_RATE_48000,
45 .rate_min = 44100,
46 .rate_max = 48000,
47 .channels_min = 2,
48 .channels_max = 2,
49 .buffer_bytes_max = 128 * 1024,
50 .period_bytes_min = 1 * 1024,
51 .period_bytes_max = 128 * 1024,
52 .periods_min = 1,
53 .periods_max = 128,
54};
55
56static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
57{
58 audio_info("Freeing up alsa stream here ..\n");
ac3c5ec8 59 kfree(runtime->private_data);
23b028c8
MZ
60 runtime->private_data = NULL;
61}
62
0cec463e 63void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream)
23b028c8 64{
23b028c8
MZ
65 unsigned int consumed = 0;
66 int new_period = 0;
67
23b028c8
MZ
68
69 audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
70 alsa_stream ? alsa_stream->substream : 0);
71
72 if (alsa_stream->open)
73 consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
74
75 /* We get called only if playback was triggered, So, the number of buffers we retrieve in
76 * each iteration are the buffers that have been played out already
77 */
78
79 if (alsa_stream->period_size) {
80 if ((alsa_stream->pos / alsa_stream->period_size) !=
81 ((alsa_stream->pos + consumed) / alsa_stream->period_size))
82 new_period = 1;
83 }
84 audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n",
85 alsa_stream->pos,
86 consumed,
87 alsa_stream->buffer_size,
88 (int) (alsa_stream->period_size * alsa_stream->substream->runtime->periods),
89 frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr),
90 new_period);
91 if (alsa_stream->buffer_size) {
15411ed5 92 alsa_stream->pos += consumed & ~(1 << 30);
23b028c8
MZ
93 alsa_stream->pos %= alsa_stream->buffer_size;
94 }
95
96 if (alsa_stream->substream) {
97 if (new_period)
98 snd_pcm_period_elapsed(alsa_stream->substream);
99 } else {
100 audio_warning(" unexpected NULL substream\n");
101 }
23b028c8
MZ
102}
103
104/* open callback */
105static int snd_bcm2835_playback_open_generic(
106 struct snd_pcm_substream *substream, int spdif)
107{
108 struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
109 struct snd_pcm_runtime *runtime = substream->runtime;
110 struct bcm2835_alsa_stream *alsa_stream;
111 int idx;
112 int err;
113
23b028c8
MZ
114
115 if (mutex_lock_interruptible(&chip->audio_mutex)) {
116 audio_error("Interrupted whilst waiting for lock\n");
117 return -EINTR;
118 }
119 audio_info("Alsa open (%d)\n", substream->number);
120 idx = substream->number;
121
122 if (spdif && chip->opened) {
123 err = -EBUSY;
124 goto out;
125 } else if (!spdif && (chip->opened & (1 << idx))) {
126 err = -EBUSY;
127 goto out;
128 }
84472ecd 129 if (idx >= MAX_SUBSTREAMS) {
23b028c8
MZ
130 audio_error
131 ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
132 idx, MAX_SUBSTREAMS);
133 err = -ENODEV;
134 goto out;
135 }
136
137 /* Check if we are ready */
138 if (!(chip->avail_substreams & (1 << idx))) {
139 /* We are not ready yet */
140 audio_error("substream(%d) device is not ready yet\n", idx);
141 err = -EAGAIN;
142 goto out;
143 }
144
145 alsa_stream = kzalloc(sizeof(*alsa_stream), GFP_KERNEL);
146 if (!alsa_stream) {
147 err = -ENOMEM;
148 goto out;
149 }
150
151 /* Initialise alsa_stream */
152 alsa_stream->chip = chip;
153 alsa_stream->substream = substream;
154 alsa_stream->idx = idx;
155
23b028c8
MZ
156 spin_lock_init(&alsa_stream->lock);
157
23b028c8
MZ
158 err = bcm2835_audio_open(alsa_stream);
159 if (err) {
160 kfree(alsa_stream);
161 goto out;
162 }
163 runtime->private_data = alsa_stream;
164 runtime->private_free = snd_bcm2835_playback_free;
165 if (spdif) {
166 runtime->hw = snd_bcm2835_playback_spdif_hw;
167 } else {
168 /* clear spdif status, as we are not in spdif mode */
169 chip->spdif_status = 0;
170 runtime->hw = snd_bcm2835_playback_hw;
171 }
172 /* minimum 16 bytes alignment (for vchiq bulk transfers) */
173 snd_pcm_hw_constraint_step(runtime,
174 0,
175 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
176 16);
177
178 chip->alsa_stream[idx] = alsa_stream;
179
180 chip->opened |= (1 << idx);
181 alsa_stream->open = 1;
182 alsa_stream->draining = 1;
183
184out:
185 mutex_unlock(&chip->audio_mutex);
186
23b028c8
MZ
187
188 return err;
189}
190
191static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
192{
193 return snd_bcm2835_playback_open_generic(substream, 0);
194}
195
196static int snd_bcm2835_playback_spdif_open(struct snd_pcm_substream *substream)
197{
198 return snd_bcm2835_playback_open_generic(substream, 1);
199}
200
201/* close callback */
202static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
203{
204 /* the hardware-specific codes will be here */
205
206 struct bcm2835_chip *chip;
207 struct snd_pcm_runtime *runtime;
208 struct bcm2835_alsa_stream *alsa_stream;
209
23b028c8
MZ
210
211 chip = snd_pcm_substream_chip(substream);
212 if (mutex_lock_interruptible(&chip->audio_mutex)) {
213 audio_error("Interrupted whilst waiting for lock\n");
214 return -EINTR;
215 }
216 runtime = substream->runtime;
217 alsa_stream = runtime->private_data;
218
219 audio_info("Alsa close\n");
220
221 /*
222 * Call stop if it's still running. This happens when app
223 * is force killed and we don't get a stop trigger.
224 */
225 if (alsa_stream->running) {
226 int err;
227 err = bcm2835_audio_stop(alsa_stream);
228 alsa_stream->running = 0;
229 if (err)
230 audio_error(" Failed to STOP alsa device\n");
231 }
232
233 alsa_stream->period_size = 0;
234 alsa_stream->buffer_size = 0;
235
236 if (alsa_stream->open) {
237 alsa_stream->open = 0;
238 bcm2835_audio_close(alsa_stream);
239 }
240 if (alsa_stream->chip)
241 alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
242 /*
243 * Do not free up alsa_stream here, it will be freed up by
244 * runtime->private_free callback we registered in *_open above
245 */
246
247 chip->opened &= ~(1 << substream->number);
248
249 mutex_unlock(&chip->audio_mutex);
23b028c8
MZ
250
251 return 0;
252}
253
254/* hw_params callback */
255static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
256 struct snd_pcm_hw_params *params)
257{
258 struct snd_pcm_runtime *runtime = substream->runtime;
259 struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
260 int err;
261
23b028c8
MZ
262
263 err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
264 if (err < 0) {
265 audio_error
266 (" pcm_lib_malloc failed to allocated pages for buffers\n");
267 return err;
268 }
269
270 alsa_stream->channels = params_channels(params);
271 alsa_stream->params_rate = params_rate(params);
272 alsa_stream->pcm_format_width = snd_pcm_format_width(params_format(params));
23b028c8
MZ
273
274 return err;
275}
276
277/* hw_free callback */
278static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)
279{
23b028c8
MZ
280 return snd_pcm_lib_free_pages(substream);
281}
282
283/* prepare callback */
284static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
285{
286 struct bcm2835_chip *chip = snd_pcm_substream_chip(substream);
287 struct snd_pcm_runtime *runtime = substream->runtime;
288 struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
289 int channels;
290 int err;
291
23b028c8
MZ
292
293 if (mutex_lock_interruptible(&chip->audio_mutex))
294 return -EINTR;
295
296 /* notify the vchiq that it should enter spdif passthrough mode by
297 * setting channels=0 (see
298 * https://github.com/raspberrypi/linux/issues/528) */
299 if (chip->spdif_status & IEC958_AES0_NONAUDIO)
300 channels = 0;
301 else
302 channels = alsa_stream->channels;
303
304 err = bcm2835_audio_set_params(alsa_stream, channels,
305 alsa_stream->params_rate,
306 alsa_stream->pcm_format_width);
a17b3703 307 if (err < 0)
23b028c8 308 audio_error(" error setting hw params\n");
a17b3703 309
23b028c8
MZ
310
311 bcm2835_audio_setup(alsa_stream);
312
313 /* in preparation of the stream, set the controls (volume level) of the stream */
314 bcm2835_audio_set_ctls(alsa_stream->chip);
315
316
317 memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
318
319 alsa_stream->pcm_indirect.hw_buffer_size =
320 alsa_stream->pcm_indirect.sw_buffer_size =
321 snd_pcm_lib_buffer_bytes(substream);
322
323 alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
324 alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
325 alsa_stream->pos = 0;
326
327 audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
328 alsa_stream->buffer_size, alsa_stream->period_size,
329 alsa_stream->pos, runtime->frame_bits);
330
331 mutex_unlock(&chip->audio_mutex);
23b028c8
MZ
332 return 0;
333}
334
335static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream,
336 struct snd_pcm_indirect *rec, size_t bytes)
337{
338 struct snd_pcm_runtime *runtime = substream->runtime;
339 struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
340 void *src = (void *) (substream->runtime->dma_area + rec->sw_data);
341 int err;
342
343 err = bcm2835_audio_write(alsa_stream, bytes, src);
344 if (err)
345 audio_error(" Failed to transfer to alsa device (%d)\n", err);
346
347}
348
349static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream)
350{
351 struct snd_pcm_runtime *runtime = substream->runtime;
352 struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
353 struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect;
354
355 pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max;
9ce7b9cf
TI
356 return snd_pcm_indirect_playback_transfer(substream, pcm_indirect,
357 snd_bcm2835_pcm_transfer);
23b028c8
MZ
358}
359
360/* trigger callback */
361static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
362{
363 struct snd_pcm_runtime *runtime = substream->runtime;
364 struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
365 int err = 0;
366
23b028c8
MZ
367
368 switch (cmd) {
369 case SNDRV_PCM_TRIGGER_START:
370 audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n",
371 alsa_stream->running);
372 if (!alsa_stream->running) {
373 err = bcm2835_audio_start(alsa_stream);
374 if (!err) {
375 alsa_stream->pcm_indirect.hw_io =
376 alsa_stream->pcm_indirect.hw_data =
377 bytes_to_frames(runtime,
378 alsa_stream->pos);
379 substream->ops->ack(substream);
380 alsa_stream->running = 1;
381 alsa_stream->draining = 1;
382 } else {
383 audio_error(" Failed to START alsa device (%d)\n", err);
384 }
385 }
386 break;
387 case SNDRV_PCM_TRIGGER_STOP:
388 audio_debug
389 ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n",
390 alsa_stream->running, runtime->status->state == SNDRV_PCM_STATE_DRAINING);
391 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
392 audio_info("DRAINING\n");
393 alsa_stream->draining = 1;
394 } else {
395 audio_info("DROPPING\n");
396 alsa_stream->draining = 0;
397 }
398 if (alsa_stream->running) {
399 err = bcm2835_audio_stop(alsa_stream);
400 if (err != 0)
401 audio_error(" Failed to STOP alsa device (%d)\n", err);
402 alsa_stream->running = 0;
403 }
404 break;
405 default:
406 err = -EINVAL;
407 }
408
23b028c8
MZ
409 return err;
410}
411
412/* pointer callback */
413static snd_pcm_uframes_t
414snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream)
415{
416 struct snd_pcm_runtime *runtime = substream->runtime;
417 struct bcm2835_alsa_stream *alsa_stream = runtime->private_data;
418
23b028c8
MZ
419
420 audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0,
421 frames_to_bytes(runtime, runtime->status->hw_ptr),
422 frames_to_bytes(runtime, runtime->control->appl_ptr),
423 alsa_stream->pos);
424
23b028c8
MZ
425 return snd_pcm_indirect_playback_pointer(substream,
426 &alsa_stream->pcm_indirect,
427 alsa_stream->pos);
428}
429
430static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream,
431 unsigned int cmd, void *arg)
432{
433 int ret = snd_pcm_lib_ioctl(substream, cmd, arg);
cd3d9ece 434
23b028c8
MZ
435 audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream,
436 cmd, arg, arg ? *(unsigned *) arg : 0, ret);
437 return ret;
438}
439
440/* operators */
a4400dfd 441static const struct snd_pcm_ops snd_bcm2835_playback_ops = {
23b028c8
MZ
442 .open = snd_bcm2835_playback_open,
443 .close = snd_bcm2835_playback_close,
444 .ioctl = snd_bcm2835_pcm_lib_ioctl,
445 .hw_params = snd_bcm2835_pcm_hw_params,
446 .hw_free = snd_bcm2835_pcm_hw_free,
447 .prepare = snd_bcm2835_pcm_prepare,
448 .trigger = snd_bcm2835_pcm_trigger,
449 .pointer = snd_bcm2835_pcm_pointer,
450 .ack = snd_bcm2835_pcm_ack,
451};
452
a4400dfd 453static const struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = {
23b028c8
MZ
454 .open = snd_bcm2835_playback_spdif_open,
455 .close = snd_bcm2835_playback_close,
456 .ioctl = snd_bcm2835_pcm_lib_ioctl,
457 .hw_params = snd_bcm2835_pcm_hw_params,
458 .hw_free = snd_bcm2835_pcm_hw_free,
459 .prepare = snd_bcm2835_pcm_prepare,
460 .trigger = snd_bcm2835_pcm_trigger,
461 .pointer = snd_bcm2835_pcm_pointer,
462 .ack = snd_bcm2835_pcm_ack,
463};
464
465/* create a pcm device */
325b5b6c 466int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels)
23b028c8
MZ
467{
468 struct snd_pcm *pcm;
469 int err;
470
23b028c8
MZ
471 mutex_init(&chip->audio_mutex);
472 if (mutex_lock_interruptible(&chip->audio_mutex)) {
473 audio_error("Interrupted whilst waiting for lock\n");
474 return -EINTR;
475 }
325b5b6c 476 err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
23b028c8
MZ
477 if (err < 0)
478 goto out;
479 pcm->private_data = chip;
480 strcpy(pcm->name, "bcm2835 ALSA");
481 chip->pcm = pcm;
482 chip->dest = AUDIO_DEST_AUTO;
483 chip->volume = alsa2chip(0);
484 chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
485 /* set operators */
486 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
487 &snd_bcm2835_playback_ops);
488
489 /* pre-allocation of buffers */
490 /* NOTE: this may fail */
491 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
492 snd_dma_continuous_data(GFP_KERNEL),
493 snd_bcm2835_playback_hw.buffer_bytes_max,
494 snd_bcm2835_playback_hw.buffer_bytes_max);
495
496
497out:
498 mutex_unlock(&chip->audio_mutex);
23b028c8
MZ
499
500 return 0;
501}
502
503int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip)
504{
505 struct snd_pcm *pcm;
506 int err;
507
23b028c8
MZ
508 if (mutex_lock_interruptible(&chip->audio_mutex)) {
509 audio_error("Interrupted whilst waiting for lock\n");
510 return -EINTR;
511 }
512 err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
513 if (err < 0)
514 goto out;
515
516 pcm->private_data = chip;
517 strcpy(pcm->name, "bcm2835 IEC958/HDMI");
518 chip->pcm_spdif = pcm;
519 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
520 &snd_bcm2835_playback_spdif_ops);
521
522 /* pre-allocation of buffers */
523 /* NOTE: this may fail */
524 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
525 snd_dma_continuous_data(GFP_KERNEL),
526 snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max);
527out:
528 mutex_unlock(&chip->audio_mutex);
23b028c8
MZ
529
530 return 0;
531}
325b5b6c
MZ
532
533int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
534 const char *name,
535 enum snd_bcm2835_route route,
536 u32 numchannels)
537{
538 struct snd_pcm *pcm;
539 int err;
540
541 mutex_init(&chip->audio_mutex);
542
543 err = snd_pcm_new(chip->card, name, 0, numchannels,
544 0, &pcm);
545 if (err)
546 return err;
547
548 pcm->private_data = chip;
549 strcpy(pcm->name, name);
550 chip->pcm = pcm;
551 chip->dest = route;
552 chip->volume = alsa2chip(0);
553 chip->mute = CTRL_VOL_UNMUTE;
554
555 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
556 &snd_bcm2835_playback_ops);
557
558 snd_pcm_lib_preallocate_pages_for_all(
559 pcm,
560 SNDRV_DMA_TYPE_CONTINUOUS,
561 snd_dma_continuous_data(GFP_KERNEL),
562 snd_bcm2835_playback_hw.buffer_bytes_max,
563 snd_bcm2835_playback_hw.buffer_bytes_max);
564
565 return 0;
566}
567