|
@@ -34,33 +34,84 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
|
|
mutex_unlock(&ctx->mutex);
|
|
mutex_unlock(&ctx->mutex);
|
|
}
|
|
}
|
|
|
|
|
|
-static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
|
|
|
|
|
|
+/*
|
|
|
|
+ * Initialize core power state and usage count. To be called after
|
|
|
|
+ * successful first boot. Hence core 0 will be running and other cores
|
|
|
|
+ * will be reset
|
|
|
|
+ */
|
|
|
|
+void skl_dsp_init_core_state(struct sst_dsp *ctx)
|
|
|
|
+{
|
|
|
|
+ struct skl_sst *skl = ctx->thread_context;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ skl->cores.state[SKL_DSP_CORE0_ID] = SKL_DSP_RUNNING;
|
|
|
|
+ skl->cores.usage_count[SKL_DSP_CORE0_ID] = 1;
|
|
|
|
+
|
|
|
|
+ for (i = SKL_DSP_CORE0_ID + 1; i < SKL_DSP_CORES_MAX; i++) {
|
|
|
|
+ skl->cores.state[i] = SKL_DSP_RESET;
|
|
|
|
+ skl->cores.usage_count[i] = 0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Get the mask for all enabled cores */
|
|
|
|
+unsigned int skl_dsp_get_enabled_cores(struct sst_dsp *ctx)
|
|
|
|
+{
|
|
|
|
+ struct skl_sst *skl = ctx->thread_context;
|
|
|
|
+ unsigned int core_mask, en_cores_mask;
|
|
|
|
+ u32 val;
|
|
|
|
+
|
|
|
|
+ core_mask = SKL_DSP_CORES_MASK(skl->cores.count);
|
|
|
|
+
|
|
|
|
+ val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
|
|
|
|
+
|
|
|
|
+ /* Cores having CPA bit set */
|
|
|
|
+ en_cores_mask = (val & SKL_ADSPCS_CPA_MASK(core_mask)) >>
|
|
|
|
+ SKL_ADSPCS_CPA_SHIFT;
|
|
|
|
+
|
|
|
|
+ /* And cores having CRST bit cleared */
|
|
|
|
+ en_cores_mask &= (~val & SKL_ADSPCS_CRST_MASK(core_mask)) >>
|
|
|
|
+ SKL_ADSPCS_CRST_SHIFT;
|
|
|
|
+
|
|
|
|
+ /* And cores having CSTALL bit cleared */
|
|
|
|
+ en_cores_mask &= (~val & SKL_ADSPCS_CSTALL_MASK(core_mask)) >>
|
|
|
|
+ SKL_ADSPCS_CSTALL_SHIFT;
|
|
|
|
+ en_cores_mask &= core_mask;
|
|
|
|
+
|
|
|
|
+ dev_dbg(ctx->dev, "DSP enabled cores mask = %x\n", en_cores_mask);
|
|
|
|
+
|
|
|
|
+ return en_cores_mask;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+skl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* update bits */
|
|
/* update bits */
|
|
sst_dsp_shim_update_bits_unlocked(ctx,
|
|
sst_dsp_shim_update_bits_unlocked(ctx,
|
|
- SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK,
|
|
|
|
- SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK));
|
|
|
|
|
|
+ SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK(core_mask),
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask));
|
|
|
|
|
|
/* poll with timeout to check if operation successful */
|
|
/* poll with timeout to check if operation successful */
|
|
ret = sst_dsp_register_poll(ctx,
|
|
ret = sst_dsp_register_poll(ctx,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_CRST_MASK,
|
|
|
|
- SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK),
|
|
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask),
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask),
|
|
SKL_DSP_RESET_TO,
|
|
SKL_DSP_RESET_TO,
|
|
"Set reset");
|
|
"Set reset");
|
|
if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
|
|
if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
|
|
- SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) !=
|
|
|
|
- SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) {
|
|
|
|
- dev_err(ctx->dev, "Set reset state failed\n");
|
|
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask)) !=
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask)) {
|
|
|
|
+ dev_err(ctx->dev, "Set reset state failed: core_mask %x\n",
|
|
|
|
+ core_mask);
|
|
ret = -EIO;
|
|
ret = -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
|
|
|
|
|
|
+int skl_dsp_core_unset_reset_state(
|
|
|
|
+ struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
@@ -68,151 +119,160 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
|
|
|
|
|
|
/* update bits */
|
|
/* update bits */
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_CRST_MASK, 0);
|
|
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask), 0);
|
|
|
|
|
|
/* poll with timeout to check if operation successful */
|
|
/* poll with timeout to check if operation successful */
|
|
ret = sst_dsp_register_poll(ctx,
|
|
ret = sst_dsp_register_poll(ctx,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_CRST_MASK,
|
|
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask),
|
|
0,
|
|
0,
|
|
SKL_DSP_RESET_TO,
|
|
SKL_DSP_RESET_TO,
|
|
"Unset reset");
|
|
"Unset reset");
|
|
|
|
|
|
if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
|
|
if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
|
|
- SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) {
|
|
|
|
- dev_err(ctx->dev, "Unset reset state failed\n");
|
|
|
|
|
|
+ SKL_ADSPCS_CRST_MASK(core_mask)) != 0) {
|
|
|
|
+ dev_err(ctx->dev, "Unset reset state failed: core_mask %x\n",
|
|
|
|
+ core_mask);
|
|
ret = -EIO;
|
|
ret = -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static bool is_skl_dsp_core_enable(struct sst_dsp *ctx)
|
|
|
|
|
|
+static bool
|
|
|
|
+is_skl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
int val;
|
|
int val;
|
|
bool is_enable;
|
|
bool is_enable;
|
|
|
|
|
|
val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
|
|
val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
|
|
|
|
|
|
- is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) &&
|
|
|
|
- (val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) &&
|
|
|
|
- !(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) &&
|
|
|
|
- !(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)));
|
|
|
|
|
|
+ is_enable = ((val & SKL_ADSPCS_CPA_MASK(core_mask)) &&
|
|
|
|
+ (val & SKL_ADSPCS_SPA_MASK(core_mask)) &&
|
|
|
|
+ !(val & SKL_ADSPCS_CRST_MASK(core_mask)) &&
|
|
|
|
+ !(val & SKL_ADSPCS_CSTALL_MASK(core_mask)));
|
|
|
|
+
|
|
|
|
+ dev_dbg(ctx->dev, "DSP core(s) enabled? %d : core_mask %x\n",
|
|
|
|
+ is_enable, core_mask);
|
|
|
|
|
|
- dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable);
|
|
|
|
return is_enable;
|
|
return is_enable;
|
|
}
|
|
}
|
|
|
|
|
|
-static int skl_dsp_reset_core(struct sst_dsp *ctx)
|
|
|
|
|
|
+static int skl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
/* stall core */
|
|
/* stall core */
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_CSTALL_MASK,
|
|
|
|
- SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK));
|
|
|
|
|
|
+ SKL_ADSPCS_CSTALL_MASK(core_mask),
|
|
|
|
+ SKL_ADSPCS_CSTALL_MASK(core_mask));
|
|
|
|
|
|
/* set reset state */
|
|
/* set reset state */
|
|
- return skl_dsp_core_set_reset_state(ctx);
|
|
|
|
|
|
+ return skl_dsp_core_set_reset_state(ctx, core_mask);
|
|
}
|
|
}
|
|
|
|
|
|
-int skl_dsp_start_core(struct sst_dsp *ctx)
|
|
|
|
|
|
+int skl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* unset reset state */
|
|
/* unset reset state */
|
|
- ret = skl_dsp_core_unset_reset_state(ctx);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- dev_dbg(ctx->dev, "dsp unset reset fails\n");
|
|
|
|
|
|
+ ret = skl_dsp_core_unset_reset_state(ctx, core_mask);
|
|
|
|
+ if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
- }
|
|
|
|
|
|
|
|
/* run core */
|
|
/* run core */
|
|
- dev_dbg(ctx->dev, "run core...\n");
|
|
|
|
|
|
+ dev_dbg(ctx->dev, "unstall/run core: core_mask = %x\n", core_mask);
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_CSTALL_MASK, 0);
|
|
|
|
|
|
+ SKL_ADSPCS_CSTALL_MASK(core_mask), 0);
|
|
|
|
|
|
- if (!is_skl_dsp_core_enable(ctx)) {
|
|
|
|
- skl_dsp_reset_core(ctx);
|
|
|
|
- dev_err(ctx->dev, "DSP core enable failed\n");
|
|
|
|
|
|
+ if (!is_skl_dsp_core_enable(ctx, core_mask)) {
|
|
|
|
+ skl_dsp_reset_core(ctx, core_mask);
|
|
|
|
+ dev_err(ctx->dev, "DSP start core failed: core_mask %x\n",
|
|
|
|
+ core_mask);
|
|
ret = -EIO;
|
|
ret = -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-int skl_dsp_core_power_up(struct sst_dsp *ctx)
|
|
|
|
|
|
+int skl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* update bits */
|
|
/* update bits */
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK));
|
|
|
|
|
|
+ SKL_ADSPCS_SPA_MASK(core_mask),
|
|
|
|
+ SKL_ADSPCS_SPA_MASK(core_mask));
|
|
|
|
|
|
/* poll with timeout to check if operation successful */
|
|
/* poll with timeout to check if operation successful */
|
|
ret = sst_dsp_register_poll(ctx,
|
|
ret = sst_dsp_register_poll(ctx,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_CPA_MASK,
|
|
|
|
- SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK),
|
|
|
|
|
|
+ SKL_ADSPCS_CPA_MASK(core_mask),
|
|
|
|
+ SKL_ADSPCS_CPA_MASK(core_mask),
|
|
SKL_DSP_PU_TO,
|
|
SKL_DSP_PU_TO,
|
|
"Power up");
|
|
"Power up");
|
|
|
|
|
|
if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
|
|
if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
|
|
- SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) !=
|
|
|
|
- SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) {
|
|
|
|
- dev_err(ctx->dev, "DSP core power up failed\n");
|
|
|
|
|
|
+ SKL_ADSPCS_CPA_MASK(core_mask)) !=
|
|
|
|
+ SKL_ADSPCS_CPA_MASK(core_mask)) {
|
|
|
|
+ dev_err(ctx->dev, "DSP core power up failed: core_mask %x\n",
|
|
|
|
+ core_mask);
|
|
ret = -EIO;
|
|
ret = -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static int skl_dsp_core_power_down(struct sst_dsp *ctx)
|
|
|
|
|
|
+int skl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
/* update bits */
|
|
/* update bits */
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_SPA_MASK, 0);
|
|
|
|
|
|
+ SKL_ADSPCS_SPA_MASK(core_mask), 0);
|
|
|
|
|
|
/* poll with timeout to check if operation successful */
|
|
/* poll with timeout to check if operation successful */
|
|
return sst_dsp_register_poll(ctx,
|
|
return sst_dsp_register_poll(ctx,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
SKL_ADSP_REG_ADSPCS,
|
|
- SKL_ADSPCS_CPA_MASK,
|
|
|
|
|
|
+ SKL_ADSPCS_CPA_MASK(core_mask),
|
|
0,
|
|
0,
|
|
SKL_DSP_PD_TO,
|
|
SKL_DSP_PD_TO,
|
|
"Power down");
|
|
"Power down");
|
|
}
|
|
}
|
|
|
|
|
|
-int skl_dsp_enable_core(struct sst_dsp *ctx)
|
|
|
|
|
|
+int skl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
/* power up */
|
|
/* power up */
|
|
- ret = skl_dsp_core_power_up(ctx);
|
|
|
|
|
|
+ ret = skl_dsp_core_power_up(ctx, core_mask);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dev_dbg(ctx->dev, "dsp core power up failed\n");
|
|
|
|
|
|
+ dev_err(ctx->dev, "dsp core power up failed: core_mask %x\n",
|
|
|
|
+ core_mask);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- return skl_dsp_start_core(ctx);
|
|
|
|
|
|
+ return skl_dsp_start_core(ctx, core_mask);
|
|
}
|
|
}
|
|
|
|
|
|
-int skl_dsp_disable_core(struct sst_dsp *ctx)
|
|
|
|
|
|
+int skl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- ret = skl_dsp_reset_core(ctx);
|
|
|
|
|
|
+ ret = skl_dsp_reset_core(ctx, core_mask);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dev_err(ctx->dev, "dsp core reset failed\n");
|
|
|
|
|
|
+ dev_err(ctx->dev, "dsp core reset failed: core_mask %x\n",
|
|
|
|
+ core_mask);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/* power down core*/
|
|
/* power down core*/
|
|
- ret = skl_dsp_core_power_down(ctx);
|
|
|
|
|
|
+ ret = skl_dsp_core_power_down(ctx, core_mask);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dev_err(ctx->dev, "dsp core power down failed\n");
|
|
|
|
|
|
+ dev_err(ctx->dev, "dsp core power down fail mask %x: %d\n",
|
|
|
|
+ core_mask, ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- if (is_skl_dsp_core_enable(ctx)) {
|
|
|
|
- dev_err(ctx->dev, "DSP core disable failed\n");
|
|
|
|
|
|
+ if (is_skl_dsp_core_enable(ctx, core_mask)) {
|
|
|
|
+ dev_err(ctx->dev, "dsp core disable fail mask %x: %d\n",
|
|
|
|
+ core_mask, ret);
|
|
ret = -EIO;
|
|
ret = -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -223,28 +283,25 @@ int skl_dsp_boot(struct sst_dsp *ctx)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- if (is_skl_dsp_core_enable(ctx)) {
|
|
|
|
- dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n");
|
|
|
|
- ret = skl_dsp_reset_core(ctx);
|
|
|
|
|
|
+ if (is_skl_dsp_core_enable(ctx, SKL_DSP_CORE0_MASK)) {
|
|
|
|
+ ret = skl_dsp_reset_core(ctx, SKL_DSP_CORE0_MASK);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dev_err(ctx->dev, "dsp reset failed\n");
|
|
|
|
|
|
+ dev_err(ctx->dev, "dsp core0 reset fail: %d\n", ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
- ret = skl_dsp_start_core(ctx);
|
|
|
|
|
|
+ ret = skl_dsp_start_core(ctx, SKL_DSP_CORE0_MASK);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dev_err(ctx->dev, "dsp start failed\n");
|
|
|
|
|
|
+ dev_err(ctx->dev, "dsp core0 start fail: %d\n", ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n");
|
|
|
|
- ret = skl_dsp_disable_core(ctx);
|
|
|
|
-
|
|
|
|
|
|
+ ret = skl_dsp_disable_core(ctx, SKL_DSP_CORE0_MASK);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- dev_err(ctx->dev, "dsp disable core failes\n");
|
|
|
|
|
|
+ dev_err(ctx->dev, "dsp core0 disable fail: %d\n", ret);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
- ret = skl_dsp_enable_core(ctx);
|
|
|
|
|
|
+ ret = skl_dsp_enable_core(ctx, SKL_DSP_CORE0_MASK);
|
|
}
|
|
}
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
@@ -280,16 +337,74 @@ irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
|
|
|
|
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
+/*
|
|
|
|
+ * skl_dsp_get_core/skl_dsp_put_core will be called inside DAPM context
|
|
|
|
+ * within the dapm mutex. Hence no separate lock is used.
|
|
|
|
+ */
|
|
|
|
+int skl_dsp_get_core(struct sst_dsp *ctx, unsigned int core_id)
|
|
|
|
+{
|
|
|
|
+ struct skl_sst *skl = ctx->thread_context;
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ if (core_id >= skl->cores.count) {
|
|
|
|
+ dev_err(ctx->dev, "invalid core id: %d\n", core_id);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (skl->cores.state[core_id] == SKL_DSP_RESET) {
|
|
|
|
+ ret = ctx->fw_ops.set_state_D0(ctx, core_id);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(ctx->dev, "unable to get core%d\n", core_id);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ skl->cores.usage_count[core_id]++;
|
|
|
|
+
|
|
|
|
+ dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
|
|
|
|
+ core_id, skl->cores.state[core_id],
|
|
|
|
+ skl->cores.usage_count[core_id]);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(skl_dsp_get_core);
|
|
|
|
+
|
|
|
|
+int skl_dsp_put_core(struct sst_dsp *ctx, unsigned int core_id)
|
|
|
|
+{
|
|
|
|
+ struct skl_sst *skl = ctx->thread_context;
|
|
|
|
+ int ret = 0;
|
|
|
|
+
|
|
|
|
+ if (core_id >= skl->cores.count) {
|
|
|
|
+ dev_err(ctx->dev, "invalid core id: %d\n", core_id);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (--skl->cores.usage_count[core_id] == 0) {
|
|
|
|
+ ret = ctx->fw_ops.set_state_D3(ctx, core_id);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(ctx->dev, "unable to put core %d: %d\n",
|
|
|
|
+ core_id, ret);
|
|
|
|
+ skl->cores.usage_count[core_id]++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dev_dbg(ctx->dev, "core id %d state %d usage_count %d\n",
|
|
|
|
+ core_id, skl->cores.state[core_id],
|
|
|
|
+ skl->cores.usage_count[core_id]);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(skl_dsp_put_core);
|
|
|
|
|
|
int skl_dsp_wake(struct sst_dsp *ctx)
|
|
int skl_dsp_wake(struct sst_dsp *ctx)
|
|
{
|
|
{
|
|
- return ctx->fw_ops.set_state_D0(ctx);
|
|
|
|
|
|
+ return skl_dsp_get_core(ctx, SKL_DSP_CORE0_ID);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(skl_dsp_wake);
|
|
EXPORT_SYMBOL_GPL(skl_dsp_wake);
|
|
|
|
|
|
int skl_dsp_sleep(struct sst_dsp *ctx)
|
|
int skl_dsp_sleep(struct sst_dsp *ctx)
|
|
{
|
|
{
|
|
- return ctx->fw_ops.set_state_D3(ctx);
|
|
|
|
|
|
+ return skl_dsp_put_core(ctx, SKL_DSP_CORE0_ID);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(skl_dsp_sleep);
|
|
EXPORT_SYMBOL_GPL(skl_dsp_sleep);
|
|
|
|
|
|
@@ -336,9 +451,7 @@ void skl_dsp_free(struct sst_dsp *dsp)
|
|
|
|
|
|
free_irq(dsp->irq, dsp);
|
|
free_irq(dsp->irq, dsp);
|
|
skl_ipc_op_int_disable(dsp);
|
|
skl_ipc_op_int_disable(dsp);
|
|
- skl_ipc_int_disable(dsp);
|
|
|
|
-
|
|
|
|
- skl_dsp_disable_core(dsp);
|
|
|
|
|
|
+ skl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(skl_dsp_free);
|
|
EXPORT_SYMBOL_GPL(skl_dsp_free);
|
|
|
|
|