Commit 29b96bf5 authored by Anton Yakovlev's avatar Anton Yakovlev Committed by Takashi Iwai

ALSA: virtio: build PCM devices and substream hardware descriptors

Like the HDA specification, the virtio sound device specification links
PCM substreams, jacks and PCM channel maps into functional groups. For
each discovered group, a PCM device is created, the number of which
coincides with the group number.

Introduce the module parameters for setting the hardware buffer
parameters:
  pcm_buffer_ms [=160]
  pcm_periods_min [=2]
  pcm_periods_max [=16]
  pcm_period_ms_min [=10]
  pcm_period_ms_max [=80]
Signed-off-by: default avatarAnton Yakovlev <anton.yakovlev@opensynergy.com>
Link: https://lore.kernel.org/r/20210302164709.3142702-5-anton.yakovlev@opensynergy.comSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 9d45e514
......@@ -4,5 +4,6 @@ obj-$(CONFIG_SND_VIRTIO) += virtio_snd.o
virtio_snd-objs := \
virtio_card.o \
virtio_ctl_msg.o
virtio_ctl_msg.o \
virtio_pcm.o
......@@ -209,6 +209,16 @@ static int virtsnd_build_devs(struct virtio_snd *snd)
VIRTIO_SND_CARD_NAME " at %s/%s",
dev_name(dev->parent), dev_name(dev));
rc = virtsnd_pcm_parse_cfg(snd);
if (rc)
return rc;
if (snd->nsubstreams) {
rc = virtsnd_pcm_build_devs(snd);
if (rc)
return rc;
}
return snd_card_register(snd->card);
}
......@@ -237,6 +247,9 @@ static int virtsnd_validate(struct virtio_device *vdev)
return -EINVAL;
}
if (virtsnd_pcm_validate(vdev))
return -EINVAL;
return 0;
}
......@@ -259,6 +272,7 @@ static int virtsnd_probe(struct virtio_device *vdev)
snd->vdev = vdev;
INIT_LIST_HEAD(&snd->ctl_msgs);
INIT_LIST_HEAD(&snd->pcm_list);
vdev->priv = snd;
......@@ -293,6 +307,7 @@ static int virtsnd_probe(struct virtio_device *vdev)
static void virtsnd_remove(struct virtio_device *vdev)
{
struct virtio_snd *snd = vdev->priv;
unsigned int i;
virtsnd_disable_event_vq(snd);
virtsnd_ctl_msg_cancel_all(snd);
......@@ -303,6 +318,9 @@ static void virtsnd_remove(struct virtio_device *vdev)
vdev->config->del_vqs(vdev);
vdev->config->reset(vdev);
for (i = 0; snd->substreams && i < snd->nsubstreams; ++i)
cancel_work_sync(&snd->substreams[i].elapsed_period);
kfree(snd->event_msgs);
}
......
......@@ -12,9 +12,13 @@
#include <uapi/linux/virtio_snd.h>
#include "virtio_ctl_msg.h"
#include "virtio_pcm.h"
#define VIRTIO_SND_CARD_DRIVER "virtio-snd"
#define VIRTIO_SND_CARD_NAME "VirtIO SoundCard"
#define VIRTIO_SND_PCM_NAME "VirtIO PCM"
struct virtio_pcm_substream;
/**
* struct virtio_snd_queue - Virtqueue wrapper structure.
......@@ -33,6 +37,9 @@ struct virtio_snd_queue {
* @card: ALSA sound card.
* @ctl_msgs: Pending control request list.
* @event_msgs: Device events.
* @pcm_list: VirtIO PCM device list.
* @substreams: VirtIO PCM substreams.
* @nsubstreams: Number of PCM substreams.
*/
struct virtio_snd {
struct virtio_device *vdev;
......@@ -40,6 +47,9 @@ struct virtio_snd {
struct snd_card *card;
struct list_head ctl_msgs;
struct virtio_snd_event *event_msgs;
struct list_head pcm_list;
struct virtio_pcm_substream *substreams;
u32 nsubstreams;
};
/* Message completion timeout in milliseconds (module parameter). */
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* virtio-snd: Virtio sound device
* Copyright (C) 2021 OpenSynergy GmbH
*/
#ifndef VIRTIO_SND_PCM_H
#define VIRTIO_SND_PCM_H
#include <linux/atomic.h>
#include <linux/virtio_config.h>
#include <sound/pcm.h>
struct virtio_pcm;
struct virtio_pcm_msg;
/**
* struct virtio_pcm_substream - VirtIO PCM substream.
* @snd: VirtIO sound device.
* @nid: Function group node identifier.
* @sid: Stream identifier.
* @direction: Stream data flow direction (SNDRV_PCM_STREAM_XXX).
* @features: Stream VirtIO feature bit map (1 << VIRTIO_SND_PCM_F_XXX).
* @substream: Kernel ALSA substream.
* @hw: Kernel ALSA substream hardware descriptor.
* @elapsed_period: Kernel work to handle the elapsed period state.
*/
struct virtio_pcm_substream {
struct virtio_snd *snd;
u32 nid;
u32 sid;
u32 direction;
u32 features;
struct snd_pcm_substream *substream;
struct snd_pcm_hardware hw;
struct work_struct elapsed_period;
};
/**
* struct virtio_pcm_stream - VirtIO PCM stream.
* @substreams: VirtIO substreams belonging to the stream.
* @nsubstreams: Number of substreams.
*/
struct virtio_pcm_stream {
struct virtio_pcm_substream **substreams;
u32 nsubstreams;
};
/**
* struct virtio_pcm - VirtIO PCM device.
* @list: VirtIO PCM list entry.
* @nid: Function group node identifier.
* @pcm: Kernel PCM device.
* @streams: VirtIO PCM streams (playback and capture).
*/
struct virtio_pcm {
struct list_head list;
u32 nid;
struct snd_pcm *pcm;
struct virtio_pcm_stream streams[SNDRV_PCM_STREAM_LAST + 1];
};
int virtsnd_pcm_validate(struct virtio_device *vdev);
int virtsnd_pcm_parse_cfg(struct virtio_snd *snd);
int virtsnd_pcm_build_devs(struct virtio_snd *snd);
struct virtio_pcm *virtsnd_pcm_find(struct virtio_snd *snd, u32 nid);
struct virtio_pcm *virtsnd_pcm_find_or_create(struct virtio_snd *snd, u32 nid);
#endif /* VIRTIO_SND_PCM_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment