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:
Родитель
6bd9dcf339
Коммит
a83e3b4c44
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче