ASoC: Intel: Skylake: Add D0iX IPCs

The audio DSP supports intermediate power states between D0 and D3
states. These states are D0i0 and D0i3 states.

Collectively we refer these two states as D0iX states.

To set or wake up from these states, driver also needs to send an IPC "Set D0iX
IPC" before doing anything else.

Add support for this new IPC messages.

Signed-off-by: Pardha Saradhi K <pardha.saradhi.kesapragada@intel.com>
Signed-off-by: Jayachandran B <jayachandran.b@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Pardha Saradhi K 2016-11-03 17:07:15 +05:30 committed by Mark Brown
parent 80a0df1819
commit 41b7523f19
2 changed files with 52 additions and 1 deletions

View file

@ -172,6 +172,17 @@
<< IPC_INITIAL_BLOCK_SHIFT)
#define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \
<< IPC_INITIAL_BLOCK_SHIFT)
/* Set D0ix IPC extension register */
#define IPC_D0IX_WAKE_SHIFT 0
#define IPC_D0IX_WAKE_MASK 0x1
#define IPC_D0IX_WAKE(x) (((x) & IPC_D0IX_WAKE_MASK) \
<< IPC_D0IX_WAKE_SHIFT)
#define IPC_D0IX_STREAMING_SHIFT 1
#define IPC_D0IX_STREAMING_MASK 0x1
#define IPC_D0IX_STREAMING(x) (((x) & IPC_D0IX_STREAMING_MASK) \
<< IPC_D0IX_STREAMING_SHIFT)
enum skl_ipc_msg_target {
IPC_FW_GEN_MSG = 0,
@ -258,7 +269,8 @@ enum skl_ipc_module_msg {
IPC_MOD_LARGE_CONFIG_SET = 4,
IPC_MOD_BIND = 5,
IPC_MOD_UNBIND = 6,
IPC_MOD_SET_DX = 7
IPC_MOD_SET_DX = 7,
IPC_MOD_SET_D0IX = 8
};
static void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
@ -931,3 +943,32 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
return ret;
}
EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
{
struct skl_ipc_header header = {0};
u64 *ipc_header = (u64 *)(&header);
int ret;
header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
header.primary |= IPC_MOD_ID(msg->module_id);
header.extension = IPC_D0IX_WAKE(msg->wake);
header.extension |= IPC_D0IX_STREAMING(msg->streaming);
dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
header.primary, header.extension);
/*
* Use the nopm IPC here as we dont want it checking for D0iX
*/
ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0);
if (ret < 0)
dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
return ret;
}
EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);

View file

@ -111,6 +111,13 @@ struct skl_ipc_large_config_msg {
u32 param_data_size;
};
struct skl_ipc_d0ix_msg {
u32 module_id;
u32 instance_id;
u8 streaming;
u8 wake;
};
#define SKL_IPC_BOOT_MSECS 3000
#define SKL_IPC_D3_MASK 0
@ -155,6 +162,9 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
u8 dma_id, u8 table_id);
int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc,
struct skl_ipc_d0ix_msg *msg);
void skl_ipc_int_enable(struct sst_dsp *dsp);
void skl_ipc_op_int_enable(struct sst_dsp *ctx);
void skl_ipc_op_int_disable(struct sst_dsp *ctx);