From b73f8b9a6faeb6eba94be47c59422503cb303c25 Mon Sep 17 00:00:00 2001 From: Timo Wischer Date: Tue, 22 Oct 2019 15:05:16 +0200 Subject: [PATCH 1/2] snd: virtio: Chose period size depending on device Change-Id: Ia1db0bcc64eb64079632a29735e737794cf219c0 Signed-off-by: Timo Wischer --- include/uapi/linux/virtio_snd.h | 4 ++++ sound/virtio/virtio_snd.c | 24 +++++++++--------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/uapi/linux/virtio_snd.h b/include/uapi/linux/virtio_snd.h index bd75dc898af436..bc923357383bb4 100644 --- a/include/uapi/linux/virtio_snd.h +++ b/include/uapi/linux/virtio_snd.h @@ -279,6 +279,10 @@ struct virtio_snd_pcm_stream_desc { __virtio32 formats; /* supported frame rate bit map (VIRTIO_SND_PCM_RATEBIT_*) */ __virtio32 rates; + /* min size in frames of one audio interval/period */ + __virtio32 period_size_min; + /* max size in frames of one audio interval/period */ + __virtio32 period_size_max; }; /* PCM control request header */ diff --git a/sound/virtio/virtio_snd.c b/sound/virtio/virtio_snd.c index ecf1e2b33e434a..66b8af75611cec 100644 --- a/sound/virtio/virtio_snd.c +++ b/sound/virtio/virtio_snd.c @@ -1377,8 +1377,6 @@ viosnd_pcm_stream_configure(struct viosnd_pcm *pcm, u32 rates; u32 sample_size_min = 0; u32 sample_size_max = 0; - unsigned int buffer_size_min; - unsigned int buffer_size_max; unsigned int page_order; stream = devm_kzalloc(dev, sizeof(*stream), GFP_KERNEL); @@ -1439,22 +1437,18 @@ viosnd_pcm_stream_configure(struct viosnd_pcm *pcm, return ERR_PTR(-EINVAL); } - buffer_size_min = - (sample_size_min * desc->channels_min * stream->hw.rate_min); - buffer_size_min /= 2; - buffer_size_max = - (sample_size_max * desc->channels_max * stream->hw.rate_max); - buffer_size_max /= 2; - + stream->hw.period_bytes_min = + (sample_size_min * desc->channels_min * desc->period_size_min); + stream->hw.period_bytes_max = + (sample_size_max * desc->channels_max * desc->period_size_max); stream->hw.channels_min = desc->channels_min; stream->hw.channels_max = desc->channels_max; - stream->hw.buffer_bytes_max = buffer_size_max; - stream->hw.periods_min = 4; - stream->hw.periods_max = 4; - stream->hw.period_bytes_min = buffer_size_min / 4; - stream->hw.period_bytes_max = buffer_size_max / 4; + stream->hw.periods_min = 2; + stream->hw.periods_max = 16; + stream->hw.buffer_bytes_max = + stream->hw.periods_max * stream->hw.period_bytes_max; - page_order = get_order(buffer_size_max); + page_order = get_order(stream->hw.buffer_bytes_max); stream->data = (void *)devm_get_free_pages(dev, GFP_KERNEL, page_order); if (!stream->data) From f5942a15d9840f531b536699e535bad086ebf7dc Mon Sep 17 00:00:00 2001 From: Timo Wischer Date: Mon, 11 Nov 2019 13:23:50 +0100 Subject: [PATCH 2/2] snd: virtio: Support explicit period size limitation With this feature the host/device can provide explicit period sizes which are only supported. This is helpful when the host for example can only handle periods which are a multiple of its own period size. Change-Id: I3f2694dc51530eb264f83deb2adb94db0a0db51c Signed-off-by: Timo Wischer --- include/uapi/linux/virtio_snd.h | 8 ++++++++ sound/virtio/virtio_snd.c | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/uapi/linux/virtio_snd.h b/include/uapi/linux/virtio_snd.h index bc923357383bb4..877e4e4d5c1dad 100644 --- a/include/uapi/linux/virtio_snd.h +++ b/include/uapi/linux/virtio_snd.h @@ -283,6 +283,14 @@ struct virtio_snd_pcm_stream_desc { __virtio32 period_size_min; /* max size in frames of one audio interval/period */ __virtio32 period_size_max; + + /* explicitly specify supported period sizes in frames */ + /* amount of supported period sizes. Can be 0 when no additional + * limitation is required + */ + __virtio32 period_size_list_count; + /* supported periods size in frames */ + __virtio32 period_size_list[32]; }; /* PCM control request header */ diff --git a/sound/virtio/virtio_snd.c b/sound/virtio/virtio_snd.c index 66b8af75611cec..5cc222d898ca8c 100644 --- a/sound/virtio/virtio_snd.c +++ b/sound/virtio/virtio_snd.c @@ -140,6 +140,7 @@ struct viosnd_pcm_stream { struct viosnd_pcm *pcm; struct snd_pcm_hardware hw; + struct snd_pcm_hw_constraint_list period_size_list; struct snd_pcm_substream *substream; u8 nchmaps; @@ -851,6 +852,11 @@ static int viosnd_pcm_open(struct snd_pcm_substream *substream) substream->runtime->hw = stream->hw; + if (stream->period_size_list.count > 0) + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + &stream->period_size_list); + return 0; } @@ -1448,6 +1454,20 @@ viosnd_pcm_stream_configure(struct viosnd_pcm *pcm, stream->hw.buffer_bytes_max = stream->hw.periods_max * stream->hw.period_bytes_max; + if (desc->period_size_list_count > 0) { + const size_t size = sizeof(desc->period_size_list[0]) * + desc->period_size_list_count; + unsigned int* const elems = devm_kzalloc(dev, size, GFP_KERNEL); + + if (!elems) + return ERR_PTR(-ENOMEM); + for (i = 0; i < desc->period_size_list_count; ++i) + elems[i] = desc->period_size_list[i]; + + stream->period_size_list.count = desc->period_size_list_count; + stream->period_size_list.list = elems; + } + page_order = get_order(stream->hw.buffer_bytes_max); stream->data = (void *)devm_get_free_pages(dev, GFP_KERNEL, page_order);