Skip to content

Commit 481973c

Browse files
libinyanglgirdwood
authored andcommitted
ASoC: SOF: add sof vBE and vFE support
This patch adds the sof virtio BE and FE support. It will create a dev node for the communication to the userspace. It also handles the virtio vq event. It dispatches the different vq kicks to different handlers. In the virtio vq handling, it handles all the ipc events from vFE. When there is position update from FW, it will check whether there is an available entry in notification vq. If yes, send the position update notification immediately. If there is no available entry, add the position update event in a list. As soon as the notification vq has an available entry, send the position update to the vFE. For vFE, it will create a virtual audio device driver and communite with vBE audio driver to create PCMs and playback/capture streams. Signed-off-by: Libin Yang <libin.yang@intel.com>
1 parent 4a0e72f commit 481973c

File tree

14 files changed

+2000
-128
lines changed

14 files changed

+2000
-128
lines changed

include/sound/sof.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <uapi/sound/sof-ipc.h>
2323

2424
struct snd_sof_dsp_ops;
25+
struct virtio_device;
2526

2627
/* SOF probe type */
2728
enum sof_device_type {
@@ -53,6 +54,9 @@ struct snd_sof_pdata {
5354
struct device *dev;
5455
enum sof_device_type type;
5556

57+
struct sof_vfe *vfe;
58+
int is_vfe;
59+
5660
/* descriptor */
5761
const struct sof_dev_desc *desc;
5862

include/uapi/sound/sof-virtio.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2+
*
3+
* This file is provided under a dual BSD/GPLv2 license. When using or
4+
* redistributing this file, you may do so under either license.
5+
*
6+
* Copyright(c) 2018 Intel Corporation. All rights reserved.
7+
*
8+
* Contact Information:
9+
* Author: Luo Xionghu <xionghu.luo@intel.com>
10+
* Liam Girdwood <liam.r.girdwood@linux.intel.com>.
11+
*/
12+
13+
#ifndef _SOF_VIRTIO_H
14+
#define _SOF_VIRTIO_H
15+
16+
/* Currently we defined 4 vqs to do the IPC, CMD_TX is for send the msg
17+
* from FE to BE, and CMD_RX is to receive the reply. NOT_RX is to receive
18+
* the notification, and NOT_TX is to send empty buffer from FE to BE.
19+
* If we can handle the IPC with only 2 vqs, the config still need to
20+
* be changed in the device model(VM config), then only CMD_VQ and NOT_VQ
21+
* is needed.
22+
*/
23+
24+
#define SOF_VIRTIO_IPC_CMD_TX_VQ 0
25+
#define SOF_VIRTIO_IPC_CMD_RX_VQ 1
26+
#define SOF_VIRTIO_IPC_NOT_TX_VQ 2
27+
#define SOF_VIRTIO_IPC_NOT_RX_VQ 3
28+
#define SOF_VIRTIO_NUM_OF_VQS 4
29+
30+
/* command messages from FE to BE, trigger/open/hw_params and so on */
31+
#define SOF_VIRTIO_IPC_CMD_TX_VQ_NAME "sof-ipc-cmd-tx"
32+
33+
/* get the reply of the command message */
34+
#define SOF_VIRTIO_IPC_CMD_RX_VQ_NAME "sof-ipc-cmd-rx"
35+
36+
/* first the FE need send empty buffer to BE to get the notification */
37+
#define SOF_VIRTIO_IPC_NOT_TX_VQ_NAME "sof-ipc-not-tx"
38+
39+
/* the vq to get the notification */
40+
#define SOF_VIRTIO_IPC_NOT_RX_VQ_NAME "sof-ipc-not-rx"
41+
42+
#endif

sound/soc/intel/boards/bxt_tdf8532.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,18 @@ static struct snd_soc_dai_link broxton_tdf8532_dais[] = {
205205
.dpcm_playback = 1,
206206
.no_pcm = 1,
207207
},
208+
{
209+
/* SSP4 for vm */
210+
.name = "vm_dai_link",
211+
.id = 6,
212+
.cpu_dai_name = "SSP4 Pin",
213+
.codec_name = "i2c-INT34C3:00",
214+
.codec_dai_name = "tdf8532-hifi",
215+
.platform_name = "0000:00:0e.0",
216+
.ignore_suspend = 1,
217+
.dpcm_playback = 1,
218+
.no_pcm = 1,
219+
},
208220
};
209221

210222
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL)

