From: "Philippe Mathieu-Daudé" <philmd@linaro.org>
To: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>,
qemu-devel@nongnu.org
Cc: "Igor Skalkin" <Igor.Skalkin@opensynergy.com>,
"Anton Yakovlev" <Anton.Yakovlev@opensynergy.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Gerd Hoffmann" <kraxel@redhat.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
"Daniel P. Berrangé" <berrange@redhat.com>,
"Eduardo Habkost" <eduardo@habkost.net>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Volker Rümelin" <vr_qemu@t-online.de>,
"Kővágó, Zoltán" <DirtY.iCE.hu@gmail.com>
Subject: Re: [PATCH v2 0/3] Add VIRTIO sound card
Date: Sun, 16 Jul 2023 19:18:37 +0200 [thread overview]
Message-ID: <73f46bd9-239a-ed6f-d3da-d4d7666b9263@linaro.org> (raw)
In-Reply-To: <xqes1.ursoa6rc1qb6@linaro.org>
Cc'ing more contributors involved with audio in general.
On 13/7/23 13:00, Manos Pitsidianakis wrote:
> Ping
>
> Patch series on patchew:
> https://patchew.org/QEMU/cover.1686238728.git.manos.pitsidianakis@linaro.org/
>
> Patch series on lore:
> https://lore.kernel.org/qemu-devel/cover.1686238728.git.manos.pitsidianakis@linaro.org/
>
>
> On Thu, 08 Jun 2023 18:56, Manos Pitsidianakis
> <manos.pitsidianakis@linaro.org> wrote:
>> This patch series adds an audio device implementing the recent virtio
>> sound spec (1.2) and a corresponding PCI wrapper device.
>>
>> Main differences with v1 patch
>> <20230526204845.673031-1-manos.pitsidianakis@linaro.org>:
>>
>> - Split virtio-snd and virtio-snd-pci devices to two commits
>> - Added audio capture support
>>
>> Known problems (On pipewire at least):
>>
>> - Stereo recording results in one channel with the recording + a
>> ticking kind of artifact and one channel that has no artifacts, just
>> the recording.
>>
>> Manos Pitsidianakis (3):
>> Add virtio-sound device
>> Add virtio-sound-pci device
>> Implement audio capture in virtio-snd device
>>
>> MAINTAINERS | 6 +
>> hw/virtio/Kconfig | 5 +
>> hw/virtio/meson.build | 2 +
>> hw/virtio/trace-events | 22 +
>> hw/virtio/virtio-snd-pci.c | 102 +++
>> hw/virtio/virtio-snd.c | 1290 ++++++++++++++++++++++++++++++++
>> include/hw/pci/pci.h | 1 +
>> include/hw/virtio/virtio-snd.h | 194 +++++
>> softmmu/qdev-monitor.c | 1 +
>> 9 files changed, 1623 insertions(+)
>> create mode 100644 hw/virtio/virtio-snd-pci.c
>> create mode 100644 hw/virtio/virtio-snd.c
>> create mode 100644 include/hw/virtio/virtio-snd.h
>>
>> Range-diff against v1:
>> 1: 652c7d2d01 ! 1: 95d564fc1f Add virtio-sound and virtio-sound-pci
>> devices
>> @@ Metadata
>> Author: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
>> ## Commit message ##
>> - Add virtio-sound and virtio-sound-pci devices
>> + Add virtio-sound device
>> This patch adds an audio device implementing the recent virtio
>> sound
>> - spec (1.2) and a corresponding PCI wrapper device.
>> + spec (1.2).
>> PCM functionality is implemented, and jack[0], chmaps[1]
>> messages are
>> - at the moment ignored.
>> -
>> - To test this, you'll need a >6.0 kernel compiled with the
>> virtio-snd
>> - flag enabled, which distros have off by default.
>> -
>> - Use with following flags in the invocation:
>> -
>> - -device virtio-sound-pci,disable-legacy=on
>> -
>> - And an audio backend listed with `-audio driver=help` that
>> works on
>> - your host machine, e.g.:
>> -
>> - Pulseaudio:
>> - -audio
>> driver=pa,model=virtio-sound,server=/run/user/1000/pulse/native
>> - sdl:
>> - -audio driver=sdl,model=virtio-sound
>> - coreaudio:
>> - -audio driver=coreaudio,model=virtio-sound
>> - etc.
>> -
>> - You can use speaker-test from alsa-tools to play noise, sines, or
>> - WAV files.
>> + at the moment left unimplemented.
>> PS2: This patch was based on a draft patch posted by
>> OpenSynergy in 2019. [2]
>> @@ Commit message
>> Signed-off-by: Igor Skalkin <Igor.Skalkin@opensynergy.com>
>> Signed-off-by: Anton Yakovlev <Anton.Yakovlev@opensynergy.com>
>> + ## MAINTAINERS ##
>> +@@ MAINTAINERS: F: hw/virtio/virtio-mem-pci.h
>> + F: hw/virtio/virtio-mem-pci.c
>> + F: include/hw/virtio/virtio-mem.h
>> + ++virtio-snd
>> ++M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
>> ++S: Supported
>> ++F: hw/virtio/virtio-snd*.c
>> ++F: include/hw/virtio/virtio-snd.h
>> ++
>> + nvme
>> + M: Keith Busch <kbusch@kernel.org>
>> + M: Klaus Jensen <its@irrelevant.dk>
>> +
>> ## hw/virtio/Kconfig ##
>> @@ hw/virtio/Kconfig: config VIRTIO_PCI
>> depends on PCI
>> @@ hw/virtio/Kconfig: config VIRTIO_PCI
>> select VIRTIO
>> ## hw/virtio/meson.build ##
>> -@@ hw/virtio/meson.build: virtio_pci_ss.add(when:
>> 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-serial-pc
>> - virtio_pci_ss.add(when: 'CONFIG_VIRTIO_PMEM', if_true:
>> files('virtio-pmem-pci.c'))
>> - virtio_pci_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true:
>> files('virtio-iommu-pci.c'))
>> - virtio_pci_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true:
>> files('virtio-mem-pci.c'))
>> -+virtio_pci_ss.add(when: 'CONFIG_VIRTIO_SND', if_true:
>> files('virtio-snd-pci.c'))
>> - virtio_pci_ss.add(when: 'CONFIG_VHOST_VDPA_DEV', if_true:
>> files('vdpa-dev-pci.c'))
>> - - specific_virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI',
>> if_true: virtio_pci_ss)
>> @@ hw/virtio/meson.build: softmmu_ss.add(when: 'CONFIG_VIRTIO',
>> if_false: files('virtio-stub.c'))
>> softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c'))
>> softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('virtio-stub.c'))
>> @@ hw/virtio/trace-events: virtio_pmem_flush_done(int type) "fsync
>> return=%d"
>> +virtio_snd_handle_pcm_info(int stream) "VIRTIO_SND_R_PCM_INFO
>> called for stream %d"
>> +virtio_snd_handle_pcm_set_params(int stream)
>> "VIRTIO_SND_PCM_SET_PARAMS called for stream %d"
>> +virtio_snd_handle_pcm_start_stop(const char *code, int stream)
>> "%s called for stream %d"
>> -+virtio_snd_handle_pcm_release(int stream) "VIRTIO_SND_PCM_RELEASE
>> called for stream %id"
>> ++virtio_snd_handle_pcm_release(int stream) "VIRTIO_SND_PCM_RELEASE
>> called for stream %d"
>> +virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called"
>> +virtio_snd_handle_xfer(void) "tx/rx queue callback called"
>> -+virtio_snd_handle_xfer_elem(const char * k) "xfer handled in
>> virtio_snd_pcm_%s"
>> +virtio_snd_handle_event(void) "event queue callback called"
>> -+virtio_snd_cpu_is_stopped(void *snd, int size) "snd %p: cpu is
>> stopped, dropping %d bytes"
>> +virtio_snd_realize(void *snd) "snd %p: realize"
>> -+virtio_snd_unrealize(void *snd) "snd %p: realize"
>> ++virtio_snd_unrealize(void *snd) "snd %p: unrealize"
>> +virtio_snd_get_features(void *vdev, uint64_t features) "snd %p:
>> get_features 0x%"PRIx64
>> +virtio_snd_get_config(void *vdev, uint32_t jacks, uint32_t
>> streams, uint32_t chmaps) "snd %p: get_config jacks=%d streams=%d
>> chmaps=%d"
>> +virtio_snd_set_config(void *vdev, uint32_t jacks, uint32_t
>> new_jacks, uint32_t streams, uint32_t new_streams, uint32_t chmaps,
>> uint32_t new_chmaps) "snd %p: set_config jacks from %d->%d, streams
>> from %d->%d, chmaps from %d->%d"
>> @@ hw/virtio/trace-events: virtio_pmem_flush_done(int type) "fsync
>> return=%d"
>> +virtio_snd_vm_state_stopped(void) "vm state stopped"
>> +virtio_snd_handle_code(int val, const char *code) "ctrl code msg
>> val = %d == %s"
>> - ## hw/virtio/virtio-snd-pci.c (new) ##
>> -@@
>> -+/*
>> -+ * VIRTIO Sound Device PCI Bindings
>> -+ *
>> -+ * Copyright (c) 2023 Emmanouil Pitsidianakis
>> <manos.pitsidianakis@linaro.org>
>> -+ *
>> -+ * This work is licensed under the terms of the GNU GPL, version
>> 2 or
>> -+ * (at your option) any later version. See the COPYING file in the
>> -+ * top-level directory.
>> -+ */
>> -+
>> -+#include "qemu/osdep.h"
>> -+#include "hw/audio/soundhw.h"
>> -+#include "hw/virtio/virtio-pci.h"
>> -+#include "hw/virtio/virtio-snd.h"
>> -+
>> -+typedef struct VirtIOSoundPCI VirtIOSoundPCI;
>> -+
>> -+/*
>> -+ * virtio-snd-pci: This extends VirtioPCIProxy.
>> -+ */
>> -+#define TYPE_VIRTIO_SND_PCI "virtio-sound-pci-base"
>> -+DECLARE_INSTANCE_CHECKER(VirtIOSoundPCI, VIRTIO_SOUND_PCI,
>> -+ TYPE_VIRTIO_SND_PCI)
>> -+
>> -+struct VirtIOSoundPCI {
>> -+ VirtIOPCIProxy parent;
>> -+ VirtIOSound vdev;
>> -+};
>> -+
>> -+static Property virtio_snd_pci_properties[] = {
>> -+ DEFINE_PROP_UINT32("class", VirtIOPCIProxy, class_code, 0),
>> -+ DEFINE_PROP_END_OF_LIST(),
>> -+};
>> -+
>> -+static const char *audiodev_id;
>> -+
>> -+static int virtio_snd_init_pci(PCIBus *init_bus, const char
>> *audiodev)
>> -+{
>> -+ audiodev_id = audiodev;
>> -+ return 0;
>> -+}
>> -+
>> -+static void virtio_snd_pci_realize(VirtIOPCIProxy *vpci_dev,
>> Error **errp)
>> -+{
>> -+ VirtIOSoundPCI *dev = VIRTIO_SOUND_PCI(vpci_dev);
>> -+ DeviceState *vdev = DEVICE(&dev->vdev);
>> -+ VirtIOSound *vsnd = VIRTIO_SND(&dev->vdev);
>> -+
>> -+ /*
>> -+ * According to spec, non-legacy virtio PCI devices are
>> always little
>> -+ * endian
>> -+ */
>> -+ vsnd->virtio_access_is_big_endian = false;
>> -+
>> -+
>> -+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), errp);
>> -+
>> -+
>> -+ qdev_prop_set_string(vdev, "audiodev", audiodev_id);
>> -+ AUD_register_card ("virtio-sound", &dev->vdev.card);
>> -+
>> -+ object_property_set_bool(OBJECT(vdev), "realized", true, errp);
>> -+}
>> -+
>> -+static void virtio_snd_pci_class_init(ObjectClass *klass, void
>> *data)
>> -+{
>> -+ DeviceClass *dc = DEVICE_CLASS(klass);
>> -+ VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
>> -+ PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
>> -+
>> -+ vpciklass->realize = virtio_snd_pci_realize;
>> -+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
>> -+
>> -+ pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
>> -+ pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SND;
>> -+ pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
>> -+ pcidev_k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
>> -+ device_class_set_props(dc, virtio_snd_pci_properties);
>> -+}
>> -+
>> -+static void virtio_snd_pci_instance_init(Object *obj)
>> -+{
>> -+ VirtIOSoundPCI *dev = VIRTIO_SOUND_PCI(obj);
>> -+
>> -+ virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
>> -+ TYPE_VIRTIO_SND);
>> -+}
>> -+
>> -+static const VirtioPCIDeviceTypeInfo virtio_snd_pci_info = {
>> -+ .base_name = TYPE_VIRTIO_SND_PCI,
>> -+ .generic_name = "virtio-sound-pci",
>> -+ .instance_size = sizeof(VirtIOSoundPCI),
>> -+ .instance_init = virtio_snd_pci_instance_init,
>> -+ .class_init = virtio_snd_pci_class_init,
>> -+};
>> -+
>> -+static void virtio_snd_pci_register(void)
>> -+{
>> -+ virtio_pci_types_register(&virtio_snd_pci_info);
>> -+ pci_register_soundhw("virtio-sound", "Virtio Sound Device",
>> -+ virtio_snd_init_pci);
>> -+}
>> -+
>> -+type_init(virtio_snd_pci_register);
>> -
>> ## hw/virtio/virtio-snd.c (new) ##
>> @@
>> +/*
>> @@ hw/virtio/virtio-snd.c (new)
>> +#define VIRTIO_SOUND_STREAM_DEFAULT 1
>> +#define VIRTIO_SOUND_CHMAP_DEFAULT 0
>> +
>> -+#define VIRTIO_SOUND_HDA_FN_NID_OUT 0
>> -+#define VIRTIO_SOUND_HDA_FN_NID_IN 1
>> ++#define VIRTIO_SOUND_HDA_FN_NID 0
>> +
>> +static const VMStateDescription vmstate_virtio_snd_device = {
>> + .name = TYPE_VIRTIO_SND,
>> @@ hw/virtio/virtio-snd.c (new)
>> +uint32_t virtio_snd_pcm_set_params_impl(VirtIOSound *s,
>> + virtio_snd_pcm_set_params
>> *params)
>> +{
>> ++ uint32_t supported_formats, supported_rates;
>> ++ VirtIOSoundPCMParams *st_params;
>> + uint32_t stream_id = params->hdr.stream_id;
>> ++
>> + if (stream_id > s->snd_conf.streams || !(s->pcm->pcm_params)) {
>> + virtio_error(VIRTIO_DEVICE(s), "Streams have not been
>> initialized.\n");
>> + return VIRTIO_SND_S_BAD_MSG;
>> @@ hw/virtio/virtio-snd.c (new)
>> + if (!s->pcm->pcm_params[stream_id]) {
>> + s->pcm->pcm_params[stream_id] =
>> g_new0(VirtIOSoundPCMParams, 1);
>> + }
>> -+ VirtIOSoundPCMParams *st_params =
>> virtio_snd_pcm_get_params(s, stream_id);
>> ++ st_params = virtio_snd_pcm_get_params(s, stream_id);
>> +
>> + st_params->features = params->features;
>> + st_params->buffer_bytes = params->buffer_bytes;
>> @@ hw/virtio/virtio-snd.c (new)
>> + }
>> + st_params->channels = params->channels;
>> +
>> -+ uint32_t supported_formats = 1 << VIRTIO_SND_PCM_FMT_S8
>> -+ | 1 << VIRTIO_SND_PCM_FMT_U8
>> -+ | 1 << VIRTIO_SND_PCM_FMT_S16
>> -+ | 1 << VIRTIO_SND_PCM_FMT_U16
>> -+ | 1 << VIRTIO_SND_PCM_FMT_S32
>> -+ | 1 << VIRTIO_SND_PCM_FMT_U32
>> -+ | 1 << VIRTIO_SND_PCM_FMT_FLOAT;
>> -+
>> -+ uint32_t supported_rates = 1 << VIRTIO_SND_PCM_RATE_5512
>> -+ | 1 << VIRTIO_SND_PCM_RATE_8000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_11025
>> -+ | 1 << VIRTIO_SND_PCM_RATE_16000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_22050
>> -+ | 1 << VIRTIO_SND_PCM_RATE_32000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_44100
>> -+ | 1 << VIRTIO_SND_PCM_RATE_48000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_64000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_88200
>> -+ | 1 << VIRTIO_SND_PCM_RATE_96000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_176400
>> -+ | 1 << VIRTIO_SND_PCM_RATE_192000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_384000;
>> ++ supported_formats = 1 << VIRTIO_SND_PCM_FMT_S8
>> ++ | 1 << VIRTIO_SND_PCM_FMT_U8
>> ++ | 1 << VIRTIO_SND_PCM_FMT_S16
>> ++ | 1 << VIRTIO_SND_PCM_FMT_U16
>> ++ | 1 << VIRTIO_SND_PCM_FMT_S32
>> ++ | 1 << VIRTIO_SND_PCM_FMT_U32
>> ++ | 1 << VIRTIO_SND_PCM_FMT_FLOAT;
>> ++
>> ++ supported_rates = 1 << VIRTIO_SND_PCM_RATE_5512
>> ++ | 1 << VIRTIO_SND_PCM_RATE_8000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_11025
>> ++ | 1 << VIRTIO_SND_PCM_RATE_16000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_22050
>> ++ | 1 << VIRTIO_SND_PCM_RATE_32000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_44100
>> ++ | 1 << VIRTIO_SND_PCM_RATE_48000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_64000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_88200
>> ++ | 1 << VIRTIO_SND_PCM_RATE_96000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_176400
>> ++ | 1 << VIRTIO_SND_PCM_RATE_192000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_384000;
>> +
>> + if (!(supported_formats & (1 << params->format))) {
>> + error_report("Stream format is not supported.");
>> @@ hw/virtio/virtio-snd.c (new)
>> + st_params->rate = params->rate;
>> + st_params->period_bytes = params->period_bytes;
>> + st_params->buffer_bytes = params->buffer_bytes;
>> ++
>> + return VIRTIO_SND_S_OK;
>> +}
>> +
>> @@ hw/virtio/virtio-snd.c (new)
>> +{
>> + virtio_snd_pcm_set_params req;
>> + uint32_t sz;
>> ++
>> + sz = iov_to_buf(cmd->elem->out_sg,
>> + cmd->elem->out_num,
>> + 0,
>> @@ hw/virtio/virtio-snd.c (new)
>> +
>> + trace_virtio_snd_handle_pcm_set_params(req.hdr.stream_id);
>> + cmd->resp.code = virtio_snd_pcm_set_params_impl(s, &req);
>> ++
>> + return;
>> +}
>> +
>> @@ hw/virtio/virtio-snd.c (new)
>> +static void virtio_snd_get_qemu_audsettings(audsettings *as,
>> + VirtIOSoundPCMParams
>> *params)
>> +{
>> -+ as->nchannels = params->channels;
>> ++ as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels);
>> + as->fmt = virtio_snd_get_qemu_format(params->format);
>> + as->freq = virtio_snd_get_qemu_freq(params->rate);
>> + as->endianness = AUDIO_HOST_ENDIANNESS;
>> @@ hw/virtio/virtio-snd.c (new)
>> + */
>> +static uint32_t virtio_snd_pcm_prepare_impl(VirtIOSound *s,
>> uint32_t stream_id)
>> +{
>> ++ audsettings as;
>> ++ uint32_t supported_formats, supported_rates;
>> ++ VirtIOSoundPCMParams *params;
>> ++ VirtIOSoundPCMStream *stream;
>> ++
>> + if (!s->pcm->streams
>> + || !s->pcm->pcm_params
>> + || !s->pcm->pcm_params[stream_id]) {
>> + return VIRTIO_SND_S_BAD_MSG;
>> + }
>> +
>> -+ uint32_t supported_formats = 1 << VIRTIO_SND_PCM_FMT_S8
>> -+ | 1 << VIRTIO_SND_PCM_FMT_U8
>> -+ | 1 << VIRTIO_SND_PCM_FMT_S16
>> -+ | 1 << VIRTIO_SND_PCM_FMT_U16
>> -+ | 1 << VIRTIO_SND_PCM_FMT_S32
>> -+ | 1 << VIRTIO_SND_PCM_FMT_U32
>> -+ | 1 << VIRTIO_SND_PCM_FMT_FLOAT;
>> -+
>> -+ uint32_t supported_rates = 1 << VIRTIO_SND_PCM_RATE_5512
>> -+ | 1 << VIRTIO_SND_PCM_RATE_8000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_11025
>> -+ | 1 << VIRTIO_SND_PCM_RATE_16000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_22050
>> -+ | 1 << VIRTIO_SND_PCM_RATE_32000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_44100
>> -+ | 1 << VIRTIO_SND_PCM_RATE_48000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_64000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_88200
>> -+ | 1 << VIRTIO_SND_PCM_RATE_96000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_176400
>> -+ | 1 << VIRTIO_SND_PCM_RATE_192000
>> -+ | 1 << VIRTIO_SND_PCM_RATE_384000;
>> -+
>> -+ VirtIOSoundPCMParams *params = virtio_snd_pcm_get_params(s,
>> stream_id);
>> ++ supported_formats = 1 << VIRTIO_SND_PCM_FMT_S8
>> ++ | 1 << VIRTIO_SND_PCM_FMT_U8
>> ++ | 1 << VIRTIO_SND_PCM_FMT_S16
>> ++ | 1 << VIRTIO_SND_PCM_FMT_U16
>> ++ | 1 << VIRTIO_SND_PCM_FMT_S32
>> ++ | 1 << VIRTIO_SND_PCM_FMT_U32
>> ++ | 1 << VIRTIO_SND_PCM_FMT_FLOAT;
>> ++
>> ++ supported_rates = 1 << VIRTIO_SND_PCM_RATE_5512
>> ++ | 1 << VIRTIO_SND_PCM_RATE_8000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_11025
>> ++ | 1 << VIRTIO_SND_PCM_RATE_16000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_22050
>> ++ | 1 << VIRTIO_SND_PCM_RATE_32000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_44100
>> ++ | 1 << VIRTIO_SND_PCM_RATE_48000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_64000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_88200
>> ++ | 1 << VIRTIO_SND_PCM_RATE_96000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_176400
>> ++ | 1 << VIRTIO_SND_PCM_RATE_192000
>> ++ | 1 << VIRTIO_SND_PCM_RATE_384000;
>> ++
>> ++ params = virtio_snd_pcm_get_params(s, stream_id);
>> + assert(params);
>> +
>> -+ VirtIOSoundPCMStream *stream = g_new0(VirtIOSoundPCMStream, 1);
>> ++ virtio_snd_get_qemu_audsettings(&as, params);
>> ++
>> ++ stream = g_new0(VirtIOSoundPCMStream, 1);
>> +
>> ++ stream->id = stream_id;
>> + stream->pcm = s->pcm;
>> + stream->direction = stream_id < s->snd_conf.streams / 2 +
>> + (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT :
>> VIRTIO_SND_D_INPUT;
>> -+ stream->info.hdr.hda_fn_nid = stream->direction ==
>> VIRTIO_SND_D_OUTPUT ?
>> -+ VIRTIO_SOUND_HDA_FN_NID_OUT : VIRTIO_SOUND_HDA_FN_NID_IN;
>> ++ stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID;
>> + stream->features = 0;
>> + stream->channels_min = 1;
>> -+ stream->channels_max = AUDIO_MAX_CHANNELS;
>> ++ stream->channels_max = as.nchannels;
>> + stream->formats = supported_formats;
>> + stream->rates = supported_rates;
>> + stream->s = s;
>> @@ hw/virtio/virtio-snd.c (new)
>> + stream->positions[0] = VIRTIO_SND_CHMAP_FL;
>> + stream->positions[1] = VIRTIO_SND_CHMAP_FR;
>> +
>> -+ audsettings as;
>> -+ virtio_snd_get_qemu_audsettings(&as, params);
>> +
>> + if (stream->direction == VIRTIO_SND_D_OUTPUT) {
>> + stream->voice.out = AUD_open_out(&s->card,
>> @@ hw/virtio/virtio-snd.c (new)
>> + stream->desired_as = stream->as;
>> + qemu_mutex_init(&stream->queue_mutex);
>> + QSIMPLEQ_INIT(&stream->queue);
>> ++
>> + s->pcm->streams[stream_id] = stream;
>> +
>> + return VIRTIO_SND_S_OK;
>> @@ hw/virtio/virtio-snd.c (new)
>> +
>> virtio_snd_ctrl_command *cmd,
>> + bool start)
>> +{
>> ++ VirtIOSoundPCMStream *stream;
>> + virtio_snd_pcm_hdr req;
>> + size_t sz;
>> +
>> @@ hw/virtio/virtio-snd.c (new)
>> + trace_virtio_snd_handle_pcm_start_stop(start ?
>> "VIRTIO_SND_R_PCM_START" :
>> + "VIRTIO_SND_R_PCM_STOP", req.stream_id);
>> +
>> -+ VirtIOSoundPCMStream *stream = virtio_snd_pcm_get_stream(s,
>> req.stream_id);
>> ++ stream = virtio_snd_pcm_get_stream(s, req.stream_id);
>> +
>> + if (stream) {
>> + if (stream->direction == VIRTIO_SND_D_OUTPUT) {
>> @@ hw/virtio/virtio-snd.c (new)
>> +}
>> +
>> +/*
>> -+ * Releases the resources allocated to a stream. Seperated from
>> the handler
>> -+ * so that the code can be reused in the unrealize function.
>> -+ * Returns the response status code. (VIRTIO_SND_S_*).
>> ++ * Releases the buffer resources allocated to a stream. Seperated
>> from the
>> ++ * handler so that the code can be reused in the unrealize
>> function. Returns
>> ++ * the response status code. (VIRTIO_SND_S_*).
>> + *
>> + * @stream: VirtIOSoundPCMStream stream
>> + * @stream_id: stream id
>> @@ hw/virtio/virtio-snd.c (new)
>> +static uint32_t virtio_snd_pcm_release_impl(VirtIOSoundPCMStream
>> *stream,
>> + uint32_t stream_id)
>> +{
>> ++ assert(stream->s->pcm->streams[stream_id] == stream);
>> ++
>> + if (virtio_snd_pcm_get_pending_bytes(stream)) {
>> + /*
>> + * virtio-v1.2-csd01, 5.14.6.6.5.1,
>> @@ hw/virtio/virtio-snd.c (new)
>> + virtio_snd_pcm_flush(stream);
>> + }
>> +
>> -+ if (stream->direction == VIRTIO_SND_D_OUTPUT) {
>> -+ AUD_close_out(&stream->s->card, stream->voice.out);
>> -+ } else {
>> -+ AUD_close_in(&stream->s->card, stream->voice.in);
>> -+ }
>> -+
>> -+ assert(stream->s->pcm->streams[stream_id] == stream);
>> -+
>> + return VIRTIO_SND_S_OK;
>> +}
>> +
>> @@ hw/virtio/virtio-snd.c (new)
>> +{
>> + uint32_t stream_id;
>> + size_t sz;
>> ++ VirtIOSoundPCMStream *stream;
>> +
>> + sz = iov_to_buf(cmd->elem->out_sg, cmd->elem->out_num,
>> + sizeof(virtio_snd_hdr), &stream_id, sizeof(stream_id));
>> @@ hw/virtio/virtio-snd.c (new)
>> +
>> + trace_virtio_snd_handle_pcm_release(stream_id);
>> +
>> -+ VirtIOSoundPCMStream *stream = virtio_snd_pcm_get_stream(s,
>> stream_id);
>> ++ stream = virtio_snd_pcm_get_stream(s, stream_id);
>> + if (!stream) {
>> + error_report("already released stream %d", stream_id);
>> + virtio_error(VIRTIO_DEVICE(s), "already released stream
>> %d", stream_id);
>> @@ hw/virtio/virtio-snd.c (new)
>> +
>> + switch (cmd->ctrl.code) {
>> + case VIRTIO_SND_R_JACK_INFO:
>> -+ /*
>> -+ * Unimplemented
>> -+ * virtio_snd_handle_jack_info(s, cmd);
>> -+ */
>> -+ break;
>> + case VIRTIO_SND_R_JACK_REMAP:
>> -+ /*
>> -+ * Unimplemented
>> -+ * virtio_snd_handle_jack_remap(s, cmd);
>> -+ */
>> ++ qemu_log_mask(LOG_UNIMP,
>> ++ "virtio_snd: jack functionality is
>> unimplemented.");
>> + break;
>> + case VIRTIO_SND_R_PCM_INFO:
>> + virtio_snd_handle_pcm_info(s, cmd);
>> @@ hw/virtio/virtio-snd.c (new)
>> + virtio_snd_handle_pcm_release(s, cmd);
>> + break;
>> + case VIRTIO_SND_R_CHMAP_INFO:
>> ++ qemu_log_mask(LOG_UNIMP,
>> ++ "virtio_snd: chmap info functionality is
>> unimplemented.");
>> + trace_virtio_snd_handle_chmap_info();
>> + break;
>> + default:
>> @@ hw/virtio/virtio-snd.c (new)
>> + */
>> +static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue
>> *vq)
>> +{
>> ++ qemu_log_mask(LOG_UNIMP, "virtio_snd: event queue is
>> unimplemented.");
>> + trace_virtio_snd_handle_event();
>> +}
>> +
>> @@ hw/virtio/virtio-snd.c (new)
>> + VirtQueueElement *elem;
>> + size_t sz;
>> + virtio_snd_pcm_xfer hdr;
>> ++ virtio_snd_pcm_status resp = { 0 };
>> +
>> + trace_virtio_snd_handle_xfer();
>> +
>> @@ hw/virtio/virtio-snd.c (new)
>> + elem,
>> + hdr.stream_id == VIRTIO_SND_D_INPUT);
>> +
>> -+ virtio_snd_pcm_status resp = { 0 };
>> + resp.status = VIRTIO_SND_S_OK;
>> + sz = iov_from_buf(elem->in_sg,
>> + elem->in_num,
>> @@ hw/virtio/virtio-snd.c (new)
>> + VirtIOSoundPCMStream *stream = data;
>> + VirtIOSoundPCMBlock *block;
>> + VirtIOSoundPCMBlock *next;
>> ++ int size;
>> +
>> + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
>> + QSIMPLEQ_FOREACH_SAFE(block, &stream->queue, entry, next) {
>> -+ int size = MIN(block->size, available);
>> -+
>> + for (;;) {
>> ++ size = MIN(block->size, available);
>> + size = AUD_write(stream->voice.out,
>> + block->data + block->offset,
>> + size);
>> @@ hw/virtio/virtio-snd.c (new)
>> + sizeof(block->elem));
>> + virtio_notify(VIRTIO_DEVICE(stream->s),
>> + block->vq);
>> -+ QSIMPLEQ_REMOVE(&stream->queue,
>> -+ block,
>> -+ VirtIOSoundPCMBlock,
>> -+ entry);
>> ++ QSIMPLEQ_REMOVE_HEAD(&stream->queue, entry);
>> ++ g_free(block);
>> + available -= size;
>> + break;
>> + }
>> @@ hw/virtio/virtio-snd.c (new)
>> +{
>> + VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>> + VirtIOSound *vsnd = VIRTIO_SND(dev);
>> ++ VirtIOSoundPCMStream *stream;
>> +
>> + qemu_del_vm_change_state_handler(vsnd->vmstate);
>> + virtio_del_queue(vdev, 0);
>> @@ hw/virtio/virtio-snd.c (new)
>> + trace_virtio_snd_unrealize(vsnd);
>> +
>> + for (int i = VIRTIO_SND_D_OUTPUT; i <= VIRTIO_SND_D_INPUT;
>> i++) {
>> -+ VirtIOSoundPCMStream *stream = vsnd->pcm->streams[i];
>> -+
>> ++ stream = vsnd->pcm->streams[i];
>> + virtio_snd_pcm_close(stream);
>> -+
>> + g_free(stream);
>> + }
>> +
>> @@ hw/virtio/virtio-snd.c (new)
>> + sizeof(virtio_snd_pcm_xfer);
>> + assert(size <= stream->period_bytes);
>> +
>> -+ trace_virtio_snd_handle_xfer_elem(read ? "read" : "write");
>> -+
>> -+ fragment = g_malloc(sizeof(VirtIOSoundPCMBlock) + size);
>> ++ fragment = g_malloc0(sizeof(VirtIOSoundPCMBlock) + size);
>> + fragment->elem = element;
>> + fragment->vq = vq;
>> + fragment->size = size;
>> @@ hw/virtio/virtio-snd.c (new)
>> +
>> +type_init(virtio_snd_register);
>> - ## include/hw/pci/pci.h ##
>> -@@ include/hw/pci/pci.h: extern bool pci_available;
>> - #define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
>> - #define PCI_DEVICE_ID_VIRTIO_9P 0x1009
>> - #define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
>> -+#define PCI_DEVICE_ID_VIRTIO_SND 0x1019
>> - - /*
>> - * modern virtio-pci devices get their id assigned automatically,
>> -
>> ## include/hw/virtio/virtio-snd.h (new) ##
>> @@
>> +/*
>> @@ include/hw/virtio/virtio-snd.h (new)
>> +typedef struct VirtIOSoundPCMStream {
>> + VirtIOSoundPCM *pcm;
>> + struct virtio_snd_pcm_info info;
>> ++ uint32_t id;
>> + uint32_t buffer_bytes;
>> + uint32_t period_bytes;
>> + /* channel position values (VIRTIO_SND_CHMAP_XXX) */
>> @@ include/hw/virtio/virtio-snd.h (new)
>> + }
>> +};
>> +#endif
>> -
>> - ## softmmu/qdev-monitor.c ##
>> -@@ softmmu/qdev-monitor.c: static const QDevAlias
>> qdev_alias_table[] = {
>> - { "virtio-serial-device", "virtio-serial",
>> QEMU_ARCH_VIRTIO_MMIO },
>> - { "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_VIRTIO_CCW },
>> - { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_VIRTIO_PCI},
>> -+ { "virtio-sound-pci", "virtio-sound", QEMU_ARCH_VIRTIO_PCI},
>> - { "virtio-tablet-device", "virtio-tablet",
>> QEMU_ARCH_VIRTIO_MMIO },
>> - { "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_VIRTIO_CCW },
>> - { "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_VIRTIO_PCI },
>> -: ---------- > 2: db527bc9a1 Add virtio-sound-pci device
>> -: ---------- > 3: 4c130f066d Implement audio capture in virtio-snd
>> device
>> --
>> 2.39.2
>>
>
prev parent reply other threads:[~2023-07-16 17:19 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-08 15:56 [PATCH v2 0/3] Add VIRTIO sound card Manos Pitsidianakis
2023-06-08 15:56 ` [PATCH v2 1/3] Add virtio-sound device Manos Pitsidianakis
2023-07-17 15:38 ` Alex Bennée
2023-06-08 15:56 ` [PATCH v2 2/3] Add virtio-sound-pci device Manos Pitsidianakis
2023-07-17 16:47 ` Alex Bennée
2023-06-08 15:56 ` [PATCH v2 3/3] Implement audio capture in virtio-snd device Manos Pitsidianakis
2023-07-13 11:00 ` [PATCH v2 0/3] Add VIRTIO sound card Manos Pitsidianakis
2023-07-16 17:18 ` Philippe Mathieu-Daudé [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=73f46bd9-239a-ed6f-d3da-d4d7666b9263@linaro.org \
--to=philmd@linaro.org \
--cc=Anton.Yakovlev@opensynergy.com \
--cc=DirtY.iCE.hu@gmail.com \
--cc=Igor.Skalkin@opensynergy.com \
--cc=berrange@redhat.com \
--cc=eduardo@habkost.net \
--cc=kraxel@redhat.com \
--cc=manos.pitsidianakis@linaro.org \
--cc=marcandre.lureau@redhat.com \
--cc=marcel.apfelbaum@gmail.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=vr_qemu@t-online.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).