1 // SPDX-License-Identifier: GPL-2.0+
3 * virtio-snd: Virtio sound device
4 * Copyright (C) 2021 OpenSynergy GmbH
6 #include <linux/moduleparam.h>
7 #include <linux/virtio_config.h>
9 #include "virtio_card.h"
11 static u32 pcm_buffer_ms
= 160;
12 module_param(pcm_buffer_ms
, uint
, 0644);
13 MODULE_PARM_DESC(pcm_buffer_ms
, "PCM substream buffer time in milliseconds");
15 static u32 pcm_periods_min
= 2;
16 module_param(pcm_periods_min
, uint
, 0644);
17 MODULE_PARM_DESC(pcm_periods_min
, "Minimum number of PCM periods");
19 static u32 pcm_periods_max
= 16;
20 module_param(pcm_periods_max
, uint
, 0644);
21 MODULE_PARM_DESC(pcm_periods_max
, "Maximum number of PCM periods");
23 static u32 pcm_period_ms_min
= 10;
24 module_param(pcm_period_ms_min
, uint
, 0644);
25 MODULE_PARM_DESC(pcm_period_ms_min
, "Minimum PCM period time in milliseconds");
27 static u32 pcm_period_ms_max
= 80;
28 module_param(pcm_period_ms_max
, uint
, 0644);
29 MODULE_PARM_DESC(pcm_period_ms_max
, "Maximum PCM period time in milliseconds");
31 /* Map for converting VirtIO format to ALSA format. */
32 static const snd_pcm_format_t g_v2a_format_map
[] = {
33 [VIRTIO_SND_PCM_FMT_IMA_ADPCM
] = SNDRV_PCM_FORMAT_IMA_ADPCM
,
34 [VIRTIO_SND_PCM_FMT_MU_LAW
] = SNDRV_PCM_FORMAT_MU_LAW
,
35 [VIRTIO_SND_PCM_FMT_A_LAW
] = SNDRV_PCM_FORMAT_A_LAW
,
36 [VIRTIO_SND_PCM_FMT_S8
] = SNDRV_PCM_FORMAT_S8
,
37 [VIRTIO_SND_PCM_FMT_U8
] = SNDRV_PCM_FORMAT_U8
,
38 [VIRTIO_SND_PCM_FMT_S16
] = SNDRV_PCM_FORMAT_S16_LE
,
39 [VIRTIO_SND_PCM_FMT_U16
] = SNDRV_PCM_FORMAT_U16_LE
,
40 [VIRTIO_SND_PCM_FMT_S18_3
] = SNDRV_PCM_FORMAT_S18_3LE
,
41 [VIRTIO_SND_PCM_FMT_U18_3
] = SNDRV_PCM_FORMAT_U18_3LE
,
42 [VIRTIO_SND_PCM_FMT_S20_3
] = SNDRV_PCM_FORMAT_S20_3LE
,
43 [VIRTIO_SND_PCM_FMT_U20_3
] = SNDRV_PCM_FORMAT_U20_3LE
,
44 [VIRTIO_SND_PCM_FMT_S24_3
] = SNDRV_PCM_FORMAT_S24_3LE
,
45 [VIRTIO_SND_PCM_FMT_U24_3
] = SNDRV_PCM_FORMAT_U24_3LE
,
46 [VIRTIO_SND_PCM_FMT_S20
] = SNDRV_PCM_FORMAT_S20_LE
,
47 [VIRTIO_SND_PCM_FMT_U20
] = SNDRV_PCM_FORMAT_U20_LE
,
48 [VIRTIO_SND_PCM_FMT_S24
] = SNDRV_PCM_FORMAT_S24_LE
,
49 [VIRTIO_SND_PCM_FMT_U24
] = SNDRV_PCM_FORMAT_U24_LE
,
50 [VIRTIO_SND_PCM_FMT_S32
] = SNDRV_PCM_FORMAT_S32_LE
,
51 [VIRTIO_SND_PCM_FMT_U32
] = SNDRV_PCM_FORMAT_U32_LE
,
52 [VIRTIO_SND_PCM_FMT_FLOAT
] = SNDRV_PCM_FORMAT_FLOAT_LE
,
53 [VIRTIO_SND_PCM_FMT_FLOAT64
] = SNDRV_PCM_FORMAT_FLOAT64_LE
,
54 [VIRTIO_SND_PCM_FMT_DSD_U8
] = SNDRV_PCM_FORMAT_DSD_U8
,
55 [VIRTIO_SND_PCM_FMT_DSD_U16
] = SNDRV_PCM_FORMAT_DSD_U16_LE
,
56 [VIRTIO_SND_PCM_FMT_DSD_U32
] = SNDRV_PCM_FORMAT_DSD_U32_LE
,
57 [VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME
] =
58 SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
61 /* Map for converting VirtIO frame rate to ALSA frame rate. */
62 struct virtsnd_v2a_rate
{
63 unsigned int alsa_bit
;
67 static const struct virtsnd_v2a_rate g_v2a_rate_map
[] = {
68 [VIRTIO_SND_PCM_RATE_5512
] = { SNDRV_PCM_RATE_5512
, 5512 },
69 [VIRTIO_SND_PCM_RATE_8000
] = { SNDRV_PCM_RATE_8000
, 8000 },
70 [VIRTIO_SND_PCM_RATE_11025
] = { SNDRV_PCM_RATE_11025
, 11025 },
71 [VIRTIO_SND_PCM_RATE_16000
] = { SNDRV_PCM_RATE_16000
, 16000 },
72 [VIRTIO_SND_PCM_RATE_22050
] = { SNDRV_PCM_RATE_22050
, 22050 },
73 [VIRTIO_SND_PCM_RATE_32000
] = { SNDRV_PCM_RATE_32000
, 32000 },
74 [VIRTIO_SND_PCM_RATE_44100
] = { SNDRV_PCM_RATE_44100
, 44100 },
75 [VIRTIO_SND_PCM_RATE_48000
] = { SNDRV_PCM_RATE_48000
, 48000 },
76 [VIRTIO_SND_PCM_RATE_64000
] = { SNDRV_PCM_RATE_64000
, 64000 },
77 [VIRTIO_SND_PCM_RATE_88200
] = { SNDRV_PCM_RATE_88200
, 88200 },
78 [VIRTIO_SND_PCM_RATE_96000
] = { SNDRV_PCM_RATE_96000
, 96000 },
79 [VIRTIO_SND_PCM_RATE_176400
] = { SNDRV_PCM_RATE_176400
, 176400 },
80 [VIRTIO_SND_PCM_RATE_192000
] = { SNDRV_PCM_RATE_192000
, 192000 }
84 * virtsnd_pcm_build_hw() - Parse substream config and build HW descriptor.
85 * @vss: VirtIO substream.
86 * @info: VirtIO substream information entry.
88 * Context: Any context.
89 * Return: 0 on success, -EINVAL if configuration is invalid.
91 static int virtsnd_pcm_build_hw(struct virtio_pcm_substream
*vss
,
92 struct virtio_snd_pcm_info
*info
)
94 struct virtio_device
*vdev
= vss
->snd
->vdev
;
97 size_t sample_max
= 0;
98 size_t sample_min
= 0;
100 vss
->features
= le32_to_cpu(info
->features
);
103 * TODO: set SNDRV_PCM_INFO_{BATCH,BLOCK_TRANSFER} if device supports
104 * only message-based transport.
107 SNDRV_PCM_INFO_MMAP
|
108 SNDRV_PCM_INFO_MMAP_VALID
|
109 SNDRV_PCM_INFO_BATCH
|
110 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
111 SNDRV_PCM_INFO_INTERLEAVED
|
112 SNDRV_PCM_INFO_PAUSE
|
113 SNDRV_PCM_INFO_NO_REWINDS
|
114 SNDRV_PCM_INFO_SYNC_APPLPTR
;
116 if (!info
->channels_min
|| info
->channels_min
> info
->channels_max
) {
118 "SID %u: invalid channel range [%u %u]\n",
119 vss
->sid
, info
->channels_min
, info
->channels_max
);
123 vss
->hw
.channels_min
= info
->channels_min
;
124 vss
->hw
.channels_max
= info
->channels_max
;
126 values
= le64_to_cpu(info
->formats
);
130 for (i
= 0; i
< ARRAY_SIZE(g_v2a_format_map
); ++i
)
131 if (values
& (1ULL << i
)) {
132 snd_pcm_format_t alsa_fmt
= g_v2a_format_map
[i
];
133 int bytes
= snd_pcm_format_physical_width(alsa_fmt
) / 8;
135 if (!sample_min
|| sample_min
> bytes
)
138 if (sample_max
< bytes
)
141 vss
->hw
.formats
|= pcm_format_to_bits(alsa_fmt
);
144 if (!vss
->hw
.formats
) {
146 "SID %u: no supported PCM sample formats found\n",
151 values
= le64_to_cpu(info
->rates
);
155 for (i
= 0; i
< ARRAY_SIZE(g_v2a_rate_map
); ++i
)
156 if (values
& (1ULL << i
)) {
157 if (!vss
->hw
.rate_min
||
158 vss
->hw
.rate_min
> g_v2a_rate_map
[i
].rate
)
159 vss
->hw
.rate_min
= g_v2a_rate_map
[i
].rate
;
161 if (vss
->hw
.rate_max
< g_v2a_rate_map
[i
].rate
)
162 vss
->hw
.rate_max
= g_v2a_rate_map
[i
].rate
;
164 vss
->hw
.rates
|= g_v2a_rate_map
[i
].alsa_bit
;
167 if (!vss
->hw
.rates
) {
169 "SID %u: no supported PCM frame rates found\n",
174 vss
->hw
.periods_min
= pcm_periods_min
;
175 vss
->hw
.periods_max
= pcm_periods_max
;
178 * We must ensure that there is enough space in the buffer to store
179 * pcm_buffer_ms ms for the combination (Cmax, Smax, Rmax), where:
180 * Cmax = maximum supported number of channels,
181 * Smax = maximum supported sample size in bytes,
182 * Rmax = maximum supported frame rate.
184 vss
->hw
.buffer_bytes_max
=
185 PAGE_ALIGN(sample_max
* vss
->hw
.channels_max
* pcm_buffer_ms
*
186 (vss
->hw
.rate_max
/ MSEC_PER_SEC
));
189 * We must ensure that the minimum period size is enough to store
190 * pcm_period_ms_min ms for the combination (Cmin, Smin, Rmin), where:
191 * Cmin = minimum supported number of channels,
192 * Smin = minimum supported sample size in bytes,
193 * Rmin = minimum supported frame rate.
195 vss
->hw
.period_bytes_min
=
196 sample_min
* vss
->hw
.channels_min
* pcm_period_ms_min
*
197 (vss
->hw
.rate_min
/ MSEC_PER_SEC
);
200 * We must ensure that the maximum period size is enough to store
201 * pcm_period_ms_max ms for the combination (Cmax, Smax, Rmax).
203 vss
->hw
.period_bytes_max
=
204 sample_max
* vss
->hw
.channels_max
* pcm_period_ms_max
*
205 (vss
->hw
.rate_max
/ MSEC_PER_SEC
);
211 * virtsnd_pcm_find() - Find the PCM device for the specified node ID.
212 * @snd: VirtIO sound device.
213 * @nid: Function node ID.
215 * Context: Any context.
216 * Return: a pointer to the PCM device or ERR_PTR(-ENOENT).
218 struct virtio_pcm
*virtsnd_pcm_find(struct virtio_snd
*snd
, u32 nid
)
220 struct virtio_pcm
*vpcm
;
222 list_for_each_entry(vpcm
, &snd
->pcm_list
, list
)
223 if (vpcm
->nid
== nid
)
226 return ERR_PTR(-ENOENT
);
230 * virtsnd_pcm_find_or_create() - Find or create the PCM device for the
232 * @snd: VirtIO sound device.
233 * @nid: Function node ID.
235 * Context: Any context that permits to sleep.
236 * Return: a pointer to the PCM device or ERR_PTR(-errno).
238 struct virtio_pcm
*virtsnd_pcm_find_or_create(struct virtio_snd
*snd
, u32 nid
)
240 struct virtio_device
*vdev
= snd
->vdev
;
241 struct virtio_pcm
*vpcm
;
243 vpcm
= virtsnd_pcm_find(snd
, nid
);
247 vpcm
= devm_kzalloc(&vdev
->dev
, sizeof(*vpcm
), GFP_KERNEL
);
249 return ERR_PTR(-ENOMEM
);
252 list_add_tail(&vpcm
->list
, &snd
->pcm_list
);
258 * virtsnd_pcm_validate() - Validate if the device can be started.
259 * @vdev: VirtIO parent device.
261 * Context: Any context.
262 * Return: 0 on success, -EINVAL on failure.
264 int virtsnd_pcm_validate(struct virtio_device
*vdev
)
266 if (pcm_periods_min
< 2 || pcm_periods_min
> pcm_periods_max
) {
268 "invalid range [%u %u] of the number of PCM periods\n",
269 pcm_periods_min
, pcm_periods_max
);
273 if (!pcm_period_ms_min
|| pcm_period_ms_min
> pcm_period_ms_max
) {
275 "invalid range [%u %u] of the size of the PCM period\n",
276 pcm_period_ms_min
, pcm_period_ms_max
);
280 if (pcm_buffer_ms
< pcm_periods_min
* pcm_period_ms_min
) {
282 "pcm_buffer_ms(=%u) value cannot be < %u ms\n",
283 pcm_buffer_ms
, pcm_periods_min
* pcm_period_ms_min
);
287 if (pcm_period_ms_max
> pcm_buffer_ms
/ 2) {
289 "pcm_period_ms_max(=%u) value cannot be > %u ms\n",
290 pcm_period_ms_max
, pcm_buffer_ms
/ 2);
298 * virtsnd_pcm_period_elapsed() - Kernel work function to handle the elapsed
300 * @work: Elapsed period work.
302 * The main purpose of this function is to call snd_pcm_period_elapsed() in
303 * a process context, not in an interrupt context. This is necessary because PCM
304 * devices operate in non-atomic mode.
306 * Context: Process context.
308 static void virtsnd_pcm_period_elapsed(struct work_struct
*work
)
310 struct virtio_pcm_substream
*vss
=
311 container_of(work
, struct virtio_pcm_substream
, elapsed_period
);
313 snd_pcm_period_elapsed(vss
->substream
);
317 * virtsnd_pcm_parse_cfg() - Parse the stream configuration.
318 * @snd: VirtIO sound device.
320 * This function is called during initial device initialization.
322 * Context: Any context that permits to sleep.
323 * Return: 0 on success, -errno on failure.
325 int virtsnd_pcm_parse_cfg(struct virtio_snd
*snd
)
327 struct virtio_device
*vdev
= snd
->vdev
;
328 struct virtio_snd_pcm_info
*info
;
332 virtio_cread_le(vdev
, struct virtio_snd_config
, streams
,
334 if (!snd
->nsubstreams
)
337 snd
->substreams
= devm_kcalloc(&vdev
->dev
, snd
->nsubstreams
,
338 sizeof(*snd
->substreams
), GFP_KERNEL
);
339 if (!snd
->substreams
)
342 info
= kcalloc(snd
->nsubstreams
, sizeof(*info
), GFP_KERNEL
);
346 rc
= virtsnd_ctl_query_info(snd
, VIRTIO_SND_R_PCM_INFO
, 0,
347 snd
->nsubstreams
, sizeof(*info
), info
);
351 for (i
= 0; i
< snd
->nsubstreams
; ++i
) {
352 struct virtio_pcm_substream
*vss
= &snd
->substreams
[i
];
353 struct virtio_pcm
*vpcm
;
357 INIT_WORK(&vss
->elapsed_period
, virtsnd_pcm_period_elapsed
);
358 init_waitqueue_head(&vss
->msg_empty
);
359 spin_lock_init(&vss
->lock
);
361 rc
= virtsnd_pcm_build_hw(vss
, &info
[i
]);
365 vss
->nid
= le32_to_cpu(info
[i
].hdr
.hda_fn_nid
);
367 vpcm
= virtsnd_pcm_find_or_create(snd
, vss
->nid
);
373 switch (info
[i
].direction
) {
374 case VIRTIO_SND_D_OUTPUT
:
375 vss
->direction
= SNDRV_PCM_STREAM_PLAYBACK
;
377 case VIRTIO_SND_D_INPUT
:
378 vss
->direction
= SNDRV_PCM_STREAM_CAPTURE
;
381 dev_err(&vdev
->dev
, "SID %u: unknown direction (%u)\n",
382 vss
->sid
, info
[i
].direction
);
387 vpcm
->streams
[vss
->direction
].nsubstreams
++;
397 * virtsnd_pcm_build_devs() - Build ALSA PCM devices.
398 * @snd: VirtIO sound device.
400 * Context: Any context that permits to sleep.
401 * Return: 0 on success, -errno on failure.
403 int virtsnd_pcm_build_devs(struct virtio_snd
*snd
)
405 struct virtio_device
*vdev
= snd
->vdev
;
406 struct virtio_pcm
*vpcm
;
410 list_for_each_entry(vpcm
, &snd
->pcm_list
, list
) {
412 vpcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].nsubstreams
;
414 vpcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].nsubstreams
;
419 rc
= snd_pcm_new(snd
->card
, VIRTIO_SND_CARD_DRIVER
, vpcm
->nid
,
420 npbs
, ncps
, &vpcm
->pcm
);
422 dev_err(&vdev
->dev
, "snd_pcm_new[%u] failed: %d\n",
427 vpcm
->pcm
->info_flags
= 0;
428 vpcm
->pcm
->dev_class
= SNDRV_PCM_CLASS_GENERIC
;
429 vpcm
->pcm
->dev_subclass
= SNDRV_PCM_SUBCLASS_GENERIC_MIX
;
430 snprintf(vpcm
->pcm
->name
, sizeof(vpcm
->pcm
->name
),
431 VIRTIO_SND_PCM_NAME
" %u", vpcm
->pcm
->device
);
432 vpcm
->pcm
->private_data
= vpcm
;
433 vpcm
->pcm
->nonatomic
= true;
435 for (i
= 0; i
< ARRAY_SIZE(vpcm
->streams
); ++i
) {
436 struct virtio_pcm_stream
*stream
= &vpcm
->streams
[i
];
438 if (!stream
->nsubstreams
)
442 devm_kcalloc(&vdev
->dev
, stream
->nsubstreams
,
443 sizeof(*stream
->substreams
),
445 if (!stream
->substreams
)
448 stream
->nsubstreams
= 0;
452 for (i
= 0; i
< snd
->nsubstreams
; ++i
) {
453 struct virtio_pcm_stream
*vs
;
454 struct virtio_pcm_substream
*vss
= &snd
->substreams
[i
];
456 vpcm
= virtsnd_pcm_find(snd
, vss
->nid
);
458 return PTR_ERR(vpcm
);
460 vs
= &vpcm
->streams
[vss
->direction
];
461 vs
->substreams
[vs
->nsubstreams
++] = vss
;
464 list_for_each_entry(vpcm
, &snd
->pcm_list
, list
) {
465 for (i
= 0; i
< ARRAY_SIZE(vpcm
->streams
); ++i
) {
466 struct virtio_pcm_stream
*vs
= &vpcm
->streams
[i
];
467 struct snd_pcm_str
*ks
= &vpcm
->pcm
->streams
[i
];
468 struct snd_pcm_substream
*kss
;
470 if (!vs
->nsubstreams
)
473 for (kss
= ks
->substream
; kss
; kss
= kss
->next
)
474 vs
->substreams
[kss
->number
]->substream
= kss
;
476 snd_pcm_set_ops(vpcm
->pcm
, i
, &virtsnd_pcm_ops
[i
]);
479 snd_pcm_set_managed_buffer_all(vpcm
->pcm
,
480 SNDRV_DMA_TYPE_VMALLOC
, NULL
,
488 * virtsnd_pcm_event() - Handle the PCM device event notification.
489 * @snd: VirtIO sound device.
490 * @event: VirtIO sound event.
492 * Context: Interrupt context.
494 void virtsnd_pcm_event(struct virtio_snd
*snd
, struct virtio_snd_event
*event
)
496 struct virtio_pcm_substream
*vss
;
497 u32 sid
= le32_to_cpu(event
->data
);
499 if (sid
>= snd
->nsubstreams
)
502 vss
= &snd
->substreams
[sid
];
504 switch (le32_to_cpu(event
->hdr
.code
)) {
505 case VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED
:
506 /* TODO: deal with shmem elapsed period */
508 case VIRTIO_SND_EVT_PCM_XRUN
:
509 spin_lock(&vss
->lock
);
510 if (vss
->xfer_enabled
)
511 vss
->xfer_xrun
= true;
512 spin_unlock(&vss
->lock
);