sound/soc/sof/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ ccflags-y += -DDEBUG
44

55
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
66
control.o trace.o compressed.o utils.o
7+
8+
ifdef CONFIG_SND_SOC_SOF_VIRTIO_BE
9+
snd-sof-objs += virtio-be.o virtio-miscdev.o
10+
endif
11+
12+
ifdef CONFIG_SND_SOC_SOF_VIRTIO_FE
13+
snd-virtio-fe-objs += virtio-fe.o
14+
endif
15+
716
snd-sof-spi-objs := hw-spi.o
817

918
snd-sof-pci-objs := sof-pci-dev.o
@@ -16,6 +25,7 @@ obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o
1625
obj-$(CONFIG_SND_SOC_SOF_ACPI) += sof-acpi-dev.o
1726
obj-$(CONFIG_SND_SOC_SOF_PCI) += sof-pci-dev.o
1827
obj-$(CONFIG_SND_SOC_SOF_SPI) += sof-spi-dev.o
28+
obj-$(CONFIG_SND_SOC_SOF_VIRTIO_FE) += virtio-fe.o
1929

2030
obj-$(CONFIG_SND_SOC_SOF_SPIDSP) += snd-sof-spi.o
2131

sound/soc/sof/core.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ struct snd_sof_pcm *snd_sof_find_spcm_comp(struct snd_sof_dev *sdev,
8181

8282
return NULL;
8383
}
84+
EXPORT_SYMBOL(snd_sof_find_spcm_comp);
8485

8586
struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_sof_dev *sdev,
8687
unsigned int pcm_id)
@@ -224,6 +225,25 @@ int snd_sof_create_page_table(struct snd_sof_dev *sdev,
224225
return pages;
225226
}
226227

228+
static void sof_virtio_vfe_init(struct snd_sof_dev *sdev,
229+
struct snd_sof_pdata *plat_data)
230+
{
231+
sdev->is_vfe = plat_data->is_vfe;
232+
233+
/*
234+
* Currently we only support one VM. comp_id from 0 to
235+
* SOF_VIRTIO_MAX_GOS_COMPS - 1 is for SOS. Other comp_id numbers
236+
* are for VM1.
237+
* TBD: comp_id number range should be dynamically assigned when
238+
* multiple VMs are supported.
239+
*/
240+
if (sdev->is_vfe) {
241+
sdev->next_comp_id = SOF_VIRTIO_MAX_GOS_COMPS;
242+
sdev->vfe = plat_data->vfe;
243+
sdev->vfe->sdev = sdev;
244+
}
245+
}
246+
227247
/*
228248
* SOF Driver enumeration.
229249
*/
@@ -256,6 +276,7 @@ static int sof_probe(struct platform_device *pdev)
256276
INIT_LIST_HEAD(&sdev->widget_list);
257277
INIT_LIST_HEAD(&sdev->dai_list);
258278
INIT_LIST_HEAD(&sdev->route_list);
279+
INIT_LIST_HEAD(&sdev->vbe_list);
259280
dev_set_drvdata(&pdev->dev, sdev);
260281
spin_lock_init(&sdev->ipc_lock);
261282
spin_lock_init(&sdev->hw_lock);
@@ -288,13 +309,22 @@ static int sof_probe(struct platform_device *pdev)
288309
goto dbg_err;
289310
}
290311

312+
/* optionally register virtio miscdev */
313+
sof_virtio_miscdev_register(sdev);
314+
291315
/* init the IPC */
292316
sdev->ipc = snd_sof_ipc_init(sdev);
293317
if (!sdev->ipc) {
294318
dev_err(sdev->dev, "error: failed to init DSP IPC %d\n", ret);
295319
goto ipc_err;
296320
}
297321

