-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SOF client support (auxiliary bus) #3007
Changes from all commits
a87a2b5
4d512ec
44b2a43
9115f5b
476d4c0
7274b1c
6a772ce
a858cfa
49abfdc
11f3b3a
20c9323
9e32894
bcaad35
92a48c2
9e675f2
deb5a0c
cba8df9
64a91b8
5f585a8
d6a888d
6677eec
68d6c63
39459f7
9e6b984
e8bab41
5c75bc5
b3089af
b269552
fd4a66c
5e3f492
f763eea
3bd20bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,34 @@ | ||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) | ||
|
||
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ | ||
control.o trace.o utils.o sof-audio.o stream-ipc.o | ||
|
||
snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += sof-probes.o | ||
control.o iomem-utils.o sof-audio.o stream-ipc.o | ||
snd-sof-$(CONFIG_SND_SOC_SOF_CLIENT) += sof-client.o | ||
|
||
snd-sof-pci-objs := sof-pci-dev.o | ||
snd-sof-acpi-objs := sof-acpi-dev.o | ||
snd-sof-of-objs := sof-of-dev.o | ||
|
||
snd-sof-ipc-test-objs := sof-client-ipc-test.o | ||
snd-sof-probes-objs := sof-client-probes.o | ||
snd-sof-dma-trace-objs := sof-client-dma-trace.o | ||
|
||
snd-sof-nocodec-objs := nocodec.o | ||
|
||
snd-sof-utils-objs := sof-utils.o | ||
|
||
obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o | ||
obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o | ||
|
||
obj-$(CONFIG_SND_SOC_SOF) += snd-sof-utils.o | ||
|
||
obj-$(CONFIG_SND_SOC_SOF_ACPI_DEV) += snd-sof-acpi.o | ||
obj-$(CONFIG_SND_SOC_SOF_OF) += snd-sof-of.o | ||
obj-$(CONFIG_SND_SOC_SOF_PCI_DEV) += snd-sof-pci.o | ||
|
||
obj-$(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) += snd-sof-ipc-test.o | ||
obj-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += snd-sof-probes.o | ||
obj-$(CONFIG_SND_SOC_SOF_DEBUG_DMA_TRACE) += snd-sof-dma-trace.o | ||
|
||
obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ | ||
obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/ | ||
obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,9 +14,6 @@ | |
#include <sound/sof.h> | ||
#include "sof-priv.h" | ||
#include "ops.h" | ||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) | ||
#include "sof-probes.h" | ||
#endif | ||
|
||
/* see SOF_DBG_ flags */ | ||
int sof_core_debug = IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE); | ||
|
@@ -95,6 +92,23 @@ void snd_sof_get_status(struct snd_sof_dev *sdev, u32 panic_code, | |
} | ||
EXPORT_SYMBOL(snd_sof_get_status); | ||
|
||
/* Helper to manage DSP state */ | ||
void sof_set_fw_state(struct snd_sof_dev *sdev, enum snd_sof_fw_state new_state) | ||
{ | ||
sdev->fw_state = new_state; | ||
|
||
switch (new_state) { | ||
case SOF_FW_BOOT_NOT_STARTED: | ||
case SOF_FW_BOOT_COMPLETE: | ||
case SOF_FW_CRASHED: | ||
sof_client_fw_state_dispatcher(sdev); | ||
fallthrough; | ||
default: | ||
break; | ||
} | ||
} | ||
EXPORT_SYMBOL(sof_set_fw_state); | ||
|
||
/* | ||
* FW Boot State Transition Diagram | ||
* | ||
|
@@ -147,7 +161,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) | |
return ret; | ||
} | ||
|
||
sdev->fw_state = SOF_FW_BOOT_PREPARE; | ||
sof_set_fw_state(sdev, SOF_FW_BOOT_PREPARE); | ||
|
||
/* check machine info */ | ||
ret = sof_machine_check(sdev); | ||
|
@@ -189,7 +203,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) | |
goto fw_load_err; | ||
} | ||
|
||
sdev->fw_state = SOF_FW_BOOT_IN_PROGRESS; | ||
sof_set_fw_state(sdev, SOF_FW_BOOT_IN_PROGRESS); | ||
|
||
/* | ||
* Boot the firmware. The FW boot status will be modified | ||
|
@@ -202,20 +216,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) | |
goto fw_run_err; | ||
} | ||
|
||
if (sof_core_debug & SOF_DBG_ENABLE_TRACE) { | ||
sdev->dtrace_is_supported = true; | ||
|
||
/* init DMA trace */ | ||
ret = snd_sof_init_trace(sdev); | ||
if (ret < 0) { | ||
/* non fatal */ | ||
dev_warn(sdev->dev, | ||
"warning: failed to initialize trace %d\n", | ||
ret); | ||
} | ||
} else { | ||
dev_dbg(sdev->dev, "SOF firmware trace disabled\n"); | ||
} | ||
if (sof_core_debug & SOF_DBG_ENABLE_TRACE) | ||
dev_dbg(sdev->dev, "SOF_DBG_ENABLE_TRACE is no longer used\n"); | ||
|
||
/* hereafter all FW boot flows are for PM reasons */ | ||
sdev->first_boot = false; | ||
|
@@ -227,14 +229,20 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) | |
if (ret < 0) { | ||
dev_err(sdev->dev, | ||
"error: failed to register DSP DAI driver %d\n", ret); | ||
goto fw_trace_err; | ||
goto fw_run_err; | ||
} | ||
|
||
ret = snd_sof_machine_register(sdev, plat_data); | ||
if (ret < 0) { | ||
dev_err(sdev->dev, | ||
"error: failed to register machine driver %d\n", ret); | ||
goto fw_trace_err; | ||
goto fw_run_err; | ||
} | ||
|
||
ret = sof_register_clients(sdev); | ||
plbossart marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (ret < 0) { | ||
dev_err(sdev->dev, "error: failed to register clients %d\n", ret); | ||
goto sof_machine_err; | ||
} | ||
|
||
/* | ||
|
@@ -252,8 +260,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) | |
|
||
return 0; | ||
|
||
fw_trace_err: | ||
snd_sof_free_trace(sdev); | ||
sof_machine_err: | ||
snd_sof_machine_unregister(sdev, plat_data); | ||
fw_run_err: | ||
snd_sof_fw_unload(sdev); | ||
fw_load_err: | ||
|
@@ -265,7 +273,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) | |
snd_sof_remove(sdev); | ||
|
||
/* all resources freed, update state to match */ | ||
sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; | ||
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED); | ||
sdev->first_boot = true; | ||
|
||
return ret; | ||
|
@@ -300,10 +308,6 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) | |
|
||
sdev->pdata = plat_data; | ||
sdev->first_boot = true; | ||
sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; | ||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) | ||
sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; | ||
#endif | ||
dev_set_drvdata(dev, sdev); | ||
|
||
/* check all mandatory ops */ | ||
|
@@ -321,9 +325,14 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) | |
INIT_LIST_HEAD(&sdev->widget_list); | ||
INIT_LIST_HEAD(&sdev->dai_list); | ||
INIT_LIST_HEAD(&sdev->route_list); | ||
INIT_LIST_HEAD(&sdev->ipc_client_list); | ||
INIT_LIST_HEAD(&sdev->ipc_rx_handler_list); | ||
INIT_LIST_HEAD(&sdev->fw_state_handler_list); | ||
spin_lock_init(&sdev->ipc_lock); | ||
spin_lock_init(&sdev->hw_lock); | ||
mutex_init(&sdev->power_state_access); | ||
mutex_init(&sdev->ipc_client_mutex); | ||
mutex_init(&sdev->client_event_handler_mutex); | ||
plbossart marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/* set default timeouts if none provided */ | ||
if (plat_data->desc->ipc_timeout == 0) | ||
|
@@ -335,6 +344,8 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) | |
else | ||
sdev->boot_timeout = plat_data->desc->boot_timeout; | ||
|
||
sof_set_fw_state(sdev, SOF_FW_BOOT_NOT_STARTED); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. squash this change in previous patch? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The main reason for moving this is the introduction of the notification for clients which uses |
||
|
||
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) { | ||
INIT_WORK(&sdev->probe_work, sof_probe_work); | ||
schedule_work(&sdev->probe_work); | ||
|
@@ -362,6 +373,19 @@ int snd_sof_device_remove(struct device *dev) | |
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) | ||
cancel_work_sync(&sdev->probe_work); | ||
|
||
/* | ||
* Unregister any registered client device first before IPC and debugfs | ||
* to allow client drivers to be removed cleanly | ||
*/ | ||
sof_unregister_clients(sdev); | ||
|
||
plbossart marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/* | ||
* Unregister machine driver. This will unbind the snd_card which | ||
* will remove the component driver and unload the topology | ||
* before freeing the snd_card. | ||
*/ | ||
snd_sof_machine_unregister(sdev, pdata); | ||
|
||
if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) { | ||
ret = snd_sof_dsp_power_down_notify(sdev); | ||
if (ret < 0) | ||
|
@@ -370,16 +394,8 @@ int snd_sof_device_remove(struct device *dev) | |
|
||
snd_sof_ipc_free(sdev); | ||
snd_sof_free_debug(sdev); | ||
snd_sof_free_trace(sdev); | ||
} | ||
|
||
/* | ||
* Unregister machine driver. This will unbind the snd_card which | ||
* will remove the component driver and unload the topology | ||
* before freeing the snd_card. | ||
*/ | ||
snd_sof_machine_unregister(sdev, pdata); | ||
|
||
plbossart marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/* | ||
* Unregistering the machine driver results in unloading the topology. | ||
* Some widgets, ex: scheduler, attempt to power down the core they are | ||
|
@@ -414,3 +430,4 @@ MODULE_AUTHOR("Liam Girdwood"); | |
MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core"); | ||
MODULE_LICENSE("Dual BSD/GPL"); | ||
MODULE_ALIAS("platform:sof-audio"); | ||
MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Why is this different from the regular components?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
snd_soc_component_module_get()
is used for compressed only viasnd_soc_component_module_get_when_probe()
wrapper where thesubstream
parameter is NULL. We can not use thesnd_soc_component_module_get_when_open()
with compress stream as:expects snd_pcm_substream and not snd_compr_stream.
I should have used
snd_soc_component_compr_module_get_when_open()
andsnd_soc_component_compr_module_put_when_close()
to make it a cleanerIt might worth adding another mark to
struct snd_soc_component
, likestruct snd_compr_stream *mark_compr_module;
or
convert the
struct snd_pcm_substream *mark_module;
tovoid *mark_module;
or
convert all marks to
void *
IN the case of the later two the
snd_soc_component_module_get() should have
void *for the substream, probably named as
mark`There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we try to send it upstream to get feedback which way this should be?
I have now the renamed version locally, introducing
snd_soc_component_compr_module_get_when_open()
andsnd_soc_component_compr_module_put_when_close()
We piggyback on
compr_open
mark to manage the module_get/put to avoid introducing bigger changes for the framework and at the end the same thing is done for the normal components.