Skip to content

Commit 99db4d9

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 e92a9ce commit 99db4d9

8 files changed

Lines changed: 599 additions & 16 deletions

File tree

sound/soc/sof/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ config SND_SOC_SOF_DEBUG_PROBES
5959
Say Y if you want to enable probes.
6060
If unsure, select "N".
6161

62+
config SND_SOC_SOF_CLIENT
63+
tristate
64+
select AUXILIARY_BUS
65+
help
66+
This option is not user-selectable but automagically handled by
67+
'select' statements at a higher level.
68+
6269
config SND_SOC_SOF_DEVELOPER_SUPPORT
6370
bool "SOF developer options support"
6471
depends on EXPERT

sound/soc/sof/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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 iomem-utils.o sof-audio.o stream-ipc.o
5+
snd-sof-$(CONFIG_SND_SOC_SOF_CLIENT) += sof-client.o
56

67
snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += sof-probes.o
78
snd-sof-$(CONFIG_SND_SOC_SOF_COMPRESS) += compress.o

sound/soc/sof/core.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,23 @@ void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code,
9595
}
9696
EXPORT_SYMBOL(snd_sof_get_status);
9797

98+
/* Helper to manage DSP state */
99+
void sof_set_fw_state(struct snd_sof_dev *sdev, enum snd_sof_fw_state new_state)
100+
{
101+
sdev->fw_state = new_state;
102+
103+
switch (new_state) {
104+
case SOF_FW_BOOT_NOT_STARTED:
105+
case SOF_FW_BOOT_COMPLETE:
106+
case SOF_FW_CRASHED:
107+
sof_client_fw_state_dispatcher(sdev);
108+
fallthrough;
109+
default:
110+
break;
111+
}
112+
}
113+
EXPORT_SYMBOL(sof_set_fw_state);
114+
98115
/*
99116
* FW Boot State Transition Diagram
100117
*
@@ -237,6 +254,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
237254
goto fw_trace_err;
238255
}
239256

257+
ret = sof_register_clients(sdev);
258+
if (ret < 0) {
259+
dev_err(sdev->dev, "error: failed to register clients %d\n", ret);
260+
goto sof_machine_err;
261+
}
262+
240263
/*
241264
* Some platforms in SOF, ex: BYT, may not have their platform PM
242265
* callbacks set. Increment the usage count so as to
@@ -252,6 +275,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
252275

253276
return 0;
254277

278+
sof_machine_err:
279+
snd_sof_machine_unregister(sdev, plat_data);
255280
fw_trace_err:
256281
snd_sof_free_trace(sdev);
257282
fw_run_err:
@@ -300,7 +325,6 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
300325

301326
sdev->pdata = plat_data;
302327
sdev->first_boot = true;
303-
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
304328
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
305329
sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
306330
#endif
@@ -321,9 +345,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
321345
INIT_LIST_HEAD(&sdev->widget_list);
322346
INIT_LIST_HEAD(&sdev->dai_list);
323347
INIT_LIST_HEAD(&sdev->route_list);
348+
INIT_LIST_HEAD(&sdev->ipc_client_list);
349+
INIT_LIST_HEAD(&sdev->ipc_rx_handler_list);
350+
INIT_LIST_HEAD(&sdev->fw_state_handler_list);
324351
spin_lock_init(&sdev->ipc_lock);
325352
spin_lock_init(&sdev->hw_lock);
326353
mutex_init(&sdev->power_state_access);
354+
mutex_init(&sdev->ipc_client_mutex);
355+
mutex_init(&sdev->client_event_handler_mutex);
327356

328357
/* set default timeouts if none provided */
329358
if (plat_data->desc->ipc_timeout == 0)
@@ -335,6 +364,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
335364
else
336365
sdev->boot_timeout = plat_data->desc->boot_timeout;
337366

367+
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
368+
338369
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) {
339370
INIT_WORK(&sdev->probe_work, sof_probe_work);
340371
schedule_work(&sdev->probe_work);
@@ -362,6 +393,12 @@ int snd_sof_device_remove(struct device *dev)
362393
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
363394
cancel_work_sync(&sdev->probe_work);
364395

396+
/*
397+
* Unregister any registered client device first before IPC and debugfs
398+
* to allow client drivers to be removed cleanly
399+
*/
400+
sof_unregister_clients(sdev);
401+
365402
/*
366403
* Unregister machine driver. This will unbind the snd_card which
367404
* will remove the component driver and unload the topology

sound/soc/sof/ipc.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -465,21 +465,25 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
465465
break;
466466
}
467467

468-
if (rx_callback) {
469-
/* read the full message as there we have rx handler for it */
470-
full_msg = kmalloc(hdr.size, GFP_KERNEL);
471-
if (!full_msg)
472-
return;
468+
/* read the full message as there we have rx handler for it */
469+
full_msg = kmalloc(hdr.size, GFP_KERNEL);
470+
if (!full_msg)
471+
return;
473472

474-
err = snd_sof_ipc_msg_data(sdev, NULL, full_msg, hdr.size);
475-
if (err < 0)
476-
dev_err(sdev->dev, "failed to read message\n");
477-
else
473+
err = snd_sof_ipc_msg_data(sdev, NULL, full_msg, hdr.size);
474+
if (err < 0) {
475+
dev_err(sdev->dev, "failed to read message\n");
476+
} else {
477+
/* Call local handler for the message */
478+
if (rx_callback)
478479
rx_callback(sdev, full_msg);
479480

480-
kfree(full_msg);
481+
/* Notify registered clients */
482+
sof_client_ipc_rx_dispatcher(sdev, full_msg);
481483
}
482484

485+
kfree(full_msg);
486+
483487
ipc_log_header(sdev->dev, "ipc rx done", hdr.cmd);
484488
}
485489
EXPORT_SYMBOL(snd_sof_ipc_msgs_rx);

sound/soc/sof/pm.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ static int sof_resume(struct device *dev, bool runtime_resume)
165165
return ret;
166166
}
167167

168+
/* Notify clients about core resume */
169+
sof_resume_clients(sdev);
170+
168171
/* notify DSP of system resume */
169172
ret = sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_RESTORE);
170173
if (ret < 0)
@@ -178,6 +181,7 @@ static int sof_resume(struct device *dev, bool runtime_resume)
178181
static int sof_suspend(struct device *dev, bool runtime_suspend)
179182
{
180183
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
184+
pm_message_t pm_state = {};
181185
u32 target_state = 0;
182186
int ret;
183187

@@ -213,6 +217,9 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
213217
/* release trace */
214218
snd_sof_release_trace(sdev);
215219

220+
/* Notify clients about core suspend */
221+
sof_suspend_clients(sdev, pm_state);
222+
216223
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
217224
/* cache debugfs contents during runtime suspend */
218225
if (runtime_suspend)

0 commit comments

Comments
 (0)