322+
sof_virtio_vfe_init(sdev, plat_data);
323+
324+
/* vFE will not touch HW. Let's skip fw loading */
325+
if (sdev->is_vfe)
326+
goto skip_load_fw_and_trace;
327+
298328
/* load the firmware */
299329
ret = snd_sof_load_firmware(sdev, true);
300330
if (ret < 0) {
@@ -319,6 +349,8 @@ static int sof_probe(struct platform_device *pdev)
319349
"warning: failed to initialize trace %d\n", ret);
320350
}
321351

352+
skip_load_fw_and_trace:
353+
322354
/* now register audio DSP platform driver and dai */
323355
ret = snd_soc_register_component(&pdev->dev, &sdev->plat_drv,
324356
sdev->ops->drv,
@@ -383,6 +415,7 @@ static int sof_remove(struct platform_device *pdev)
383415
snd_soc_unregister_component(&pdev->dev);
384416
snd_sof_fw_unload(sdev);
385417
snd_sof_ipc_free(sdev);
418+
sof_virtio_miscdev_unregister();
386419
snd_sof_free_debug(sdev);
387420
snd_sof_release_trace(sdev);
388421
snd_sof_remove(sdev);

sound/soc/sof/ipc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,9 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
535535

536536
memcpy(&spcm->stream[direction].posn, &posn, sizeof(posn));
537537

538+
/* optionally update position for vBE */
539+
sof_vbe_update_guest_posn(sdev, &posn);
540+
538541
/* only inform ALSA for period_wakeup mode */
539542
if (!spcm->stream[direction].substream->runtime->no_period_wakeup)
540543
snd_pcm_period_elapsed(spcm->stream[direction].substream);

sound/soc/sof/pcm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,7 @@ static int sof_pcm_probe(struct snd_soc_component *component)
691691

692692
/* load the default topology */
693693
sdev->component = component;
694+
sdev->card = component->card;
694695

695696
switch (plat_data->type) {
696697
case SOF_DEVICE_SPI:

sound/soc/sof/sof-priv.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <uapi/sound/sof-ipc.h>
2323
#include <uapi/sound/sof-fw.h>
2424
#include <uapi/sound/asoc.h>
25+
#include <uapi/sound/sof-virtio.h>
2526
#include <sound/hdaudio.h>
2627
#include <sound/compress_driver.h>
2728

@@ -54,6 +55,11 @@
5455
#define SOF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
5556
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_FLOAT)
5657

58+
/* The maximum number of components a virtio guest vFE driver can use */
59+
#define SOF_VIRTIO_MAX_GOS_COMPS 1000
60+
61+
#define SOF_VIRTIO_COMP_ID_UNASSIGNED 0xffffffff
62+
5763
struct snd_sof_dev;
5864
struct snd_sof_ipc_msg;
5965
struct snd_sof_ipc;
@@ -62,6 +68,8 @@ struct snd_soc_tplg_ops;
6268
struct snd_soc_component;
6369
struct sof_intel_hda_dev;
6470
struct snd_sof_pdata;
71+
struct virtio_device;
72+
struct virtqueue;
6573

6674
/*
6775
* SOF DSP HW abstraction operations.
@@ -290,6 +298,47 @@ struct snd_sof_dai {
290298
struct list_head list; /* list in sdev dai list */
291299
};
292300

