ASoC: Intel: Skylake: Add D0i3 mode ref counting

For device opened/closed, we check the D0i3 capability for the device
and invoke skl_tplg_d0i3_get/put, which counts the use case based on the
mode supported.

These counters are then used to decide if the device can enter D0i3 mode
of streaming or non-streaming or no D0i3.

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:
Vinod Koul 2016-11-03 17:07:20 +05:30 committed by Mark Brown
parent 6bd9dcf339
commit a83e3b4c44
6 changed files with 74 additions and 0 deletions

View File

@ -610,10 +610,15 @@ int bxt_sst_dsp_init(struct device *dev, void __iomem *mmio_base, int irq,
if (ret)
return ret;
/* set the D0i3 check */
skl->ipc.ops.check_dsp_lp_on = skl_ipc_check_D0i0;
skl->cores.count = 2;
skl->boot_complete = false;
init_waitqueue_head(&skl->boot_wait);
skl->is_first_boot = true;
INIT_DELAYED_WORK(&skl->d0i3.work, bxt_set_dsp_D0i3);
skl->d0i3.state = SKL_DSP_D0I3_NONE;
if (dsp)
*dsp = skl;

View File

@ -144,6 +144,8 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
struct hdac_ext_stream *stream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct skl_dma_params *dma_params;
struct skl *skl = get_skl_ctx(dai->dev);
struct skl_module_cfg *mconfig;
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
@ -177,6 +179,9 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
skl_set_suspend_active(substream, dai, true);
snd_pcm_set_sync(substream);
mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
skl_tplg_d0i3_get(skl, mconfig->d0i3_caps);
return 0;
}
@ -302,6 +307,7 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
struct skl_dma_params *dma_params = NULL;
struct skl *skl = ebus_to_skl(ebus);
struct skl_module_cfg *mconfig;
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
@ -325,6 +331,9 @@ static void skl_pcm_close(struct snd_pcm_substream *substream,
skl->skl_sst->miscbdcg_disabled = false;
}
mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
skl_tplg_d0i3_put(skl, mconfig->d0i3_caps);
kfree(dma_params);
}

View File

@ -306,6 +306,23 @@ static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
header->primary | SKL_ADSP_REG_HIPCI_BUSY);
}
int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state)
{
int ret;
/* check D0i3 support */
if (!dsp->fw_ops.set_state_D0i0)
return 0;
/* Attempt D0i0 or D0i3 based on state */
if (state)
ret = dsp->fw_ops.set_state_D0i0(dsp);
else
ret = dsp->fw_ops.set_state_D0i3(dsp);
return ret;
}
static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
u64 ipc_header)
{

View File

@ -187,6 +187,8 @@ int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc,
struct skl_ipc_d0ix_msg *msg);
int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state);
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);

View File

@ -36,6 +36,44 @@
#define SKL_IN_DIR_BIT_MASK BIT(0)
#define SKL_PIN_COUNT_MASK GENMASK(7, 4)
void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
{
struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
switch (caps) {
case SKL_D0I3_NONE:
d0i3->non_d0i3++;
break;
case SKL_D0I3_STREAMING:
d0i3->streaming++;
break;
case SKL_D0I3_NON_STREAMING:
d0i3->non_streaming++;
break;
}
}
void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps)
{
struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
switch (caps) {
case SKL_D0I3_NONE:
d0i3->non_d0i3--;
break;
case SKL_D0I3_STREAMING:
d0i3->streaming--;
break;
case SKL_D0I3_NON_STREAMING:
d0i3->non_streaming--;
break;
}
}
/*
* SKL DSP driver modelling uses only few DAPM widgets so for rest we will
* ignore. This helpers checks if the SKL driver handles this widget type

View File

@ -369,6 +369,9 @@ struct skl_module_cfg *skl_tplg_fe_get_cpr_module(
int skl_tplg_update_pipe_params(struct device *dev,
struct skl_module_cfg *mconfig, struct skl_pipe_params *params);
void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps);
void skl_tplg_d0i3_put(struct skl *skl, enum d0i3_capability caps);
int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe);
int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);