|
@@ -49,6 +49,9 @@ static const int mic_quatro_list[][SKL_CH_QUATRO] = {
|
|
{0, 1, 2, 3},
|
|
{0, 1, 2, 3},
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+#define CHECK_HW_PARAMS(ch, freq, bps, prm_ch, prm_freq, prm_bps) \
|
|
|
|
+ ((ch == prm_ch) && (bps == prm_bps) && (freq == prm_freq))
|
|
|
|
+
|
|
void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
|
|
void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
|
|
{
|
|
{
|
|
struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
|
|
struct skl_d0i3_data *d0i3 = &skl->skl_sst->d0i3;
|
|
@@ -153,8 +156,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl,
|
|
struct skl_module_cfg *mconfig)
|
|
struct skl_module_cfg *mconfig)
|
|
{
|
|
{
|
|
struct skl_sst *ctx = skl->skl_sst;
|
|
struct skl_sst *ctx = skl->skl_sst;
|
|
|
|
+ u8 res_idx = mconfig->res_idx;
|
|
|
|
+ struct skl_module_res *res = &mconfig->module->resources[res_idx];
|
|
|
|
|
|
- if (skl->resource.mcps + mconfig->mcps > skl->resource.max_mcps) {
|
|
|
|
|
|
+ if (skl->resource.mcps + res->cps > skl->resource.max_mcps) {
|
|
dev_err(ctx->dev,
|
|
dev_err(ctx->dev,
|
|
"%s: module_id %d instance %d\n", __func__,
|
|
"%s: module_id %d instance %d\n", __func__,
|
|
mconfig->id.module_id, mconfig->id.instance_id);
|
|
mconfig->id.module_id, mconfig->id.instance_id);
|
|
@@ -170,7 +175,10 @@ static bool skl_is_pipe_mcps_avail(struct skl *skl,
|
|
static void skl_tplg_alloc_pipe_mcps(struct skl *skl,
|
|
static void skl_tplg_alloc_pipe_mcps(struct skl *skl,
|
|
struct skl_module_cfg *mconfig)
|
|
struct skl_module_cfg *mconfig)
|
|
{
|
|
{
|
|
- skl->resource.mcps += mconfig->mcps;
|
|
|
|
|
|
+ u8 res_idx = mconfig->res_idx;
|
|
|
|
+ struct skl_module_res *res = &mconfig->module->resources[res_idx];
|
|
|
|
+
|
|
|
|
+ skl->resource.mcps += res->cps;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -179,7 +187,11 @@ static void skl_tplg_alloc_pipe_mcps(struct skl *skl,
|
|
static void
|
|
static void
|
|
skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig)
|
|
skl_tplg_free_pipe_mcps(struct skl *skl, struct skl_module_cfg *mconfig)
|
|
{
|
|
{
|
|
- skl->resource.mcps -= mconfig->mcps;
|
|
|
|
|
|
+ u8 res_idx = mconfig->res_idx;
|
|
|
|
+ struct skl_module_res *res = &mconfig->module->resources[res_idx];
|
|
|
|
+
|
|
|
|
+ res = &mconfig->module->resources[res_idx];
|
|
|
|
+ skl->resource.mcps -= res->cps;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -195,17 +207,21 @@ skl_tplg_free_pipe_mem(struct skl *skl, struct skl_module_cfg *mconfig)
|
|
static void skl_dump_mconfig(struct skl_sst *ctx,
|
|
static void skl_dump_mconfig(struct skl_sst *ctx,
|
|
struct skl_module_cfg *mcfg)
|
|
struct skl_module_cfg *mcfg)
|
|
{
|
|
{
|
|
|
|
+ struct skl_module_iface *iface = &mcfg->module->formats[0];
|
|
|
|
+
|
|
dev_dbg(ctx->dev, "Dumping config\n");
|
|
dev_dbg(ctx->dev, "Dumping config\n");
|
|
dev_dbg(ctx->dev, "Input Format:\n");
|
|
dev_dbg(ctx->dev, "Input Format:\n");
|
|
- dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt[0].channels);
|
|
|
|
- dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt[0].s_freq);
|
|
|
|
- dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt[0].ch_cfg);
|
|
|
|
- dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->in_fmt[0].valid_bit_depth);
|
|
|
|
|
|
+ dev_dbg(ctx->dev, "channels = %d\n", iface->inputs[0].fmt.channels);
|
|
|
|
+ dev_dbg(ctx->dev, "s_freq = %d\n", iface->inputs[0].fmt.s_freq);
|
|
|
|
+ dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->inputs[0].fmt.ch_cfg);
|
|
|
|
+ dev_dbg(ctx->dev, "valid bit depth = %d\n",
|
|
|
|
+ iface->inputs[0].fmt.valid_bit_depth);
|
|
dev_dbg(ctx->dev, "Output Format:\n");
|
|
dev_dbg(ctx->dev, "Output Format:\n");
|
|
- dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt[0].channels);
|
|
|
|
- dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt[0].s_freq);
|
|
|
|
- dev_dbg(ctx->dev, "valid bit depth = %d\n", mcfg->out_fmt[0].valid_bit_depth);
|
|
|
|
- dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt[0].ch_cfg);
|
|
|
|
|
|
+ dev_dbg(ctx->dev, "channels = %d\n", iface->outputs[0].fmt.channels);
|
|
|
|
+ dev_dbg(ctx->dev, "s_freq = %d\n", iface->outputs[0].fmt.s_freq);
|
|
|
|
+ dev_dbg(ctx->dev, "valid bit depth = %d\n",
|
|
|
|
+ iface->outputs[0].fmt.valid_bit_depth);
|
|
|
|
+ dev_dbg(ctx->dev, "ch_cfg = %d\n", iface->outputs[0].fmt.ch_cfg);
|
|
}
|
|
}
|
|
|
|
|
|
static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs)
|
|
static void skl_tplg_update_chmap(struct skl_module_fmt *fmt, int chs)
|
|
@@ -273,8 +289,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg,
|
|
struct skl_module_fmt *in_fmt, *out_fmt;
|
|
struct skl_module_fmt *in_fmt, *out_fmt;
|
|
|
|
|
|
/* Fixups will be applied to pin 0 only */
|
|
/* Fixups will be applied to pin 0 only */
|
|
- in_fmt = &m_cfg->in_fmt[0];
|
|
|
|
- out_fmt = &m_cfg->out_fmt[0];
|
|
|
|
|
|
+ in_fmt = &m_cfg->module->formats[0].inputs[0].fmt;
|
|
|
|
+ out_fmt = &m_cfg->module->formats[0].outputs[0].fmt;
|
|
|
|
|
|
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
if (is_fe) {
|
|
if (is_fe) {
|
|
@@ -312,21 +328,23 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
|
|
{
|
|
{
|
|
int multiplier = 1;
|
|
int multiplier = 1;
|
|
struct skl_module_fmt *in_fmt, *out_fmt;
|
|
struct skl_module_fmt *in_fmt, *out_fmt;
|
|
|
|
+ struct skl_module_res *res;
|
|
|
|
|
|
/* Since fixups is applied to pin 0 only, ibs, obs needs
|
|
/* Since fixups is applied to pin 0 only, ibs, obs needs
|
|
* change for pin 0 only
|
|
* change for pin 0 only
|
|
*/
|
|
*/
|
|
- in_fmt = &mcfg->in_fmt[0];
|
|
|
|
- out_fmt = &mcfg->out_fmt[0];
|
|
|
|
|
|
+ res = &mcfg->module->resources[0];
|
|
|
|
+ in_fmt = &mcfg->module->formats[0].inputs[0].fmt;
|
|
|
|
+ out_fmt = &mcfg->module->formats[0].outputs[0].fmt;
|
|
|
|
|
|
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
|
|
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
|
|
multiplier = 5;
|
|
multiplier = 5;
|
|
|
|
|
|
- mcfg->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) *
|
|
|
|
|
|
+ res->ibs = DIV_ROUND_UP(in_fmt->s_freq, 1000) *
|
|
in_fmt->channels * (in_fmt->bit_depth >> 3) *
|
|
in_fmt->channels * (in_fmt->bit_depth >> 3) *
|
|
multiplier;
|
|
multiplier;
|
|
|
|
|
|
- mcfg->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) *
|
|
|
|
|
|
+ res->obs = DIV_ROUND_UP(out_fmt->s_freq, 1000) *
|
|
out_fmt->channels * (out_fmt->bit_depth >> 3) *
|
|
out_fmt->channels * (out_fmt->bit_depth >> 3) *
|
|
multiplier;
|
|
multiplier;
|
|
}
|
|
}
|
|
@@ -365,6 +383,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
|
|
struct nhlt_specific_cfg *cfg;
|
|
struct nhlt_specific_cfg *cfg;
|
|
struct skl *skl = get_skl_ctx(ctx->dev);
|
|
struct skl *skl = get_skl_ctx(ctx->dev);
|
|
u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type);
|
|
u8 dev_type = skl_tplg_be_dev_type(m_cfg->dev_type);
|
|
|
|
+ int fmt_idx = m_cfg->fmt_idx;
|
|
|
|
+ struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx];
|
|
|
|
|
|
/* check if we already have blob */
|
|
/* check if we already have blob */
|
|
if (m_cfg->formats_config.caps_size > 0)
|
|
if (m_cfg->formats_config.caps_size > 0)
|
|
@@ -375,23 +395,23 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
|
|
case SKL_DEVICE_DMIC:
|
|
case SKL_DEVICE_DMIC:
|
|
link_type = NHLT_LINK_DMIC;
|
|
link_type = NHLT_LINK_DMIC;
|
|
dir = SNDRV_PCM_STREAM_CAPTURE;
|
|
dir = SNDRV_PCM_STREAM_CAPTURE;
|
|
- s_freq = m_cfg->in_fmt[0].s_freq;
|
|
|
|
- s_fmt = m_cfg->in_fmt[0].bit_depth;
|
|
|
|
- ch = m_cfg->in_fmt[0].channels;
|
|
|
|
|
|
+ s_freq = m_iface->inputs[0].fmt.s_freq;
|
|
|
|
+ s_fmt = m_iface->inputs[0].fmt.bit_depth;
|
|
|
|
+ ch = m_iface->inputs[0].fmt.channels;
|
|
break;
|
|
break;
|
|
|
|
|
|
case SKL_DEVICE_I2S:
|
|
case SKL_DEVICE_I2S:
|
|
link_type = NHLT_LINK_SSP;
|
|
link_type = NHLT_LINK_SSP;
|
|
if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) {
|
|
if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) {
|
|
dir = SNDRV_PCM_STREAM_PLAYBACK;
|
|
dir = SNDRV_PCM_STREAM_PLAYBACK;
|
|
- s_freq = m_cfg->out_fmt[0].s_freq;
|
|
|
|
- s_fmt = m_cfg->out_fmt[0].bit_depth;
|
|
|
|
- ch = m_cfg->out_fmt[0].channels;
|
|
|
|
|
|
+ s_freq = m_iface->outputs[0].fmt.s_freq;
|
|
|
|
+ s_fmt = m_iface->outputs[0].fmt.bit_depth;
|
|
|
|
+ ch = m_iface->outputs[0].fmt.channels;
|
|
} else {
|
|
} else {
|
|
dir = SNDRV_PCM_STREAM_CAPTURE;
|
|
dir = SNDRV_PCM_STREAM_CAPTURE;
|
|
- s_freq = m_cfg->in_fmt[0].s_freq;
|
|
|
|
- s_fmt = m_cfg->in_fmt[0].bit_depth;
|
|
|
|
- ch = m_cfg->in_fmt[0].channels;
|
|
|
|
|
|
+ s_freq = m_iface->inputs[0].fmt.s_freq;
|
|
|
|
+ s_fmt = m_iface->inputs[0].fmt.bit_depth;
|
|
|
|
+ ch = m_iface->inputs[0].fmt.channels;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -549,6 +569,7 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
|
|
struct snd_soc_dapm_widget *w;
|
|
struct snd_soc_dapm_widget *w;
|
|
struct skl_module_cfg *mconfig;
|
|
struct skl_module_cfg *mconfig;
|
|
struct skl_sst *ctx = skl->skl_sst;
|
|
struct skl_sst *ctx = skl->skl_sst;
|
|
|
|
+ u8 cfg_idx;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
list_for_each_entry(w_module, &pipe->w_list, node) {
|
|
list_for_each_entry(w_module, &pipe->w_list, node) {
|
|
@@ -564,11 +585,15 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
|
|
return -EIO;
|
|
return -EIO;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ cfg_idx = mconfig->pipe->cur_config_idx;
|
|
|
|
+ mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
|
|
|
|
+ mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
|
|
|
|
+
|
|
/* check resource available */
|
|
/* check resource available */
|
|
if (!skl_is_pipe_mcps_avail(skl, mconfig))
|
|
if (!skl_is_pipe_mcps_avail(skl, mconfig))
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
- if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
|
|
|
|
|
|
+ if (mconfig->module->loadable && ctx->dsp->fw_ops.load_mod) {
|
|
ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
|
|
ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
|
|
mconfig->id.module_id, mconfig->guid);
|
|
mconfig->id.module_id, mconfig->guid);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
@@ -596,24 +621,35 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
|
|
if (mconfig->id.pvt_id < 0)
|
|
if (mconfig->id.pvt_id < 0)
|
|
return ret;
|
|
return ret;
|
|
skl_tplg_set_module_init_data(w);
|
|
skl_tplg_set_module_init_data(w);
|
|
|
|
+
|
|
|
|
+ ret = skl_dsp_get_core(ctx->dsp, mconfig->core_id);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ dev_err(ctx->dev, "Failed to wake up core %d ret=%d\n",
|
|
|
|
+ mconfig->core_id, ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
ret = skl_init_module(ctx, mconfig);
|
|
ret = skl_init_module(ctx, mconfig);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
|
|
skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
|
|
- return ret;
|
|
|
|
|
|
+ goto err;
|
|
}
|
|
}
|
|
skl_tplg_alloc_pipe_mcps(skl, mconfig);
|
|
skl_tplg_alloc_pipe_mcps(skl, mconfig);
|
|
ret = skl_tplg_set_module_params(w, ctx);
|
|
ret = skl_tplg_set_module_params(w, ctx);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
- return ret;
|
|
|
|
|
|
+ goto err;
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
+err:
|
|
|
|
+ skl_dsp_put_core(ctx->dsp, mconfig->core_id);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
|
|
static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
|
|
struct skl_pipe *pipe)
|
|
struct skl_pipe *pipe)
|
|
{
|
|
{
|
|
- int ret;
|
|
|
|
|
|
+ int ret = 0;
|
|
struct skl_pipe_module *w_module = NULL;
|
|
struct skl_pipe_module *w_module = NULL;
|
|
struct skl_module_cfg *mconfig = NULL;
|
|
struct skl_module_cfg *mconfig = NULL;
|
|
|
|
|
|
@@ -622,7 +658,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
|
|
mconfig = w_module->w->priv;
|
|
mconfig = w_module->w->priv;
|
|
uuid_mod = (uuid_le *)mconfig->guid;
|
|
uuid_mod = (uuid_le *)mconfig->guid;
|
|
|
|
|
|
- if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod &&
|
|
|
|
|
|
+ if (mconfig->module->loadable && ctx->dsp->fw_ops.unload_mod &&
|
|
mconfig->m_state > SKL_MODULE_UNINIT) {
|
|
mconfig->m_state > SKL_MODULE_UNINIT) {
|
|
ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp,
|
|
ret = ctx->dsp->fw_ops.unload_mod(ctx->dsp,
|
|
mconfig->id.module_id);
|
|
mconfig->id.module_id);
|
|
@@ -630,10 +666,76 @@ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
|
|
return -EIO;
|
|
return -EIO;
|
|
}
|
|
}
|
|
skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
|
|
skl_put_pvt_id(ctx, uuid_mod, &mconfig->id.pvt_id);
|
|
|
|
+
|
|
|
|
+ ret = skl_dsp_put_core(ctx->dsp, mconfig->core_id);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ /* don't return; continue with other modules */
|
|
|
|
+ dev_err(ctx->dev, "Failed to sleep core %d ret=%d\n",
|
|
|
|
+ mconfig->core_id, ret);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* no modules to unload in this path, so return */
|
|
/* no modules to unload in this path, so return */
|
|
- return 0;
|
|
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Here, we select pipe format based on the pipe type and pipe
|
|
|
|
+ * direction to determine the current config index for the pipeline.
|
|
|
|
+ * The config index is then used to select proper module resources.
|
|
|
|
+ * Intermediate pipes currently have a fixed format hence we select the
|
|
|
|
+ * 0th configuratation by default for such pipes.
|
|
|
|
+ */
|
|
|
|
+static int
|
|
|
|
+skl_tplg_get_pipe_config(struct skl *skl, struct skl_module_cfg *mconfig)
|
|
|
|
+{
|
|
|
|
+ struct skl_sst *ctx = skl->skl_sst;
|
|
|
|
+ struct skl_pipe *pipe = mconfig->pipe;
|
|
|
|
+ struct skl_pipe_params *params = pipe->p_params;
|
|
|
|
+ struct skl_path_config *pconfig = &pipe->configs[0];
|
|
|
|
+ struct skl_pipe_fmt *fmt = NULL;
|
|
|
|
+ bool in_fmt = false;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (pipe->nr_cfgs == 0) {
|
|
|
|
+ pipe->cur_config_idx = 0;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) {
|
|
|
|
+ dev_dbg(ctx->dev, "No conn_type detected, take 0th config\n");
|
|
|
|
+ pipe->cur_config_idx = 0;
|
|
|
|
+ pipe->memory_pages = pconfig->mem_pages;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((pipe->conn_type == SKL_PIPE_CONN_TYPE_FE &&
|
|
|
|
+ pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) ||
|
|
|
|
+ (pipe->conn_type == SKL_PIPE_CONN_TYPE_BE &&
|
|
|
|
+ pipe->direction == SNDRV_PCM_STREAM_CAPTURE))
|
|
|
|
+ in_fmt = true;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < pipe->nr_cfgs; i++) {
|
|
|
|
+ pconfig = &pipe->configs[i];
|
|
|
|
+ if (in_fmt)
|
|
|
|
+ fmt = &pconfig->in_fmt;
|
|
|
|
+ else
|
|
|
|
+ fmt = &pconfig->out_fmt;
|
|
|
|
+
|
|
|
|
+ if (CHECK_HW_PARAMS(params->ch, params->s_freq, params->s_fmt,
|
|
|
|
+ fmt->channels, fmt->freq, fmt->bps)) {
|
|
|
|
+ pipe->cur_config_idx = i;
|
|
|
|
+ pipe->memory_pages = pconfig->mem_pages;
|
|
|
|
+ dev_dbg(ctx->dev, "Using pipe config: %d\n", i);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dev_err(ctx->dev, "Invalid pipe config: %d %d %d for pipe: %d\n",
|
|
|
|
+ params->ch, params->s_freq, params->s_fmt, pipe->ppl_id);
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -655,6 +757,10 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
|
|
struct skl_sst *ctx = skl->skl_sst;
|
|
struct skl_sst *ctx = skl->skl_sst;
|
|
struct skl_module_deferred_bind *modules;
|
|
struct skl_module_deferred_bind *modules;
|
|
|
|
|
|
|
|
+ ret = skl_tplg_get_pipe_config(skl, mconfig);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
/* check resource available */
|
|
/* check resource available */
|
|
if (!skl_is_pipe_mcps_avail(skl, mconfig))
|
|
if (!skl_is_pipe_mcps_avail(skl, mconfig))
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
@@ -758,12 +864,12 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
|
|
* check all out/in pins are in bind state.
|
|
* check all out/in pins are in bind state.
|
|
* if so set the module param
|
|
* if so set the module param
|
|
*/
|
|
*/
|
|
- for (i = 0; i < mcfg->max_out_queue; i++) {
|
|
|
|
|
|
+ for (i = 0; i < mcfg->module->max_output_pins; i++) {
|
|
if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE)
|
|
if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- for (i = 0; i < mcfg->max_in_queue; i++) {
|
|
|
|
|
|
+ for (i = 0; i < mcfg->module->max_input_pins; i++) {
|
|
if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE)
|
|
if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -814,7 +920,7 @@ static int skl_tplg_module_add_deferred_bind(struct skl *skl,
|
|
int i;
|
|
int i;
|
|
|
|
|
|
/* only supported for module with static pin connection */
|
|
/* only supported for module with static pin connection */
|
|
- for (i = 0; i < dst->max_in_queue; i++) {
|
|
|
|
|
|
+ for (i = 0; i < dst->module->max_input_pins; i++) {
|
|
struct skl_module_pin *pin = &dst->m_in_pin[i];
|
|
struct skl_module_pin *pin = &dst->m_in_pin[i];
|
|
|
|
|
|
if (pin->is_dynamic)
|
|
if (pin->is_dynamic)
|
|
@@ -925,7 +1031,7 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (!sink)
|
|
|
|
|
|
+ if (!sink && next_sink)
|
|
return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig);
|
|
return skl_tplg_bind_sinks(next_sink, skl, src_w, src_mconfig);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -1074,7 +1180,7 @@ static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w,
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- for (i = 0; i < sink_mconfig->max_in_queue; i++) {
|
|
|
|
|
|
+ for (i = 0; i < sink_mconfig->module->max_input_pins; i++) {
|
|
if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) {
|
|
if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) {
|
|
src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg;
|
|
src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg;
|
|
if (!src_mconfig)
|
|
if (!src_mconfig)
|
|
@@ -1185,7 +1291,7 @@ static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- for (i = 0; i < src_mconfig->max_out_queue; i++) {
|
|
|
|
|
|
+ for (i = 0; i < src_mconfig->module->max_output_pins; i++) {
|
|
if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) {
|
|
if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) {
|
|
sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg;
|
|
sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg;
|
|
if (!sink_mconfig)
|
|
if (!sink_mconfig)
|
|
@@ -1479,14 +1585,22 @@ int skl_tplg_update_pipe_params(struct device *dev,
|
|
struct skl_module_cfg *mconfig,
|
|
struct skl_module_cfg *mconfig,
|
|
struct skl_pipe_params *params)
|
|
struct skl_pipe_params *params)
|
|
{
|
|
{
|
|
|
|
+ struct skl_module_res *res = &mconfig->module->resources[0];
|
|
|
|
+ struct skl *skl = get_skl_ctx(dev);
|
|
struct skl_module_fmt *format = NULL;
|
|
struct skl_module_fmt *format = NULL;
|
|
|
|
+ u8 cfg_idx = mconfig->pipe->cur_config_idx;
|
|
|
|
|
|
skl_tplg_fill_dma_id(mconfig, params);
|
|
skl_tplg_fill_dma_id(mconfig, params);
|
|
|
|
+ mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx;
|
|
|
|
+ mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx;
|
|
|
|
+
|
|
|
|
+ if (skl->nr_modules)
|
|
|
|
+ return 0;
|
|
|
|
|
|
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
|
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
|
- format = &mconfig->in_fmt[0];
|
|
|
|
|
|
+ format = &mconfig->module->formats[0].inputs[0].fmt;
|
|
else
|
|
else
|
|
- format = &mconfig->out_fmt[0];
|
|
|
|
|
|
+ format = &mconfig->module->formats[0].outputs[0].fmt;
|
|
|
|
|
|
/* set the hw_params */
|
|
/* set the hw_params */
|
|
format->s_freq = params->s_freq;
|
|
format->s_freq = params->s_freq;
|
|
@@ -1514,11 +1628,11 @@ int skl_tplg_update_pipe_params(struct device *dev,
|
|
}
|
|
}
|
|
|
|
|
|
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
- mconfig->ibs = (format->s_freq / 1000) *
|
|
|
|
|
|
+ res->ibs = (format->s_freq / 1000) *
|
|
(format->channels) *
|
|
(format->channels) *
|
|
(format->bit_depth >> 3);
|
|
(format->bit_depth >> 3);
|
|
} else {
|
|
} else {
|
|
- mconfig->obs = (format->s_freq / 1000) *
|
|
|
|
|
|
+ res->obs = (format->s_freq / 1000) *
|
|
(format->channels) *
|
|
(format->channels) *
|
|
(format->bit_depth >> 3);
|
|
(format->bit_depth >> 3);
|
|
}
|
|
}
|
|
@@ -1792,6 +1906,54 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static int skl_tplg_fill_pipe_cfg(struct device *dev,
|
|
|
|
+ struct skl_pipe *pipe, u32 tkn,
|
|
|
|
+ u32 tkn_val, int conf_idx, int dir)
|
|
|
|
+{
|
|
|
|
+ struct skl_pipe_fmt *fmt;
|
|
|
|
+ struct skl_path_config *config;
|
|
|
|
+
|
|
|
|
+ switch (dir) {
|
|
|
|
+ case SKL_DIR_IN:
|
|
|
|
+ fmt = &pipe->configs[conf_idx].in_fmt;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_DIR_OUT:
|
|
|
|
+ fmt = &pipe->configs[conf_idx].out_fmt;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Invalid direction: %d\n", dir);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ config = &pipe->configs[conf_idx];
|
|
|
|
+
|
|
|
|
+ switch (tkn) {
|
|
|
|
+ case SKL_TKN_U32_CFG_FREQ:
|
|
|
|
+ fmt->freq = tkn_val;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U8_CFG_CHAN:
|
|
|
|
+ fmt->channels = tkn_val;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U8_CFG_BPS:
|
|
|
|
+ fmt->bps = tkn_val;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_PATH_MEM_PGS:
|
|
|
|
+ config->mem_pages = tkn_val;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Invalid token config: %d\n", tkn);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int skl_tplg_fill_pipe_tkn(struct device *dev,
|
|
static int skl_tplg_fill_pipe_tkn(struct device *dev,
|
|
struct skl_pipe *pipe, u32 tkn,
|
|
struct skl_pipe *pipe, u32 tkn,
|
|
u32 tkn_val)
|
|
u32 tkn_val)
|
|
@@ -1814,6 +1976,14 @@ static int skl_tplg_fill_pipe_tkn(struct device *dev,
|
|
pipe->lp_mode = tkn_val;
|
|
pipe->lp_mode = tkn_val;
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SKL_TKN_U32_PIPE_DIRECTION:
|
|
|
|
+ pipe->direction = tkn_val;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_NUM_CONFIGS:
|
|
|
|
+ pipe->nr_cfgs = tkn_val;
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
dev_err(dev, "Token not handled %d\n", tkn);
|
|
dev_err(dev, "Token not handled %d\n", tkn);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -1930,27 +2100,9 @@ static int skl_tplg_fill_pins_info(struct device *dev,
|
|
* on the direction
|
|
* on the direction
|
|
*/
|
|
*/
|
|
static int skl_tplg_fill_fmt(struct device *dev,
|
|
static int skl_tplg_fill_fmt(struct device *dev,
|
|
- struct skl_module_cfg *mconfig, u32 tkn,
|
|
|
|
- u32 value, u32 dir, u32 pin_count)
|
|
|
|
|
|
+ struct skl_module_fmt *dst_fmt,
|
|
|
|
+ u32 tkn, u32 value)
|
|
{
|
|
{
|
|
- struct skl_module_fmt *dst_fmt;
|
|
|
|
-
|
|
|
|
- switch (dir) {
|
|
|
|
- case SKL_DIR_IN:
|
|
|
|
- dst_fmt = mconfig->in_fmt;
|
|
|
|
- dst_fmt += pin_count;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case SKL_DIR_OUT:
|
|
|
|
- dst_fmt = mconfig->out_fmt;
|
|
|
|
- dst_fmt += pin_count;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- dev_err(dev, "Invalid direction value\n");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
switch (tkn) {
|
|
switch (tkn) {
|
|
case SKL_TKN_U32_FMT_CH:
|
|
case SKL_TKN_U32_FMT_CH:
|
|
dst_fmt->channels = value;
|
|
dst_fmt->channels = value;
|
|
@@ -1992,6 +2144,32 @@ static int skl_tplg_fill_fmt(struct device *dev,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int skl_tplg_widget_fill_fmt(struct device *dev,
|
|
|
|
+ struct skl_module_iface *fmt,
|
|
|
|
+ u32 tkn, u32 val, u32 dir, int fmt_idx)
|
|
|
|
+{
|
|
|
|
+ struct skl_module_fmt *dst_fmt;
|
|
|
|
+
|
|
|
|
+ if (!fmt)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ switch (dir) {
|
|
|
|
+ case SKL_DIR_IN:
|
|
|
|
+ dst_fmt = &fmt->inputs[fmt_idx].fmt;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_DIR_OUT:
|
|
|
|
+ dst_fmt = &fmt->outputs[fmt_idx].fmt;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Invalid direction: %d\n", dir);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return skl_tplg_fill_fmt(dev, dst_fmt, tkn, val);
|
|
|
|
+}
|
|
|
|
+
|
|
static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig,
|
|
static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig,
|
|
struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
|
|
struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
|
|
{
|
|
{
|
|
@@ -2014,6 +2192,108 @@ static void skl_tplg_fill_pin_dynamic_val(
|
|
mpin[i].is_dynamic = value;
|
|
mpin[i].is_dynamic = value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Resource table in the manifest has pin specific resources
|
|
|
|
+ * like pin and pin buffer size
|
|
|
|
+ */
|
|
|
|
+static int skl_tplg_manifest_pin_res_tkn(struct device *dev,
|
|
|
|
+ struct snd_soc_tplg_vendor_value_elem *tkn_elem,
|
|
|
|
+ struct skl_module_res *res, int pin_idx, int dir)
|
|
|
|
+{
|
|
|
|
+ struct skl_module_pin_resources *m_pin;
|
|
|
|
+
|
|
|
|
+ switch (dir) {
|
|
|
|
+ case SKL_DIR_IN:
|
|
|
|
+ m_pin = &res->input[pin_idx];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_DIR_OUT:
|
|
|
|
+ m_pin = &res->output[pin_idx];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Invalid pin direction: %d\n", dir);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch (tkn_elem->token) {
|
|
|
|
+ case SKL_TKN_MM_U32_RES_PIN_ID:
|
|
|
|
+ m_pin->pin_index = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_PIN_BUF:
|
|
|
|
+ m_pin->buf_size = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Invalid token: %d\n", tkn_elem->token);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Fill module specific resources from the manifest's resource
|
|
|
|
+ * table like CPS, DMA size, mem_pages.
|
|
|
|
+ */
|
|
|
|
+static int skl_tplg_fill_res_tkn(struct device *dev,
|
|
|
|
+ struct snd_soc_tplg_vendor_value_elem *tkn_elem,
|
|
|
|
+ struct skl_module_res *res,
|
|
|
|
+ int pin_idx, int dir)
|
|
|
|
+{
|
|
|
|
+ int ret, tkn_count = 0;
|
|
|
|
+
|
|
|
|
+ if (!res)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ switch (tkn_elem->token) {
|
|
|
|
+ case SKL_TKN_MM_U32_CPS:
|
|
|
|
+ res->cps = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_DMA_SIZE:
|
|
|
|
+ res->dma_buffer_size = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_CPC:
|
|
|
|
+ res->cpc = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_MEM_PAGES:
|
|
|
|
+ res->is_pages = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_OBS:
|
|
|
|
+ res->obs = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_IBS:
|
|
|
|
+ res->ibs = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_MAX_MCPS:
|
|
|
|
+ res->cps = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_RES_PIN_ID:
|
|
|
|
+ case SKL_TKN_MM_U32_PIN_BUF:
|
|
|
|
+ ret = skl_tplg_manifest_pin_res_tkn(dev, tkn_elem, res,
|
|
|
|
+ pin_idx, dir);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Not a res type token: %d", tkn_elem->token);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ tkn_count++;
|
|
|
|
+
|
|
|
|
+ return tkn_count;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Parse tokens to fill up the module private data
|
|
* Parse tokens to fill up the module private data
|
|
*/
|
|
*/
|
|
@@ -2024,49 +2304,54 @@ static int skl_tplg_get_token(struct device *dev,
|
|
int tkn_count = 0;
|
|
int tkn_count = 0;
|
|
int ret;
|
|
int ret;
|
|
static int is_pipe_exists;
|
|
static int is_pipe_exists;
|
|
- static int pin_index, dir;
|
|
|
|
|
|
+ static int pin_index, dir, conf_idx;
|
|
|
|
+ struct skl_module_iface *iface = NULL;
|
|
|
|
+ struct skl_module_res *res = NULL;
|
|
|
|
+ int res_idx = mconfig->res_idx;
|
|
|
|
+ int fmt_idx = mconfig->fmt_idx;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If the manifest structure contains no modules, fill all
|
|
|
|
+ * the module data to 0th index.
|
|
|
|
+ * res_idx and fmt_idx are default set to 0.
|
|
|
|
+ */
|
|
|
|
+ if (skl->nr_modules == 0) {
|
|
|
|
+ res = &mconfig->module->resources[res_idx];
|
|
|
|
+ iface = &mconfig->module->formats[fmt_idx];
|
|
|
|
+ }
|
|
|
|
|
|
if (tkn_elem->token > SKL_TKN_MAX)
|
|
if (tkn_elem->token > SKL_TKN_MAX)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
switch (tkn_elem->token) {
|
|
switch (tkn_elem->token) {
|
|
case SKL_TKN_U8_IN_QUEUE_COUNT:
|
|
case SKL_TKN_U8_IN_QUEUE_COUNT:
|
|
- mconfig->max_in_queue = tkn_elem->value;
|
|
|
|
- mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue *
|
|
|
|
- sizeof(*mconfig->m_in_pin),
|
|
|
|
- GFP_KERNEL);
|
|
|
|
- if (!mconfig->m_in_pin)
|
|
|
|
- return -ENOMEM;
|
|
|
|
-
|
|
|
|
|
|
+ mconfig->module->max_input_pins = tkn_elem->value;
|
|
break;
|
|
break;
|
|
|
|
|
|
case SKL_TKN_U8_OUT_QUEUE_COUNT:
|
|
case SKL_TKN_U8_OUT_QUEUE_COUNT:
|
|
- mconfig->max_out_queue = tkn_elem->value;
|
|
|
|
- mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue *
|
|
|
|
- sizeof(*mconfig->m_out_pin),
|
|
|
|
- GFP_KERNEL);
|
|
|
|
-
|
|
|
|
- if (!mconfig->m_out_pin)
|
|
|
|
- return -ENOMEM;
|
|
|
|
-
|
|
|
|
|
|
+ mconfig->module->max_output_pins = tkn_elem->value;
|
|
break;
|
|
break;
|
|
|
|
|
|
case SKL_TKN_U8_DYN_IN_PIN:
|
|
case SKL_TKN_U8_DYN_IN_PIN:
|
|
|
|
+ if (!mconfig->m_in_pin)
|
|
|
|
+ mconfig->m_in_pin = devm_kzalloc(dev, MAX_IN_QUEUE *
|
|
|
|
+ sizeof(*mconfig->m_in_pin), GFP_KERNEL);
|
|
if (!mconfig->m_in_pin)
|
|
if (!mconfig->m_in_pin)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
- skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin,
|
|
|
|
- mconfig->max_in_queue, tkn_elem->value);
|
|
|
|
-
|
|
|
|
|
|
+ skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, MAX_IN_QUEUE,
|
|
|
|
+ tkn_elem->value);
|
|
break;
|
|
break;
|
|
|
|
|
|
case SKL_TKN_U8_DYN_OUT_PIN:
|
|
case SKL_TKN_U8_DYN_OUT_PIN:
|
|
|
|
+ if (!mconfig->m_out_pin)
|
|
|
|
+ mconfig->m_out_pin = devm_kzalloc(dev, MAX_IN_QUEUE *
|
|
|
|
+ sizeof(*mconfig->m_in_pin), GFP_KERNEL);
|
|
if (!mconfig->m_out_pin)
|
|
if (!mconfig->m_out_pin)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
- skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin,
|
|
|
|
- mconfig->max_out_queue, tkn_elem->value);
|
|
|
|
-
|
|
|
|
|
|
+ skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, MAX_OUT_QUEUE,
|
|
|
|
+ tkn_elem->value);
|
|
break;
|
|
break;
|
|
|
|
|
|
case SKL_TKN_U8_TIME_SLOT:
|
|
case SKL_TKN_U8_TIME_SLOT:
|
|
@@ -2094,19 +2379,13 @@ static int skl_tplg_get_token(struct device *dev,
|
|
break;
|
|
break;
|
|
|
|
|
|
case SKL_TKN_U32_MEM_PAGES:
|
|
case SKL_TKN_U32_MEM_PAGES:
|
|
- mconfig->mem_pages = tkn_elem->value;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
case SKL_TKN_U32_MAX_MCPS:
|
|
case SKL_TKN_U32_MAX_MCPS:
|
|
- mconfig->mcps = tkn_elem->value;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
case SKL_TKN_U32_OBS:
|
|
case SKL_TKN_U32_OBS:
|
|
- mconfig->obs = tkn_elem->value;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
case SKL_TKN_U32_IBS:
|
|
case SKL_TKN_U32_IBS:
|
|
- mconfig->ibs = tkn_elem->value;
|
|
|
|
|
|
+ ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, dir, pin_index);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
break;
|
|
break;
|
|
|
|
|
|
case SKL_TKN_U32_VBUS_ID:
|
|
case SKL_TKN_U32_VBUS_ID:
|
|
@@ -2139,10 +2418,16 @@ static int skl_tplg_get_token(struct device *dev,
|
|
|
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SKL_TKN_U32_PIPE_CONFIG_ID:
|
|
|
|
+ conf_idx = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
case SKL_TKN_U32_PIPE_CONN_TYPE:
|
|
case SKL_TKN_U32_PIPE_CONN_TYPE:
|
|
case SKL_TKN_U32_PIPE_PRIORITY:
|
|
case SKL_TKN_U32_PIPE_PRIORITY:
|
|
case SKL_TKN_U32_PIPE_MEM_PGS:
|
|
case SKL_TKN_U32_PIPE_MEM_PGS:
|
|
case SKL_TKN_U32_PMODE:
|
|
case SKL_TKN_U32_PMODE:
|
|
|
|
+ case SKL_TKN_U32_PIPE_DIRECTION:
|
|
|
|
+ case SKL_TKN_U32_NUM_CONFIGS:
|
|
if (is_pipe_exists) {
|
|
if (is_pipe_exists) {
|
|
ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe,
|
|
ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe,
|
|
tkn_elem->token, tkn_elem->value);
|
|
tkn_elem->token, tkn_elem->value);
|
|
@@ -2152,6 +2437,27 @@ static int skl_tplg_get_token(struct device *dev,
|
|
|
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SKL_TKN_U32_PATH_MEM_PGS:
|
|
|
|
+ case SKL_TKN_U32_CFG_FREQ:
|
|
|
|
+ case SKL_TKN_U8_CFG_CHAN:
|
|
|
|
+ case SKL_TKN_U8_CFG_BPS:
|
|
|
|
+ if (mconfig->pipe->nr_cfgs) {
|
|
|
|
+ ret = skl_tplg_fill_pipe_cfg(dev, mconfig->pipe,
|
|
|
|
+ tkn_elem->token, tkn_elem->value,
|
|
|
|
+ conf_idx, dir);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_CFG_MOD_RES_ID:
|
|
|
|
+ mconfig->mod_cfg[conf_idx].res_idx = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_CFG_MOD_FMT_ID:
|
|
|
|
+ mconfig->mod_cfg[conf_idx].fmt_idx = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* SKL_TKN_U32_DIR_PIN_COUNT token has the value for both
|
|
* SKL_TKN_U32_DIR_PIN_COUNT token has the value for both
|
|
* direction and the pin count. The first four bits represent
|
|
* direction and the pin count. The first four bits represent
|
|
@@ -2172,7 +2478,7 @@ static int skl_tplg_get_token(struct device *dev,
|
|
case SKL_TKN_U32_FMT_INTERLEAVE:
|
|
case SKL_TKN_U32_FMT_INTERLEAVE:
|
|
case SKL_TKN_U32_FMT_SAMPLE_TYPE:
|
|
case SKL_TKN_U32_FMT_SAMPLE_TYPE:
|
|
case SKL_TKN_U32_FMT_CH_MAP:
|
|
case SKL_TKN_U32_FMT_CH_MAP:
|
|
- ret = skl_tplg_fill_fmt(dev, mconfig, tkn_elem->token,
|
|
|
|
|
|
+ ret = skl_tplg_widget_fill_fmt(dev, iface, tkn_elem->token,
|
|
tkn_elem->value, dir, pin_index);
|
|
tkn_elem->value, dir, pin_index);
|
|
|
|
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
@@ -2397,11 +2703,11 @@ static void skl_clear_pin_config(struct snd_soc_platform *platform,
|
|
strlen(platform->component.name))) {
|
|
strlen(platform->component.name))) {
|
|
mconfig = w->priv;
|
|
mconfig = w->priv;
|
|
pipe = mconfig->pipe;
|
|
pipe = mconfig->pipe;
|
|
- for (i = 0; i < mconfig->max_in_queue; i++) {
|
|
|
|
|
|
+ for (i = 0; i < mconfig->module->max_input_pins; i++) {
|
|
mconfig->m_in_pin[i].in_use = false;
|
|
mconfig->m_in_pin[i].in_use = false;
|
|
mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND;
|
|
mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND;
|
|
}
|
|
}
|
|
- for (i = 0; i < mconfig->max_out_queue; i++) {
|
|
|
|
|
|
+ for (i = 0; i < mconfig->module->max_output_pins; i++) {
|
|
mconfig->m_out_pin[i].in_use = false;
|
|
mconfig->m_out_pin[i].in_use = false;
|
|
mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND;
|
|
mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND;
|
|
}
|
|
}
|
|
@@ -2460,6 +2766,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
|
|
if (!mconfig)
|
|
if (!mconfig)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
+ if (skl->nr_modules == 0) {
|
|
|
|
+ mconfig->module = devm_kzalloc(bus->dev,
|
|
|
|
+ sizeof(*mconfig->module), GFP_KERNEL);
|
|
|
|
+ if (!mconfig->module)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+
|
|
w->priv = mconfig;
|
|
w->priv = mconfig;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2602,13 +2915,13 @@ static int skl_tplg_fill_str_mfest_tkn(struct device *dev,
|
|
str_elem->string,
|
|
str_elem->string,
|
|
ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name));
|
|
ARRAY_SIZE(skl->skl_sst->lib_info[ref_count].name));
|
|
ref_count++;
|
|
ref_count++;
|
|
- tkn_count++;
|
|
|
|
break;
|
|
break;
|
|
|
|
|
|
default:
|
|
default:
|
|
dev_err(dev, "Not a string token %d\n", str_elem->token);
|
|
dev_err(dev, "Not a string token %d\n", str_elem->token);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ tkn_count++;
|
|
|
|
|
|
return tkn_count;
|
|
return tkn_count;
|
|
}
|
|
}
|
|
@@ -2634,26 +2947,236 @@ static int skl_tplg_get_str_tkn(struct device *dev,
|
|
return tkn_count;
|
|
return tkn_count;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int skl_tplg_manifest_fill_fmt(struct device *dev,
|
|
|
|
+ struct skl_module_iface *fmt,
|
|
|
|
+ struct snd_soc_tplg_vendor_value_elem *tkn_elem,
|
|
|
|
+ u32 dir, int fmt_idx)
|
|
|
|
+{
|
|
|
|
+ struct skl_module_pin_fmt *dst_fmt;
|
|
|
|
+ struct skl_module_fmt *mod_fmt;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (!fmt)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ switch (dir) {
|
|
|
|
+ case SKL_DIR_IN:
|
|
|
|
+ dst_fmt = &fmt->inputs[fmt_idx];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_DIR_OUT:
|
|
|
|
+ dst_fmt = &fmt->outputs[fmt_idx];
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Invalid direction: %d\n", dir);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ mod_fmt = &dst_fmt->fmt;
|
|
|
|
+
|
|
|
|
+ switch (tkn_elem->token) {
|
|
|
|
+ case SKL_TKN_MM_U32_INTF_PIN_ID:
|
|
|
|
+ dst_fmt->id = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ ret = skl_tplg_fill_fmt(dev, mod_fmt, tkn_elem->token,
|
|
|
|
+ tkn_elem->value);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int skl_tplg_fill_mod_info(struct device *dev,
|
|
|
|
+ struct snd_soc_tplg_vendor_value_elem *tkn_elem,
|
|
|
|
+ struct skl_module *mod)
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+ if (!mod)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ switch (tkn_elem->token) {
|
|
|
|
+ case SKL_TKN_U8_IN_PIN_TYPE:
|
|
|
|
+ mod->input_pin_type = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U8_OUT_PIN_TYPE:
|
|
|
|
+ mod->output_pin_type = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U8_IN_QUEUE_COUNT:
|
|
|
|
+ mod->max_input_pins = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U8_OUT_QUEUE_COUNT:
|
|
|
|
+ mod->max_output_pins = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U8_NUM_RES:
|
|
|
|
+ mod->nr_resources = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U8_NUM_INTF:
|
|
|
|
+ mod->nr_interfaces = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ dev_err(dev, "Invalid mod info token %d", tkn_elem->token);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static int skl_tplg_get_int_tkn(struct device *dev,
|
|
static int skl_tplg_get_int_tkn(struct device *dev,
|
|
struct snd_soc_tplg_vendor_value_elem *tkn_elem,
|
|
struct snd_soc_tplg_vendor_value_elem *tkn_elem,
|
|
struct skl *skl)
|
|
struct skl *skl)
|
|
{
|
|
{
|
|
- int tkn_count = 0;
|
|
|
|
|
|
+ int tkn_count = 0, ret;
|
|
|
|
+ static int mod_idx, res_val_idx, intf_val_idx, dir, pin_idx;
|
|
|
|
+ struct skl_module_res *res = NULL;
|
|
|
|
+ struct skl_module_iface *fmt = NULL;
|
|
|
|
+ struct skl_module *mod = NULL;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (skl->modules) {
|
|
|
|
+ mod = skl->modules[mod_idx];
|
|
|
|
+ res = &mod->resources[res_val_idx];
|
|
|
|
+ fmt = &mod->formats[intf_val_idx];
|
|
|
|
+ }
|
|
|
|
|
|
switch (tkn_elem->token) {
|
|
switch (tkn_elem->token) {
|
|
case SKL_TKN_U32_LIB_COUNT:
|
|
case SKL_TKN_U32_LIB_COUNT:
|
|
skl->skl_sst->lib_count = tkn_elem->value;
|
|
skl->skl_sst->lib_count = tkn_elem->value;
|
|
- tkn_count++;
|
|
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U8_NUM_MOD:
|
|
|
|
+ skl->nr_modules = tkn_elem->value;
|
|
|
|
+ skl->modules = devm_kcalloc(dev, skl->nr_modules,
|
|
|
|
+ sizeof(*skl->modules), GFP_KERNEL);
|
|
|
|
+ if (!skl->modules)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < skl->nr_modules; i++) {
|
|
|
|
+ skl->modules[i] = devm_kzalloc(dev,
|
|
|
|
+ sizeof(struct skl_module), GFP_KERNEL);
|
|
|
|
+ if (!skl->modules[i])
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U8_MOD_IDX:
|
|
|
|
+ mod_idx = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U8_IN_PIN_TYPE:
|
|
|
|
+ case SKL_TKN_U8_OUT_PIN_TYPE:
|
|
|
|
+ case SKL_TKN_U8_IN_QUEUE_COUNT:
|
|
|
|
+ case SKL_TKN_U8_OUT_QUEUE_COUNT:
|
|
|
|
+ case SKL_TKN_MM_U8_NUM_RES:
|
|
|
|
+ case SKL_TKN_MM_U8_NUM_INTF:
|
|
|
|
+ ret = skl_tplg_fill_mod_info(dev, tkn_elem, mod);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_DIR_PIN_COUNT:
|
|
|
|
+ dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK;
|
|
|
|
+ pin_idx = (tkn_elem->value & SKL_PIN_COUNT_MASK) >> 4;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_RES_ID:
|
|
|
|
+ if (!res)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ res->id = tkn_elem->value;
|
|
|
|
+ res_val_idx = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_FMT_ID:
|
|
|
|
+ if (!fmt)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ fmt->fmt_idx = tkn_elem->value;
|
|
|
|
+ intf_val_idx = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_CPS:
|
|
|
|
+ case SKL_TKN_MM_U32_DMA_SIZE:
|
|
|
|
+ case SKL_TKN_MM_U32_CPC:
|
|
|
|
+ case SKL_TKN_U32_MEM_PAGES:
|
|
|
|
+ case SKL_TKN_U32_OBS:
|
|
|
|
+ case SKL_TKN_U32_IBS:
|
|
|
|
+ case SKL_TKN_MM_U32_RES_PIN_ID:
|
|
|
|
+ case SKL_TKN_MM_U32_PIN_BUF:
|
|
|
|
+ ret = skl_tplg_fill_res_tkn(dev, tkn_elem, res, pin_idx, dir);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_NUM_IN_FMT:
|
|
|
|
+ if (!fmt)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ res->nr_input_pins = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_MM_U32_NUM_OUT_FMT:
|
|
|
|
+ if (!fmt)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ res->nr_output_pins = tkn_elem->value;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SKL_TKN_U32_FMT_CH:
|
|
|
|
+ case SKL_TKN_U32_FMT_FREQ:
|
|
|
|
+ case SKL_TKN_U32_FMT_BIT_DEPTH:
|
|
|
|
+ case SKL_TKN_U32_FMT_SAMPLE_SIZE:
|
|
|
|
+ case SKL_TKN_U32_FMT_CH_CONFIG:
|
|
|
|
+ case SKL_TKN_U32_FMT_INTERLEAVE:
|
|
|
|
+ case SKL_TKN_U32_FMT_SAMPLE_TYPE:
|
|
|
|
+ case SKL_TKN_U32_FMT_CH_MAP:
|
|
|
|
+ case SKL_TKN_MM_U32_INTF_PIN_ID:
|
|
|
|
+ ret = skl_tplg_manifest_fill_fmt(dev, fmt, tkn_elem,
|
|
|
|
+ dir, pin_idx);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
break;
|
|
break;
|
|
|
|
|
|
default:
|
|
default:
|
|
dev_err(dev, "Not a manifest token %d\n", tkn_elem->token);
|
|
dev_err(dev, "Not a manifest token %d\n", tkn_elem->token);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
+ tkn_count++;
|
|
|
|
|
|
return tkn_count;
|
|
return tkn_count;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int skl_tplg_get_manifest_uuid(struct device *dev,
|
|
|
|
+ struct skl *skl,
|
|
|
|
+ struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
|
|
|
|
+{
|
|
|
|
+ static int ref_count;
|
|
|
|
+ struct skl_module *mod;
|
|
|
|
+
|
|
|
|
+ if (uuid_tkn->token == SKL_TKN_UUID) {
|
|
|
|
+ mod = skl->modules[ref_count];
|
|
|
|
+ memcpy(&mod->uuid, &uuid_tkn->uuid, sizeof(uuid_tkn->uuid));
|
|
|
|
+ ref_count++;
|
|
|
|
+ } else {
|
|
|
|
+ dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token);
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Fill the manifest structure by parsing the tokens based on the
|
|
* Fill the manifest structure by parsing the tokens based on the
|
|
* type.
|
|
* type.
|
|
@@ -2686,7 +3209,11 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
|
|
continue;
|
|
continue;
|
|
|
|
|
|
case SND_SOC_TPLG_TUPLE_TYPE_UUID:
|
|
case SND_SOC_TPLG_TUPLE_TYPE_UUID:
|
|
- dev_warn(dev, "no uuid tokens for skl tplf manifest\n");
|
|
|
|
|
|
+ ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ tuple_size += sizeof(*array->uuid);
|
|
continue;
|
|
continue;
|
|
|
|
|
|
default:
|
|
default:
|
|
@@ -2703,14 +3230,12 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
|
|
|
|
|
|
tkn_count = tkn_count + ret;
|
|
tkn_count = tkn_count + ret;
|
|
tkn_elem++;
|
|
tkn_elem++;
|
|
- tuple_size += tkn_count *
|
|
|
|
- sizeof(struct snd_soc_tplg_vendor_value_elem);
|
|
|
|
- break;
|
|
|
|
}
|
|
}
|
|
|
|
+ tuple_size += (tkn_count * sizeof(*tkn_elem));
|
|
tkn_count = 0;
|
|
tkn_count = 0;
|
|
}
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return off;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2733,11 +3258,10 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
|
|
num_blocks = ret;
|
|
num_blocks = ret;
|
|
|
|
|
|
off += array->size;
|
|
off += array->size;
|
|
- array = (struct snd_soc_tplg_vendor_array *)
|
|
|
|
- (manifest->priv.data + off);
|
|
|
|
-
|
|
|
|
/* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
|
|
/* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
|
|
while (num_blocks > 0) {
|
|
while (num_blocks > 0) {
|
|
|
|
+ array = (struct snd_soc_tplg_vendor_array *)
|
|
|
|
+ (manifest->priv.data + off);
|
|
ret = skl_tplg_get_desc_blocks(dev, array);
|
|
ret = skl_tplg_get_desc_blocks(dev, array);
|
|
|
|
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
@@ -2771,6 +3295,7 @@ static int skl_tplg_get_manifest_data(struct snd_soc_tplg_manifest *manifest,
|
|
} else {
|
|
} else {
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
+ off += ret;
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|