Skip to content

Commit d03fc53

Browse files
ranj063ujfalusi
authored andcommitted
ASoC: SOF: Introduce IPC SOF client support
A client in the SOF (Sound Open Firmware) context is a driver that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Co-developed-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Fred Oh <fred.oh@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent 1082519 commit d03fc53

6 files changed

Lines changed: 210 additions & 0 deletions

File tree

sound/soc/sof/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ config SND_SOC_SOF_DEBUG_PROBES
5555
Say Y if you want to enable probes.
5656
If unsure, select "N".
5757

58+
5859
config SND_SOC_SOF_PCM_DISABLE_PAUSE
5960
bool "SOF disable pause push/release"
6061
help
@@ -64,6 +65,13 @@ config SND_SOC_SOF_PCM_DISABLE_PAUSE
6465
Say Y if you want to disable pause push/release
6566
If unsure, select "N".
6667

68+
config SND_SOC_SOF_CLIENT
69+
tristate
70+
select AUXILIARY_BUS
71+
help
72+
This option is not user-selectable but automagically handled by
73+
'select' statements at a higher level.
74+
6775
config SND_SOC_SOF_DEVELOPER_SUPPORT
6876
bool "SOF developer options support"
6977
depends on EXPERT

sound/soc/sof/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
44
control.o trace.o utils.o sof-audio.o
5+
snd-sof-$(CONFIG_SND_SOC_SOF_CLIENT) += sof-client.o
6+
57
snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o compress.o
68

79
snd-sof-pci-objs := sof-pci-dev.o

sound/soc/sof/core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,11 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
322322
INIT_LIST_HEAD(&sdev->widget_list);
323323
INIT_LIST_HEAD(&sdev->dai_list);
324324
INIT_LIST_HEAD(&sdev->route_list);
325+
INIT_LIST_HEAD(&sdev->ipc_client_list);
325326
spin_lock_init(&sdev->ipc_lock);
326327
spin_lock_init(&sdev->hw_lock);
327328
mutex_init(&sdev->power_state_access);
329+
mutex_init(&sdev->ipc_client_mutex);
328330

329331
/* set default timeouts if none provided */
330332
if (plat_data->desc->ipc_timeout == 0)

sound/soc/sof/sof-client.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
//
3+
// Copyright(c) 2021 Intel Corporation. All rights reserved.
4+
// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
5+
//
6+
7+
#include <linux/debugfs.h>
8+
#include <linux/errno.h>
9+
#include <linux/list.h>
10+
#include <linux/mutex.h>
11+
#include <linux/slab.h>
12+
#include "sof-client.h"
13+
#include "sof-priv.h"
14+
15+
static void sof_client_auxdev_release(struct device *dev)
16+
{
17+
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
18+
struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev);
19+
20+
kfree(cdev);
21+
}
22+
23+
static int sof_client_dev_add_data(struct sof_client_dev *cdev, const void *data,
24+
size_t size)
25+
{
26+
void *d = NULL;
27+
28+
if (data) {
29+
d = kmemdup(data, size, GFP_KERNEL);
30+
if (!d)
31+
return -ENOMEM;
32+
}
33+
34+
cdev->auxdev.dev.platform_data = d;
35+
return 0;
36+
}
37+
38+
int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id,
39+
const void *data, size_t size)
40+
{
41+
struct auxiliary_device *auxdev;
42+
struct sof_client_dev *cdev;
43+
int ret;
44+
45+
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
46+
if (!cdev)
47+
return -ENOMEM;
48+
49+
cdev->sdev = sdev;
50+
auxdev = &cdev->auxdev;
51+
auxdev->name = name;
52+
auxdev->dev.parent = sdev->dev;
53+
auxdev->dev.release = sof_client_auxdev_release;
54+
auxdev->id = id;
55+
56+
ret = sof_client_dev_add_data(cdev, data, size);
57+
if (ret < 0)
58+
return ret;
59+
60+
ret = auxiliary_device_init(auxdev);
61+
if (ret < 0) {
62+
dev_err(sdev->dev, "error: failed to initialize client dev %s\n", name);
63+
kfree(cdev);
64+
return ret;
65+
}
66+
67+
ret = auxiliary_device_add(&cdev->auxdev);
68+
if (ret < 0) {
69+
dev_err(sdev->dev, "error: failed to add client dev %s\n", name);
70+
/*
71+
* cdev will be freed when the release callback is invoked through
72+
* put_device()
73+
*/
74+
auxiliary_device_uninit(&cdev->auxdev);
75+
return ret;
76+
}
77+
78+
/* add to list of SOF client devices */
79+
mutex_lock(&sdev->ipc_client_mutex);
80+
list_add(&cdev->list, &sdev->ipc_client_list);
81+
mutex_unlock(&sdev->ipc_client_mutex);
82+
83+
return 0;
84+
}
85+
EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, SND_SOC_SOF_CLIENT);
86+
87+
void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id)
88+
{
89+
struct sof_client_dev *cdev, *_cdev;
90+
91+
mutex_lock(&sdev->ipc_client_mutex);
92+
93+
/*
94+
* cdev will be freed when the release callback for the auxiliary device
95+
* is invoked
96+
*/
97+
list_for_each_entry_safe(cdev, _cdev, &sdev->ipc_client_list, list) {
98+
if (!strcmp(cdev->auxdev.name, name) && cdev->auxdev.id == id) {
99+
list_del(&cdev->list);
100+
auxiliary_device_delete(&cdev->auxdev);
101+
auxiliary_device_uninit(&cdev->auxdev);
102+
break;
103+
}
104+
}
105+
106+
mutex_unlock(&sdev->ipc_client_mutex);
107+
}
108+
EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, SND_SOC_SOF_CLIENT);
109+
110+
int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
111+
void *reply_data, size_t reply_bytes)
112+
{
113+
struct sof_ipc_cmd_hdr *hdr = ipc_msg;
114+
115+
if (!hdr)
116+
return -EINVAL;
117+
118+
return sof_ipc_tx_message(cdev->sdev->ipc, hdr->cmd, ipc_msg, hdr->size,
119+
reply_data, reply_bytes);
120+
}
121+
EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT);
122+
123+
struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev)
124+
{
125+
return cdev->sdev->debugfs_root;
126+
}
127+
EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, SND_SOC_SOF_CLIENT);
128+
129+
/* DMA buffer allocation in client drivers must use the core SOF device */
130+
struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev)
131+
{
132+
return cdev->sdev->dev;
133+
}
134+
EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, SND_SOC_SOF_CLIENT);

