Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/drivers/intel/baytrail/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ void ipc_platform_do_cmd(struct ipc *ipc)

// TODO: signal audio work to enter D3 in normal context
/* are we about to enter D3 ? */
if (iipc->pm_prepare_D3) {
if (iipc->pm_target_state == SOF_PM_STATE_D3) {
while (1) {
wait_for_interrupt(0);
}
Expand Down Expand Up @@ -235,7 +235,7 @@ int platform_ipc_init(struct ipc *ipc)
iipc->dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED);

/* PM */
iipc->pm_prepare_D3 = 0;
iipc->pm_target_state = SOF_PM_STATE_D0; /* initial value */

/* configure interrupt */
interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK,
Expand Down
6 changes: 3 additions & 3 deletions src/drivers/intel/cavs/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void ipc_platform_do_cmd(struct ipc *ipc)

/* are we about to enter D3 ? */
#if CAVS_VERSION < CAVS_VERSION_2_0
if (iipc->pm_prepare_D3) {
if (iipc->pm_target_state == SOF_PM_STATE_D3) {
/* no return - memory will be powered off and IPC sent */
platform_pm_runtime_power_off();
}
Expand All @@ -178,7 +178,7 @@ void ipc_platform_do_cmd(struct ipc *ipc)
ipc_write(IPC_DIPCCTL, ipc_read(IPC_DIPCCTL) | IPC_DIPCCTL_IPCTBIE);

#if CAVS_VERSION == CAVS_VERSION_2_0
if (iipc->pm_prepare_D3) {
if (iipc->pm_target_state == SOF_PM_STATE_D3) {
//TODO: add support for Icelake
while (1)
wait_for_interrupt(5);
Expand Down Expand Up @@ -246,7 +246,7 @@ int platform_ipc_init(struct ipc *ipc)
ipc_process_task, _ipc, 0, 0);

/* PM */
iipc->pm_prepare_D3 = 0;
iipc->pm_target_state = SOF_PM_STATE_D0; /* initial value */

/* configure interrupt */
interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK,
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/intel/cavs/sue-ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void ipc_platform_do_cmd(struct ipc *ipc)

// TODO: signal audio work to enter D3 in normal context
/* are we about to enter D3 ? */
if (iipc->pm_prepare_D3) {
if (iipc->pm_target_state == SOF_PM_STATE_D3) {
while (1)
wait_for_interrupt(0);
}
Expand Down Expand Up @@ -137,7 +137,7 @@ int platform_ipc_init(struct ipc *ipc)
ipc_process_task, _ipc, 0, 0);

/* PM */
iipc->pm_prepare_D3 = 0;
iipc->pm_target_state = SOF_PM_STATE_D0; /* initial value */

return 0;
}
4 changes: 2 additions & 2 deletions src/drivers/intel/haswell/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void ipc_platform_do_cmd(struct ipc *ipc)

// TODO: signal audio work to enter D3 in normal context
/* are we about to enter D3 ? */
if (iipc->pm_prepare_D3) {
if (iipc->pm_target_state == SOF_PM_STATE_D3) {
while (1) {
wait_for_interrupt(0);
}
Expand Down Expand Up @@ -225,7 +225,7 @@ int platform_ipc_init(struct ipc *ipc)
iipc->dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED);

/* PM */
iipc->pm_prepare_D3 = 0;
iipc->pm_target_state = SOF_PM_STATE_D0; /* initial value */

/* configure interrupt */
interrupt_register(PLATFORM_IPC_INTERRUPT, IRQ_AUTO_UNMASK,
Expand Down
2 changes: 1 addition & 1 deletion src/host/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ int platform_ipc_init(struct ipc *ipc)
bzero(iipc->page_table, HOST_PAGE_SIZE);

/* PM */
iipc->pm_prepare_D3 = 0;
iipc->pm_target_state = SOF_PM_STATE_D0; /* initial value */

return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion src/include/sof/ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <sof/audio/component.h>
#include <sof/dma-trace.h>
#include <sof/preproc.h>
#include <uapi/ipc/pm.h>

struct sof;
struct dai_config;
Expand Down Expand Up @@ -211,7 +212,7 @@ struct ipc_data {
uint8_t *page_table;

/* PM */
int pm_prepare_D3; /* do we need to prepare for D3 */
uint32_t pm_target_state; /* SOF_PM_STATE_D.. */
};

int ipc_cmd(void);
Expand Down
2 changes: 1 addition & 1 deletion src/include/uapi/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

/** \brief SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 6
#define SOF_ABI_MINOR 7
#define SOF_ABI_PATCH 0

/** \brief SOF ABI version number. Format within 32bit word is MMmmmppp */
Expand Down
2 changes: 2 additions & 0 deletions src/include/uapi/ipc/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
#define SOF_IPC_PM_CLK_GET SOF_CMD_TYPE(0x005)
#define SOF_IPC_PM_CLK_REQ SOF_CMD_TYPE(0x006)
#define SOF_IPC_PM_CORE_ENABLE SOF_CMD_TYPE(0x007)
#define SOF_IPC_PM_STATE_SET SOF_CMD_TYPE(0x008)
Comment thread
lgirdwood marked this conversation as resolved.
Resolved

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this deprecate PM_CTX_SAVE/RESTORE then?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for now PM_CTX_SAVE/RESTORE would be backward compatible to for D3 entry transition effectively, mid-term they would become deprecated
Could we switch to https://github.com/orgs/thesofproject/teams/sof-developers/discussions/ for a discussion on pm flows ?

#define SOF_IPC_PM_STATE_GET SOF_CMD_TYPE(0x009)

/** \name DSP Command: Component runtime config - multiple different types
* @{
Expand Down
45 changes: 45 additions & 0 deletions src/include/uapi/ipc/pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,49 @@ struct sof_ipc_pm_core_config {
uint32_t enable_mask;
} __attribute__((packed));

/* DSP subsystem power states */
enum sof_pm_state {
SOF_PM_STATE_D0 = 0, /* D0 only, also initial state */
SOF_PM_STATE_D3, /* D3 DSP subsystem is power gated*/
/* internal FW transitions across D0ix substates incl. D0 are allowed */
SOF_PM_STATE_D0ix,
};

/* Flags to allow FW for applying internally clock gating policies */
enum sof_pm_cg {
SOF_PM_CG_ON = 0, /* Clock gating enabled, */
SOF_PM_CG_OFF, /* Clock gating disabled */
};

/* Flags to allow FW for applying power gating policies */
enum sof_pm_pg {
SOF_PM_PG_ON = 0, /* Power gating enabled, */
SOF_PM_PG_OFF, /* Power gating disabled */
};

/* PM state - SOF_IPC_PM_STATE_SET */
struct sof_ipc_pm_state {
struct sof_ipc_cmd_hdr hdr;

uint32_t pm_state; /**< power state SOF_PM_STATE_D.. */
/**< flag to disable FW logic for autonomous D0ix<->D0 transitions */
uint32_t prevent_power_gating;
/**< flag to disable FW logic for autonomous clock gating */
uint32_t prevent_clock_gating;
/**< reserved for future use */
uint32_t reserved[8];
} __attribute__((packed));

/* PM params info reply - SOF_IPC_PM_STATE_GET */
struct sof_ipc_pm_state_reply {
struct sof_ipc_reply rhdr;
uint32_t pm_state; /**< power state SOF_PM_STATE_D.. */
/**< flag to disable FW logic for autonomous D0ix<->D0 transitions */
uint32_t prevent_power_gating;
/**< flag to disable FW logic for autonomous clock gating */
uint32_t prevent_clock_gating;
/**< reserved for future use */
uint32_t reserved[8];
} __attribute__((packed));

#endif
47 changes: 46 additions & 1 deletion src/ipc/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ static int ipc_pm_context_save(uint32_t header)
/* write the context to the host driver */
//mailbox_hostbox_write(0, pm_ctx, sizeof(*pm_ctx));

iipc->pm_prepare_D3 = 1;
iipc->pm_target_state = SOF_PM_STATE_D3;

return 0;
}
Expand Down Expand Up @@ -687,6 +687,47 @@ static int ipc_pm_core_enable(uint32_t header)
return 0;
}

/* set power management state */
static int ipc_pm_state_set(uint32_t header)
{
struct sof_ipc_pm_state pm_state;
struct ipc_data *iipc = ipc_get_drvdata(_ipc);

/* copy message with ABI safe method */
IPC_COPY_CMD(pm_state, _ipc->comp_data);

trace_ipc("ipc: pm state: %d, prevent: cg %d pg %d -> set",
pm_state.pm_state, pm_state.prevent_clock_gating,
pm_state.prevent_power_gating);

iipc->pm_target_state = pm_state.pm_state;
/* TODO: add handling for clock & power gating policies */

return 0;
}

/* get power management state */
static int ipc_pm_state_get(uint32_t header)
{
struct sof_ipc_pm_state_reply reply;
struct ipc_data *iipc = ipc_get_drvdata(_ipc);

/* write component values to the outbox */
reply.rhdr.hdr.size = sizeof(reply);
reply.rhdr.hdr.cmd = header;
reply.rhdr.error = 0;
reply.pm_state = iipc->pm_target_state;
reply.prevent_clock_gating = 0; /* TODO: add data handling*/
reply.prevent_power_gating = 0; /* TODO: add data handling */

trace_ipc("ipc: pm state: %d, prevent: cg %d pg %d -> get",
reply.pm_state, reply.prevent_clock_gating,
reply.prevent_power_gating);

mailbox_hostbox_write(0, &reply, sizeof(reply));
return 1;
}

static int ipc_glb_pm_message(uint32_t header)
{
uint32_t cmd = iCS(header);
Expand All @@ -700,6 +741,10 @@ static int ipc_glb_pm_message(uint32_t header)
return ipc_pm_context_size(header);
case SOF_IPC_PM_CORE_ENABLE:
return ipc_pm_core_enable(header);
case SOF_IPC_PM_STATE_SET:
return ipc_pm_state_set(header);
case SOF_IPC_PM_STATE_GET:
return ipc_pm_state_get(header);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lbetlej just for my understanding. When would the driver use the ipc_pm_state_get()? Clearly when the DSP is in D3, this cannot be used.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ranj063 I'm not sure, but with IPCs from #1339 it may be possible, they work in D3 afaik.
@lbetlej am I right?

case SOF_IPC_PM_CLK_SET:
case SOF_IPC_PM_CLK_GET:
case SOF_IPC_PM_CLK_REQ:
Expand Down