// SPDX-License-Identifier: GPL-2.0+ /* * virtio-snd: Virtio sound device * Copyright (C) 2021 OpenSynergy GmbH */ #include <sound/pcm_params.h> #include "virtio_card.h" /* * I/O messages lifetime * --------------------- * * Allocation: * Messages are initially allocated in the ops->hw_params() after the size and * number of periods have been successfully negotiated. * * Freeing: * Messages can be safely freed after the queue has been successfully flushed * (RELEASE command in the ops->sync_stop()) and the ops->hw_free() has been * called. * * When the substream stops, the ops->sync_stop() waits until the device has * completed all pending messages. This wait can be interrupted either by a * signal or due to a timeout. In this case, the device can still access * messages even after calling ops->hw_free(). It can also issue an interrupt, * and the interrupt handler will also try to access message structures. * * Therefore, freeing of already allocated messages occurs: * * - in ops->hw_params(), if this operator was called several times in a row, * or if ops->hw_free() failed to free messages previously; * * - in ops->hw_free(), if the queue has been successfully flushed; * * - in dev->release(). */ /* Map for converting ALSA format to VirtIO format. */ struct virtsnd_a2v_format { … }; static const struct virtsnd_a2v_format g_a2v_format_map[] = …; /* Map for converting ALSA frame rate to VirtIO frame rate. */ struct virtsnd_a2v_rate { … }; static const struct virtsnd_a2v_rate g_a2v_rate_map[] = …; static int virtsnd_pcm_sync_stop(struct snd_pcm_substream *substream); /** * virtsnd_pcm_open() - Open the PCM substream. * @substream: Kernel ALSA substream. * * Context: Process context. * Return: 0 on success, -errno on failure. */ static int virtsnd_pcm_open(struct snd_pcm_substream *substream) { … } /** * virtsnd_pcm_close() - Close the PCM substream. * @substream: Kernel ALSA substream. * * Context: Process context. * Return: 0. */ static int virtsnd_pcm_close(struct snd_pcm_substream *substream) { … } /** * virtsnd_pcm_dev_set_params() - Set the parameters of the PCM substream on * the device side. * @vss: VirtIO PCM substream. * @buffer_bytes: Size of the hardware buffer. * @period_bytes: Size of the hardware period. * @channels: Selected number of channels. * @format: Selected sample format (SNDRV_PCM_FORMAT_XXX). * @rate: Selected frame rate. * * Context: Any context that permits to sleep. * Return: 0 on success, -errno on failure. */ static int virtsnd_pcm_dev_set_params(struct virtio_pcm_substream *vss, unsigned int buffer_bytes, unsigned int period_bytes, unsigned int channels, snd_pcm_format_t format, unsigned int rate) { … } /** * virtsnd_pcm_hw_params() - Set the parameters of the PCM substream. * @substream: Kernel ALSA substream. * @hw_params: Hardware parameters. * * Context: Process context. * Return: 0 on success, -errno on failure. */ static int virtsnd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { … } /** * virtsnd_pcm_hw_free() - Reset the parameters of the PCM substream. * @substream: Kernel ALSA substream. * * Context: Process context. * Return: 0 */ static int virtsnd_pcm_hw_free(struct snd_pcm_substream *substream) { … } /** * virtsnd_pcm_prepare() - Prepare the PCM substream. * @substream: Kernel ALSA substream. * * Context: Process context. * Return: 0 on success, -errno on failure. */ static int virtsnd_pcm_prepare(struct snd_pcm_substream *substream) { … } /** * virtsnd_pcm_trigger() - Process command for the PCM substream. * @substream: Kernel ALSA substream. * @command: Substream command (SNDRV_PCM_TRIGGER_XXX). * * Context: Any context. Takes and releases the VirtIO substream spinlock. * May take and release the tx/rx queue spinlock. * Return: 0 on success, -errno on failure. */ static int virtsnd_pcm_trigger(struct snd_pcm_substream *substream, int command) { … } /** * virtsnd_pcm_sync_stop() - Synchronous PCM substream stop. * @substream: Kernel ALSA substream. * * The function can be called both from the upper level or from the driver * itself. * * Context: Process context. Takes and releases the VirtIO substream spinlock. * Return: 0 on success, -errno on failure. */ static int virtsnd_pcm_sync_stop(struct snd_pcm_substream *substream) { … } /** * virtsnd_pcm_pb_pointer() - Get the current hardware position for the PCM * substream for playback. * @substream: Kernel ALSA substream. * * Context: Any context. * Return: Hardware position in frames inside [0 ... buffer_size) range. */ static snd_pcm_uframes_t virtsnd_pcm_pb_pointer(struct snd_pcm_substream *substream) { … } /** * virtsnd_pcm_cp_pointer() - Get the current hardware position for the PCM * substream for capture. * @substream: Kernel ALSA substream. * * Context: Any context. * Return: Hardware position in frames inside [0 ... buffer_size) range. */ static snd_pcm_uframes_t virtsnd_pcm_cp_pointer(struct snd_pcm_substream *substream) { … } static void virtsnd_pcm_trans_copy(struct snd_pcm_substream *substream, struct snd_pcm_indirect *rec, size_t bytes) { … } static int virtsnd_pcm_pb_ack(struct snd_pcm_substream *substream) { … } static int virtsnd_pcm_cp_ack(struct snd_pcm_substream *substream) { … } /* PCM substream operators map. */ const struct snd_pcm_ops virtsnd_pcm_ops[] = …;