Skip to content

Commit

Permalink
zephyr: cpu: Suspend and resume DAIs during D3 state transitions
Browse files Browse the repository at this point in the history
This patch introduces the suspension and resumption of Digital Audio
Interface (DAI) components in the SOF firmware when the system enters
and exits the D3 power state. The change ensures that DAI components are
properly powered down before the system enters D3 to conserve power and
are subsequently powered back up upon exiting D3 to resume normal
operation.

The implementation iterates over the component list to identify DAI
components and invokes the `dai_remove` function to suspend each DAI
before entering D3. Upon exiting D3, the `dai_probe` function is called
to resume the operation of each previously suspended DAI.

This approach helps maintain the integrity of the audio pipeline across
D3 state transitions and prevents issues that may arise from DAIs being
left in an undefined state during power transitions.

Signed-off-by: Tomasz Leman <[email protected]>
  • Loading branch information
tmleman committed Sep 10, 2024
1 parent 8c75f80 commit e3887e4
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions zephyr/lib/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
* \authors Tomasz Leman <[email protected]>
*/

#include <sof/audio/component.h>
#include <sof/init.h>
#include <sof/lib/cpu.h>
#include <sof/lib/pm_runtime.h>
#include <ipc/topology.h>
#include <module/module/base.h>
#include <rtos/alloc.h>

#include "../audio/copier/copier.h"

/* Zephyr includes */
#include <version.h>
#include <zephyr/kernel.h>
Expand Down Expand Up @@ -55,6 +59,11 @@ void cpu_notify_state_entry(enum pm_state state)
if (state == PM_STATE_SOFT_OFF) {
#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE
size_t storage_buffer_size;
struct ipc_comp_dev *icd;
struct list_item *clist;
struct processing_module *mod;
struct copier_data *cd;
struct dai_data *dd;

/* allocate IMR global_imr_ram_storage */
const struct device *tlb_dev = DEVICE_DT_GET(DT_NODELABEL(tlb));
Expand All @@ -80,6 +89,23 @@ void cpu_notify_state_entry(enum pm_state state)
k_panic();
}

/* Suspend all DAI components before entering D3 state. */
list_for_item(clist, &ipc_get()->comp_list) {
icd = container_of(clist, struct ipc_comp_dev, list);
if (icd->type != COMP_TYPE_COMPONENT)
continue;

if (dev_comp_type(icd->cd) == SOF_COMP_DAI) {
mod = comp_mod(icd->cd);
cd = module_get_private_data(mod);
dd = cd->dd[0];
if (dai_remove(dd->dai->dev) < 0) {
tr_err(&zephyr_tr, "DAI suspend failed, type %d index %d",
dd->dai->type, dd->dai->index);
}
}
}

#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */
}
}
Expand All @@ -99,6 +125,29 @@ void cpu_notify_state_exit(enum pm_state state)
#endif

#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE
struct ipc_comp_dev *icd;
struct list_item *clist;
struct processing_module *mod;
struct copier_data *cd;
struct dai_data *dd;

/* Resume all DAI components after exiting D3 state. */
list_for_item(clist, &ipc_get()->comp_list) {
icd = container_of(clist, struct ipc_comp_dev, list);
if (icd->type != COMP_TYPE_COMPONENT)
continue;

if (dev_comp_type(icd->cd) == SOF_COMP_DAI) {
mod = comp_mod(icd->cd);
cd = module_get_private_data(mod);
dd = cd->dd[0];
if (dai_probe(dd->dai->dev) < 0) {
tr_err(&zephyr_tr, "DAI resume failed, type %d index %d",
dd->dai->type, dd->dai->index);
}
}
}

/* free global_imr_ram_storage */
rfree(global_imr_ram_storage);
global_imr_ram_storage = NULL;
Expand Down

0 comments on commit e3887e4

Please sign in to comment.