sound/soc/sof/sof-client.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#ifndef __SOC_SOF_CLIENT_H
4+
#define __SOC_SOF_CLIENT_H
5+
6+
#include <linux/auxiliary_bus.h>
7+
#include <linux/device.h>
8+
#include <linux/list.h>
9+
10+
struct snd_sof_dev;
11+
struct dentry;
12+
13+
/**
14+
* struct sof_client_dev - SOF client device
15+
* @auxdev: auxiliary device
16+
* @sdev: pointer to SOF core device struct
17+
* @list: item in SOF core client dev list
18+
* @data: device specific data
19+
*/
20+
struct sof_client_dev {
21+
struct auxiliary_device auxdev;
22+
struct snd_sof_dev *sdev;
23+
struct list_head list;
24+
void *data;
25+
};
26+
27+
#define sof_client_dev_to_sof_dev(cdev) (cdev->sdev)
28+
29+
#define auxiliary_dev_to_sof_client_dev(auxiliary_dev) \
30+
container_of(auxiliary_dev, struct sof_client_dev, auxdev)
31+
32+
int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
33+
void *reply_data, size_t reply_bytes);
34+
35+
struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev);
36+
struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev);
37+
38+
#if IS_ENABLED(CONFIG_SND_SOC_SOF_CLIENT)
39+
int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id,
40+
const void *data, size_t size);
41+
void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id);
42+
#else
43+
static inline int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name,
44+
u32 id, const void *data, size_t size)
45+
{
46+
return 0;
47+
}
48+
49+
static inline void sof_client_dev_unregister(struct snd_sof_dev *sdev,
50+
const char *name, u32 id)
51+
{
52+
}
53+
#endif
54+
55+
#endif /* __SOC_SOF_CLIENT_H */

sound/soc/sof/sof-priv.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,15 @@ struct snd_sof_dev {
466466

467467
bool msi_enabled;
468468

469+
/*
470+
* Used to keep track of registered IPC client devices so that they can
471+
* be removed when the parent SOF module is removed.
472+
*/
473+
struct list_head ipc_client_list;
474+
475+
/* mutex to protect client list */
476+
struct mutex ipc_client_mutex;
477+
469478
void *private; /* core does not touch this */
470479
};
471480

0 commit comments

Comments
 (0)