301+
/*
302+
* in virtio iovec array:
303+
* iovec[0]: the ipc message data between vFE and vBE
304+
* iovec[1]: the ipc reply data between vFE and vBE
305+
*/
306+
#define SOF_VIRTIO_IPC_MSG 0
307+
#define SOF_VIRTIO_IPC_REPLY 1
308+
309+
/* Virtio Frontend */
310+
struct sof_vfe {
311+
struct sof_virtio_priv *priv;
312+
struct snd_sof_dev *sdev;
313+
314+
/* IPC cmd from frontend to backend */
315+
struct virtqueue *ipc_cmd_tx_vq;
316+
317+
/* IPC cmd reply from backend to frontend */
318+
struct virtqueue *ipc_cmd_rx_vq;
319+
320+
/* IPC notification from backend to frontend */
321+
struct virtqueue *ipc_not_rx_vq;
322+
323+
/* IPC notification reply from frontend to backend */
324+
struct virtqueue *ipc_not_tx_vq;
325+
326+
/* position update work */
327+
struct work_struct posn_update_work;
328+
329+
/* current pending cmd message */
330+
struct snd_sof_ipc_msg *msg;
331+
332+
/* current and pending notification */
333+
struct snd_sof_ipc_msg *not;
334+
struct sof_ipc_stream_posn *posn;
335+
};
336+
337+
struct vbs_sof_posn {
338+
struct list_head list;
339+
struct sof_ipc_stream_posn pos;
340+
};
341+
293342
/*
294343
* SOF Device Level.
295344
*/
@@ -302,6 +351,7 @@ struct snd_sof_dev {
302351

303352
/* ASoC components */
304353
struct snd_soc_component_driver plat_drv;
354+
struct snd_soc_card *card;
305355

306356
/* DSP firmware boot */
307357
wait_queue_head_t boot_wait;
@@ -358,6 +408,11 @@ struct snd_sof_dev {
358408
wait_queue_head_t waitq;
359409
int code_loading;
360410

411+
/* virtio for BE and FE */
412+
struct list_head vbe_list;
413+
struct sof_vfe *vfe;
414+
int is_vfe;
415+
361416
/* DMA for Trace */
362417
struct snd_dma_buffer dmatb;
363418
struct snd_dma_buffer dmatp;
@@ -377,6 +432,29 @@ struct snd_sof_dev {
377432
#define sof_to_bus(s) (&(s)->hda->hbus.core)
378433
#define sof_to_hbus(s) (&(s)->hda->hbus)
379434

435+
#if IS_ENABLED(CONFIG_SND_SOC_SOF_VIRTIO_BE)
436+
int sof_virtio_miscdev_register(struct snd_sof_dev *sdev);
437+
int sof_virtio_miscdev_unregister(void);
438+
int sof_vbe_update_guest_posn(struct snd_sof_dev *sdev,
439+
struct sof_ipc_stream_posn *posn);
440+
#else
441+
static inline int sof_virtio_miscdev_register(struct snd_sof_dev *sdev)
442+
{
443+
return 0;
444+
}
445+
446+
static inline int sof_virtio_miscdev_unregister(void)
447+
{
448+
return 0;
449+
}
450+
451+
static inline int sof_vbe_update_guest_posn(struct snd_sof_dev *sdev,
452+
struct sof_ipc_stream_posn *posn)
453+
{
454+
return 0;
455+
}
456+
#endif
457+
380458
/*
381459
* SOF platform private struct used as drvdata of
382460
* platform dev (e.g. pci/acpi/spi...) drvdata.
@@ -494,10 +572,26 @@ int snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
494572
void *stack, size_t stack_size);
495573
int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev);
496574

575+
/*
576+
* VirtIO
577+
*/
578+
int sof_virtio_submit_guest_ipc(struct snd_sof_dev *sdev, int vm_id,
579+
void *ipc_buf, void *reply_buf,
580+
size_t count, size_t reply_sz);
581+
int snd_sof_virtio_fs_init(struct snd_sof_dev *sdev);
582+
int snd_sof_virtio_fs_release(void);
583+
int sof_virtio_update_guest_posn(void *ctx, struct sof_ipc_stream_posn *posn);
584+
int sof_virtio_try_update_guest_posn(struct snd_sof_dev *sdev,
585+
struct sof_ipc_stream_posn *posn);
586+
void sof_virtio_set_spcm_posn_offset(struct snd_sof_pcm *spcm, int direction);
587+
int sof_virtio_register_guest(void *ctx);
588+
int sof_virtio_release_guest(int id);
589+
497590
/*
498591
* Platform specific ops.
499592
*/
500593
extern struct snd_compr_ops sof_compressed_ops;
594+
extern struct snd_sof_dsp_ops snd_sof_virtio_fe_ops;
501595

502596
/*
503597
* Kcontrols.

0 commit comments

Comments
 (0)