static void bcm2835_audio_delayed_init(void *xsc) { struct bcm2835_audio_info *sc; char status[SND_STATUSLEN]; sc = xsc; config_intrhook_disestablish(&sc->intr_hook); bcm2835_audio_init(sc); bcm2835_audio_open(sc); sc->volume = 75; sc->dest = DEST_AUTO; if (mixer_init(sc->dev, &bcmmixer_class, sc)) { device_printf(sc->dev, "mixer_init failed\n"); goto no; } if (pcm_register(sc->dev, sc, 1, 1)) { device_printf(sc->dev, "pcm_register failed\n"); goto no; } pcm_addchan(sc->dev, PCMDIR_PLAY, &bcmchan_class, sc); snprintf(status, SND_STATUSLEN, "at VCHIQ"); pcm_setstatus(sc->dev, status); bcm2835_audio_reset_channel(&sc->pch); bcm2835_audio_create_worker(sc); vchi_audio_sysctl_init(sc); no: ; }
/* open callback */ static int snd_bcm2835_playback_open_generic( struct snd_pcm_substream *substream, int spdif) { struct bcm2835_chip *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct bcm2835_alsa_stream *alsa_stream; int idx; int err; audio_info(" .. IN (%d)\n", substream->number); if (mutex_lock_interruptible(&chip->audio_mutex)) { audio_error("Interrupted whilst waiting for lock\n"); return -EINTR; } audio_info("Alsa open (%d)\n", substream->number); idx = substream->number; if (spdif && chip->opened) { err = -EBUSY; goto out; } else if (!spdif && (chip->opened & (1 << idx))) { err = -EBUSY; goto out; } if (idx >= MAX_SUBSTREAMS) { audio_error ("substream(%d) device doesn't exist max(%d) substreams allowed\n", idx, MAX_SUBSTREAMS); err = -ENODEV; goto out; } /* Check if we are ready */ if (!(chip->avail_substreams & (1 << idx))) { /* We are not ready yet */ audio_error("substream(%d) device is not ready yet\n", idx); err = -EAGAIN; goto out; } alsa_stream = kzalloc(sizeof(*alsa_stream), GFP_KERNEL); if (!alsa_stream) { err = -ENOMEM; goto out; } /* Initialise alsa_stream */ alsa_stream->chip = chip; alsa_stream->substream = substream; alsa_stream->idx = idx; sema_init(&alsa_stream->buffers_update_sem, 0); sema_init(&alsa_stream->control_sem, 0); spin_lock_init(&alsa_stream->lock); err = bcm2835_audio_open(alsa_stream); if (err) { kfree(alsa_stream); goto out; } runtime->private_data = alsa_stream; runtime->private_free = snd_bcm2835_playback_free; if (spdif) { runtime->hw = snd_bcm2835_playback_spdif_hw; } else { /* clear spdif status, as we are not in spdif mode */ chip->spdif_status = 0; runtime->hw = snd_bcm2835_playback_hw; } /* minimum 16 bytes alignment (for vchiq bulk transfers) */ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16); chip->alsa_stream[idx] = alsa_stream; chip->opened |= (1 << idx); alsa_stream->open = 1; alsa_stream->draining = 1; out: mutex_unlock(&chip->audio_mutex); audio_info(" .. OUT =%d\n", err); return err; }
/* open callback */ static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream) { bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; bcm2835_alsa_stream_t *alsa_stream; int idx; int err; audio_info(" .. IN (%d)\n", substream->number); audio_warning("Alsa open (%d)\n", substream->number); idx = substream->number; if (idx > MAX_SUBSTREAMS) { audio_error ("substream(%d) device doesn't exist max(%d) substreams allowed\n", idx, MAX_SUBSTREAMS); err = -ENODEV; goto out; } /* Check if we are ready */ if (!(chip->avail_substreams & (1 << idx))) { /* We are not ready yet */ audio_error("substream(%d) device is not ready yet\n", idx); err = -EAGAIN; goto out; } alsa_stream = kzalloc(sizeof(bcm2835_alsa_stream_t), GFP_KERNEL); if (alsa_stream == NULL) { return -ENOMEM; } /* Initialise alsa_stream */ alsa_stream->chip = chip; alsa_stream->substream = substream; alsa_stream->idx = idx; chip->alsa_stream[idx] = alsa_stream; sema_init(&alsa_stream->buffers_update_sem, 0); sema_init(&alsa_stream->control_sem, 0); spin_lock_init(&alsa_stream->lock); /* Enabled in start trigger, called on each "fifo irq" after that */ alsa_stream->enable_fifo_irq = 0; alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq; runtime->private_data = alsa_stream; runtime->private_free = snd_bcm2835_playback_free; runtime->hw = snd_bcm2835_playback_hw; /* minimum 16 bytes alignment (for vchiq bulk transfers) */ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16); err = bcm2835_audio_open(alsa_stream); if (err != 0) { kfree(alsa_stream); return err; } alsa_stream->open = 1; alsa_stream->draining = 1; out: audio_info(" .. OUT =%d\n", err); return err; }