Skip to content

Commit 5709a61

Browse files
committed
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> # Conflicts: # sound/soc/sof/sof-priv.h
1 parent 1842d88 commit 5709a61

8 files changed

Lines changed: 603 additions & 20 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: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,27 @@ 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+
if (sdev->fw_state == new_state)
102+
return;
103+
104+
dev_dbg(sdev->dev, "New firmware state: %d\n", new_state);
105+
sdev->fw_state = new_state;
106+
107+
switch (new_state) {
108+
case SOF_FW_BOOT_NOT_STARTED:
109+
case SOF_FW_BOOT_COMPLETE:
110+
case SOF_FW_CRASHED:
111+
sof_client_fw_state_dispatcher(sdev);
112+
fallthrough;
113+
default:
114+
break;
115+
}
116+
}
117+
EXPORT_SYMBOL(sof_set_fw_state);
118+
98119
/*
99120
* FW Boot State Transition Diagram
100121
*
@@ -237,6 +258,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
237258
goto fw_trace_err;
238259
}
239260

261+
ret = sof_register_clients(sdev);
262+
if (ret < 0) {
263+
dev_err(sdev->dev, "error: failed to register clients %d\n", ret);
264+
goto sof_machine_err;
265+
}
266+
240267
/*
241268
* Some platforms in SOF, ex: BYT, may not have their platform PM
242269
* callbacks set. Increment the usage count so as to
@@ -252,6 +279,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
252279

253280
return 0;
254281

282+
sof_machine_err:
283+
snd_sof_machine_unregister(sdev, plat_data);
255284
fw_trace_err:
256285
snd_sof_free_trace(sdev);
257286
fw_run_err:
@@ -300,7 +329,6 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
300329

301330
sdev->pdata = plat_data;
302331
sdev->first_boot = true;
303-
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
304332
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
305333
sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
306334
#endif
@@ -321,9 +349,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
321349
INIT_LIST_HEAD(&sdev->widget_list);
322350
INIT_LIST_HEAD(&sdev->dai_list);
323351
INIT_LIST_HEAD(&sdev->route_list);
352+
INIT_LIST_HEAD(&sdev->ipc_client_list);
353+
INIT_LIST_HEAD(&sdev->ipc_rx_handler_list);
354+
INIT_LIST_HEAD(&sdev->fw_state_handler_list);
324355
spin_lock_init(&sdev->ipc_lock);
325356
spin_lock_init(&sdev->hw_lock);
326357
mutex_init(&sdev->power_state_access);
358+
mutex_init(&sdev->ipc_client_mutex);
359+
mutex_init(&sdev->client_event_handler_mutex);
327360

328361
/* set default timeouts if none provided */
329362
if (plat_data->desc->ipc_timeout == 0)
@@ -335,6 +368,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data)
335368
else
336369
sdev->boot_timeout = plat_data->desc->boot_timeout;
337370

371+
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED);
372+
338373
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) {
339374
INIT_WORK(&sdev->probe_work, sof_probe_work);
340375
schedule_work(&sdev->probe_work);
@@ -362,6 +397,12 @@ int snd_sof_device_remove(struct device *dev)
362397
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
363398
cancel_work_sync(&sdev->probe_work);
364399

400+
/*
401+
* Unregister any registered client device first before IPC and debugfs
402+
* to allow client drivers to be removed cleanly
403+
*/
404+
sof_unregister_clients(sdev);
405+
365406
/*
366407
* Unregister machine driver. This will unbind the snd_card which
367408
* 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
@@ -471,21 +471,25 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
471471
break;
472472
}
473473

474-
if (rx_callback) {
475-
/* read the full message as there we have rx handler for it */
476-
full_msg = kmalloc(hdr.size, GFP_KERNEL);
477-
if (!full_msg)
478-
return;
474+
/* read the full message as there we have rx handler for it */
475+
full_msg = kmalloc(hdr.size, GFP_KERNEL);
476+
if (!full_msg)
477+
return;
479478

480-
err = snd_sof_ipc_msg_data(sdev, NULL, full_msg, hdr.size);
481-
if (err < 0)
482-
dev_err(sdev->dev, "failed to read message\n");
483-
else
479+
err = snd_sof_ipc_msg_data(sdev, NULL, full_msg, hdr.size);
480+
if (err < 0) {
481+
dev_err(sdev->dev, "failed to read message\n");
482+
} else {
483+
/* Call local handler for the message */
484+
if (rx_callback)
484485
rx_callback(sdev, full_msg);
485486

486-
kfree(full_msg);
487+
/* Notify registered clients */
488+
sof_client_ipc_rx_dispatcher(sdev, full_msg);
487489
}
488490

491+
kfree(full_msg);
492+
489493
ipc_log_header(sdev->dev, "ipc rx done", hdr.cmd);
490494
}
491495
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)