#include "skl-topology.h"
#include "skl.h"
#include "skl-tplg-interface.h"
+++ #include "../common/sst-dsp.h"
+++ #include "../common/sst-dsp-priv.h"
#define SKL_CH_FIXUP_MASK (1 << 0)
#define SKL_RATE_FIXUP_MASK (1 << 1)
{
dev_dbg(ctx->dev, "Dumping config\n");
dev_dbg(ctx->dev, "Input Format:\n");
--- dev_dbg(ctx->dev, "channels = %d\n", mcfg->in_fmt.channels);
--- dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->in_fmt.s_freq);
--- dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->in_fmt.ch_cfg);
--- dev_dbg(ctx->dev, "valid bit depth = %d\n",
--- mcfg->in_fmt.valid_bit_depth);
+++ 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, "Output Format:\n");
--- dev_dbg(ctx->dev, "channels = %d\n", mcfg->out_fmt.channels);
--- dev_dbg(ctx->dev, "s_freq = %d\n", mcfg->out_fmt.s_freq);
--- dev_dbg(ctx->dev, "valid bit depth = %d\n",
--- mcfg->out_fmt.valid_bit_depth);
--- dev_dbg(ctx->dev, "ch_cfg = %d\n", mcfg->out_fmt.ch_cfg);
+++ 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);
}
static void skl_tplg_update_params(struct skl_module_fmt *fmt,
fmt->s_freq = params->s_freq;
if (fixup & SKL_CH_FIXUP_MASK)
fmt->channels = params->ch;
--- if (fixup & SKL_FMT_FIXUP_MASK)
--- fmt->valid_bit_depth = params->s_fmt;
+++ if (fixup & SKL_FMT_FIXUP_MASK) {
+++ fmt->valid_bit_depth = skl_get_bit_depth(params->s_fmt);
+++
+++ /*
+++ * 16 bit is 16 bit container whereas 24 bit is in 32 bit
+++ * container so update bit depth accordingly
+++ */
+++ switch (fmt->valid_bit_depth) {
+++ case SKL_DEPTH_16BIT:
+++ fmt->bit_depth = fmt->valid_bit_depth;
+++ break;
+++
+++ default:
+++ fmt->bit_depth = SKL_DEPTH_32BIT;
+++ break;
+++ }
+++ }
+++
}
/*
int in_fixup, out_fixup;
struct skl_module_fmt *in_fmt, *out_fmt;
--- in_fmt = &m_cfg->in_fmt;
--- out_fmt = &m_cfg->out_fmt;
+++ /* Fixups will be applied to pin 0 only */
+++ in_fmt = &m_cfg->in_fmt[0];
+++ out_fmt = &m_cfg->out_fmt[0];
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (is_fe) {
struct skl_module_cfg *mcfg)
{
int multiplier = 1;
+++ struct skl_module_fmt *in_fmt, *out_fmt;
+++
+++
+++ /* Since fixups is applied to pin 0 only, ibs, obs needs
+++ * change for pin 0 only
+++ */
+++ in_fmt = &mcfg->in_fmt[0];
+++ out_fmt = &mcfg->out_fmt[0];
if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT)
multiplier = 5;
---
--- mcfg->ibs = (mcfg->in_fmt.s_freq / 1000) *
--- (mcfg->in_fmt.channels) *
--- (mcfg->in_fmt.bit_depth >> 3) *
+++ mcfg->ibs = (in_fmt->s_freq / 1000) *
+++ (mcfg->in_fmt->channels) *
+++ (mcfg->in_fmt->bit_depth >> 3) *
multiplier;
--- mcfg->obs = (mcfg->out_fmt.s_freq / 1000) *
--- (mcfg->out_fmt.channels) *
--- (mcfg->out_fmt.bit_depth >> 3) *
+++ mcfg->obs = (mcfg->out_fmt->s_freq / 1000) *
+++ (mcfg->out_fmt->channels) *
+++ (mcfg->out_fmt->bit_depth >> 3) *
multiplier;
}
return 0;
}
+++ /*
+++ * some modules can have multiple params set from user control and
+++ * need to be set after module is initialized. If set_param flag is
+++ * set module params will be done after module is initialised.
+++ */
+++ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w,
+++ struct skl_sst *ctx)
+++ {
+++ int i, ret;
+++ struct skl_module_cfg *mconfig = w->priv;
+++ const struct snd_kcontrol_new *k;
+++ struct soc_bytes_ext *sb;
+++ struct skl_algo_data *bc;
+++ struct skl_specific_cfg *sp_cfg;
+++
+++ if (mconfig->formats_config.caps_size > 0 &&
+++ mconfig->formats_config.set_params == SKL_PARAM_SET) {
+++ sp_cfg = &mconfig->formats_config;
+++ ret = skl_set_module_params(ctx, sp_cfg->caps,
+++ sp_cfg->caps_size,
+++ sp_cfg->param_id, mconfig);
+++ if (ret < 0)
+++ return ret;
+++ }
+++
+++ for (i = 0; i < w->num_kcontrols; i++) {
+++ k = &w->kcontrol_news[i];
+++ if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+++ sb = (void *) k->private_value;
+++ bc = (struct skl_algo_data *)sb->dobj.private;
+++
+++ if (bc->set_params == SKL_PARAM_SET) {
+++ ret = skl_set_module_params(ctx,
+++ (u32 *)bc->params, bc->max,
+++ bc->param_id, mconfig);
+++ if (ret < 0)
+++ return ret;
+++ }
+++ }
+++ }
+++
+++ return 0;
+++ }
+++
+++ /*
+++ * some module param can set from user control and this is required as
+++ * when module is initailzed. if module param is required in init it is
+++ * identifed by set_param flag. if set_param flag is not set, then this
+++ * parameter needs to set as part of module init.
+++ */
+++ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w)
+++ {
+++ const struct snd_kcontrol_new *k;
+++ struct soc_bytes_ext *sb;
+++ struct skl_algo_data *bc;
+++ struct skl_module_cfg *mconfig = w->priv;
+++ int i;
+++
+++ for (i = 0; i < w->num_kcontrols; i++) {
+++ k = &w->kcontrol_news[i];
+++ if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+++ sb = (struct soc_bytes_ext *)k->private_value;
+++ bc = (struct skl_algo_data *)sb->dobj.private;
+++
+++ if (bc->set_params != SKL_PARAM_INIT)
+++ continue;
+++
+++ mconfig->formats_config.caps = (u32 *)&bc->params;
+++ mconfig->formats_config.caps_size = bc->max;
+++
+++ break;
+++ }
+++ }
+++
+++ return 0;
+++ }
+++
/*
* Inside a pipe instance, we can have various modules. These modules need
* to instantiated in DSP by invoking INIT_MODULE IPC, which is achieved by
if (!skl_tplg_alloc_pipe_mcps(skl, mconfig))
return -ENOMEM;
+++ if (mconfig->is_loadable && ctx->dsp->fw_ops.load_mod) {
+++ ret = ctx->dsp->fw_ops.load_mod(ctx->dsp,
+++ mconfig->id.module_id, mconfig->guid);
+++ if (ret < 0)
+++ return ret;
+++ }
+++
/*
* apply fix/conversion to module params based on
* FE/BE params
*/
skl_tplg_update_module_params(w, ctx);
--- ret = skl_init_module(ctx, mconfig, NULL);
+++
+++ skl_tplg_set_module_init_data(w);
+++ ret = skl_init_module(ctx, mconfig);
+++ if (ret < 0)
+++ return ret;
+++
+++ ret = skl_tplg_set_module_params(w, ctx);
if (ret < 0)
return ret;
}
return 0;
}
+++ static int skl_tplg_unload_pipe_modules(struct skl_sst *ctx,
+++ struct skl_pipe *pipe)
+++ {
+++ struct skl_pipe_module *w_module = NULL;
+++ struct skl_module_cfg *mconfig = NULL;
+++
+++ list_for_each_entry(w_module, &pipe->w_list, node) {
+++ mconfig = w_module->w->priv;
+++
+++ if (mconfig->is_loadable && ctx->dsp->fw_ops.unload_mod)
+++ return ctx->dsp->fw_ops.unload_mod(ctx->dsp,
+++ mconfig->id.module_id);
+++ }
+++
+++ /* no modules to unload in this path, so return */
+++ return 0;
+++ }
+++
/*
* Mixer module represents a pipeline. So in the Pre-PMU event of mixer we
* need create the pipeline. So we do following:
return 0;
}
--- /*
--- * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
--- * we need to do following:
--- * - Bind to sink pipeline
--- * Since the sink pipes can be running and we don't get mixer event on
--- * connect for already running mixer, we need to find the sink pipes
--- * here and bind to them. This way dynamic connect works.
--- * - Start sink pipeline, if not running
--- * - Then run current pipe
--- */
--- static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
--- struct skl *skl)
+++ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
+++ struct skl *skl,
+++ struct skl_module_cfg *src_mconfig)
{
struct snd_soc_dapm_path *p;
--- struct skl_dapm_path_list *path_list;
--- struct snd_soc_dapm_widget *source, *sink;
--- struct skl_module_cfg *src_mconfig, *sink_mconfig;
+++ struct snd_soc_dapm_widget *sink = NULL, *next_sink = NULL;
+++ struct skl_module_cfg *sink_mconfig;
struct skl_sst *ctx = skl->skl_sst;
--- int ret = 0;
---
--- source = w;
--- src_mconfig = source->priv;
+++ int ret;
--- /*
--- * find which sink it is connected to, bind with the sink,
--- * if sink is not started, start sink pipe first, then start
--- * this pipe
--- */
--- snd_soc_dapm_widget_for_each_source_path(w, p) {
+++ snd_soc_dapm_widget_for_each_sink_path(w, p) {
if (!p->connect)
continue;
dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name);
dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name);
+++ next_sink = p->sink;
/*
* here we will check widgets in sink pipelines, so that
* can be any widgets type and we are only interested if
is_skl_dsp_widget_type(p->sink)) {
sink = p->sink;
--- src_mconfig = source->priv;
sink_mconfig = sink->priv;
/* Bind source to sink, mixin is always source */
/* Start sinks pipe first */
if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) {
--- ret = skl_run_pipe(ctx, sink_mconfig->pipe);
+++ if (sink_mconfig->pipe->conn_type !=
+++ SKL_PIPE_CONN_TYPE_FE)
+++ ret = skl_run_pipe(ctx,
+++ sink_mconfig->pipe);
if (ret)
return ret;
}
---
--- path_list = kzalloc(
--- sizeof(struct skl_dapm_path_list),
--- GFP_KERNEL);
--- if (path_list == NULL)
--- return -ENOMEM;
---
--- /* Add connected path to one global list */
--- path_list->dapm_path = p;
--- list_add_tail(&path_list->node, &skl->dapm_path_list);
--- break;
}
}
--- /* Start source pipe last after starting all sinks */
--- ret = skl_run_pipe(ctx, src_mconfig->pipe);
+++ if (!sink)
+++ return skl_tplg_bind_sinks(next_sink, skl, src_mconfig);
+++
+++ return 0;
+++ }
+++
+++ /*
+++ * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
+++ * we need to do following:
+++ * - Bind to sink pipeline
+++ * Since the sink pipes can be running and we don't get mixer event on
+++ * connect for already running mixer, we need to find the sink pipes
+++ * here and bind to them. This way dynamic connect works.
+++ * - Start sink pipeline, if not running
+++ * - Then run current pipe
+++ */
+++ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
+++ struct skl *skl)
+++ {
+++ struct skl_module_cfg *src_mconfig;
+++ struct skl_sst *ctx = skl->skl_sst;
+++ int ret = 0;
+++
+++ src_mconfig = w->priv;
+++
+++ /*
+++ * find which sink it is connected to, bind with the sink,
+++ * if sink is not started, start sink pipe first, then start
+++ * this pipe
+++ */
+++ ret = skl_tplg_bind_sinks(w, skl, src_mconfig);
if (ret)
return ret;
+++ /* Start source pipe last after starting all sinks */
+++ if (src_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+++ return skl_run_pipe(ctx, src_mconfig->pipe);
+++
return 0;
}
+++ static struct snd_soc_dapm_widget *skl_get_src_dsp_widget(
+++ struct snd_soc_dapm_widget *w, struct skl *skl)
+++ {
+++ struct snd_soc_dapm_path *p;
+++ struct snd_soc_dapm_widget *src_w = NULL;
+++ struct skl_sst *ctx = skl->skl_sst;
+++
+++ snd_soc_dapm_widget_for_each_source_path(w, p) {
+++ src_w = p->source;
+++ if (!p->connect)
+++ continue;
+++
+++ dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
+++ dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+++
+++ /*
+++ * here we will check widgets in sink pipelines, so that can
+++ * be any widgets type and we are only interested if they are
+++ * ones used for SKL so check that first
+++ */
+++ if ((p->source->priv != NULL) &&
+++ is_skl_dsp_widget_type(p->source)) {
+++ return p->source;
+++ }
+++ }
+++
+++ if (src_w != NULL)
+++ return skl_get_src_dsp_widget(src_w, skl);
+++
+++ return NULL;
+++ }
+++
/*
* in the Post-PMU event of mixer we need to do following:
* - Check if this pipe is running
struct skl *skl)
{
int ret = 0;
--- struct snd_soc_dapm_path *p;
struct snd_soc_dapm_widget *source, *sink;
struct skl_module_cfg *src_mconfig, *sink_mconfig;
struct skl_sst *ctx = skl->skl_sst;
* one more sink before this sink got connected, Since source is
* started, bind this sink to source and start this pipe.
*/
--- snd_soc_dapm_widget_for_each_sink_path(w, p) {
--- if (!p->connect)
--- continue;
---
--- dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
--- dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+++ source = skl_get_src_dsp_widget(w, skl);
+++ if (source != NULL) {
+++ src_mconfig = source->priv;
+++ sink_mconfig = sink->priv;
+++ src_pipe_started = 1;
/*
--- * here we will check widgets in sink pipelines, so that
--- * can be any widgets type and we are only interested if
--- * they are ones used for SKL so check that first
+++ * check pipe state, then no need to bind or start the
+++ * pipe
*/
--- if ((p->source->priv != NULL) &&
--- is_skl_dsp_widget_type(p->source)) {
--- source = p->source;
--- src_mconfig = source->priv;
--- sink_mconfig = sink->priv;
--- src_pipe_started = 1;
---
--- /*
--- * check pipe state, then no need to bind or start
--- * the pipe
--- */
--- if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
--- src_pipe_started = 0;
--- }
+++ if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
+++ src_pipe_started = 0;
}
if (src_pipe_started) {
if (ret)
return ret;
--- ret = skl_run_pipe(ctx, sink_mconfig->pipe);
+++ if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
+++ ret = skl_run_pipe(ctx, sink_mconfig->pipe);
}
return ret;
static int skl_tplg_mixer_dapm_pre_pmd_event(struct snd_soc_dapm_widget *w,
struct skl *skl)
{
--- struct snd_soc_dapm_widget *source, *sink;
struct skl_module_cfg *src_mconfig, *sink_mconfig;
--- int ret = 0, path_found = 0;
--- struct skl_dapm_path_list *path_list, *tmp_list;
+++ int ret = 0, i;
struct skl_sst *ctx = skl->skl_sst;
--- sink = w;
--- sink_mconfig = sink->priv;
+++ sink_mconfig = w->priv;
/* Stop the pipe */
ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
if (ret)
return ret;
--- /*
--- * This list, dapm_path_list handling here does not need any locks
--- * as we are under dapm lock while handling widget events.
--- * List can be manipulated safely only under dapm widgets handler
--- * routines
--- */
--- list_for_each_entry_safe(path_list, tmp_list,
--- &skl->dapm_path_list, node) {
--- if (path_list->dapm_path->sink == sink) {
--- dev_dbg(ctx->dev, "Path found = %s\n",
--- path_list->dapm_path->name);
--- source = path_list->dapm_path->source;
--- src_mconfig = source->priv;
--- path_found = 1;
---
--- list_del(&path_list->node);
--- kfree(path_list);
--- break;
--- }
--- }
---
--- /*
--- * If path_found == 1, that means pmd for source pipe has
--- * not occurred, source is connected to some other sink.
--- * so its responsibility of sink to unbind itself from source.
--- */
--- if (path_found) {
--- ret = skl_stop_pipe(ctx, src_mconfig->pipe);
--- if (ret < 0)
--- return ret;
+++ for (i = 0; i < sink_mconfig->max_in_queue; i++) {
+++ if (sink_mconfig->m_in_pin[i].pin_state == SKL_PIN_BIND_DONE) {
+++ src_mconfig = sink_mconfig->m_in_pin[i].tgt_mcfg;
+++ if (!src_mconfig)
+++ continue;
+++ /*
+++ * If path_found == 1, that means pmd for source
+++ * pipe has not occurred, source is connected to
+++ * some other sink. so its responsibility of sink
+++ * to unbind itself from source.
+++ */
+++ ret = skl_stop_pipe(ctx, src_mconfig->pipe);
+++ if (ret < 0)
+++ return ret;
--- ret = skl_unbind_modules(ctx, src_mconfig, sink_mconfig);
+++ ret = skl_unbind_modules(ctx,
+++ src_mconfig, sink_mconfig);
+++ }
}
return ret;
int ret = 0;
skl_tplg_free_pipe_mcps(skl, mconfig);
+++ skl_tplg_free_pipe_mem(skl, mconfig);
list_for_each_entry(w_module, &s_pipe->w_list, node) {
dst_module = w_module->w->priv;
+++ skl_tplg_free_pipe_mcps(skl, dst_module);
if (src_module == NULL) {
src_module = dst_module;
continue;
}
ret = skl_delete_pipe(ctx, mconfig->pipe);
--- skl_tplg_free_pipe_mem(skl, mconfig);
--- return ret;
+++ return skl_tplg_unload_pipe_modules(ctx, s_pipe);
}
/*
static int skl_tplg_pga_dapm_post_pmd_event(struct snd_soc_dapm_widget *w,
struct skl *skl)
{
--- struct snd_soc_dapm_widget *source, *sink;
struct skl_module_cfg *src_mconfig, *sink_mconfig;
--- int ret = 0, path_found = 0;
--- struct skl_dapm_path_list *path_list, *tmp_path_list;
+++ int ret = 0, i;
struct skl_sst *ctx = skl->skl_sst;
--- source = w;
--- src_mconfig = source->priv;
+++ src_mconfig = w->priv;
--- skl_tplg_free_pipe_mcps(skl, src_mconfig);
/* Stop the pipe since this is a mixin module */
ret = skl_stop_pipe(ctx, src_mconfig->pipe);
if (ret)
return ret;
--- list_for_each_entry_safe(path_list, tmp_path_list, &skl->dapm_path_list, node) {
--- if (path_list->dapm_path->source == source) {
--- dev_dbg(ctx->dev, "Path found = %s\n",
--- path_list->dapm_path->name);
--- sink = path_list->dapm_path->sink;
--- sink_mconfig = sink->priv;
--- path_found = 1;
---
--- list_del(&path_list->node);
--- kfree(path_list);
--- break;
+++ for (i = 0; i < src_mconfig->max_out_queue; i++) {
+++ if (src_mconfig->m_out_pin[i].pin_state == SKL_PIN_BIND_DONE) {
+++ sink_mconfig = src_mconfig->m_out_pin[i].tgt_mcfg;
+++ if (!sink_mconfig)
+++ continue;
+++ /*
+++ * This is a connecter and if path is found that means
+++ * unbind between source and sink has not happened yet
+++ */
+++ ret = skl_stop_pipe(ctx, sink_mconfig->pipe);
+++ if (ret < 0)
+++ return ret;
+++ ret = skl_unbind_modules(ctx, src_mconfig,
+++ sink_mconfig);
}
}
--- /*
--- * This is a connector and if path is found that means
--- * unbind between source and sink has not happened yet
--- */
--- if (path_found) {
--- ret = skl_stop_pipe(ctx, src_mconfig->pipe);
--- if (ret < 0)
--- return ret;
---
--- ret = skl_unbind_modules(ctx, src_mconfig, sink_mconfig);
--- }
---
return ret;
}
return 0;
}
+++ static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
+++ unsigned int __user *data, unsigned int size)
+++ {
+++ struct soc_bytes_ext *sb =
+++ (struct soc_bytes_ext *)kcontrol->private_value;
+++ struct skl_algo_data *bc = (struct skl_algo_data *)sb->dobj.private;
+++ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+++ struct skl_module_cfg *mconfig = w->priv;
+++ struct skl *skl = get_skl_ctx(w->dapm->dev);
+++
+++ if (w->power)
+++ skl_get_module_params(skl->skl_sst, (u32 *)bc->params,
+++ bc->max, bc->param_id, mconfig);
+++
+++ if (bc->params) {
+++ if (copy_to_user(data, &bc->param_id, sizeof(u32)))
+++ return -EFAULT;
+++ if (copy_to_user(data + 1, &size, sizeof(u32)))
+++ return -EFAULT;
+++ if (copy_to_user(data + 2, bc->params, size))
+++ return -EFAULT;
+++ }
+++
+++ return 0;
+++ }
+++
+++ #define SKL_PARAM_VENDOR_ID 0xff
+++
+++ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
+++ const unsigned int __user *data, unsigned int size)
+++ {
+++ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+++ struct skl_module_cfg *mconfig = w->priv;
+++ struct soc_bytes_ext *sb =
+++ (struct soc_bytes_ext *)kcontrol->private_value;
+++ struct skl_algo_data *ac = (struct skl_algo_data *)sb->dobj.private;
+++ struct skl *skl = get_skl_ctx(w->dapm->dev);
+++
+++ if (ac->params) {
+++ /*
+++ * if the param_is is of type Vendor, firmware expects actual
+++ * parameter id and size from the control.
+++ */
+++ if (ac->param_id == SKL_PARAM_VENDOR_ID) {
+++ if (copy_from_user(ac->params, data, size))
+++ return -EFAULT;
+++ } else {
+++ if (copy_from_user(ac->params,
+++ data + 2 * sizeof(u32), size))
+++ return -EFAULT;
+++ }
+++
+++ if (w->power)
+++ return skl_set_module_params(skl->skl_sst,
+++ (u32 *)ac->params, ac->max,
+++ ac->param_id, mconfig);
+++ }
+++
+++ return 0;
+++ }
+++
/*
* The FE params are passed by hw_params of the DAI.
* On hw_params, the params are stored in Gateway module of the FE and we
memcpy(pipe->p_params, params, sizeof(*params));
if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
--- format = &mconfig->in_fmt;
+++ format = &mconfig->in_fmt[0];
else
--- format = &mconfig->out_fmt;
+++ format = &mconfig->out_fmt[0];
/* set the hw_params */
format->s_freq = params->s_freq;
break;
case SKL_DEPTH_24BIT:
+++ case SKL_DEPTH_32BIT:
format->bit_depth = SKL_DEPTH_32BIT;
break;
w = dai->playback_widget;
snd_soc_dapm_widget_for_each_sink_path(w, p) {
if (p->connect && p->sink->power &&
--- is_skl_dsp_widget_type(p->sink))
+++ !is_skl_dsp_widget_type(p->sink))
continue;
if (p->sink->priv) {
w = dai->capture_widget;
snd_soc_dapm_widget_for_each_source_path(w, p) {
if (p->connect && p->source->power &&
--- is_skl_dsp_widget_type(p->source))
+++ !is_skl_dsp_widget_type(p->source))
continue;
if (p->source->priv) {
memcpy(pipe->p_params, params, sizeof(*params));
+++ if (link_type == NHLT_LINK_HDA)
+++ return 0;
+++
/* update the blob based on virtual bus_id*/
cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
params->s_fmt, params->ch,
if (p->connect && is_skl_dsp_widget_type(p->source) &&
p->source->priv) {
--- if (!p->source->power) {
--- ret = skl_tplg_be_fill_pipe_params(
--- dai, p->source->priv,
--- params);
--- if (ret < 0)
--- return ret;
--- } else {
--- return -EBUSY;
--- }
+++ ret = skl_tplg_be_fill_pipe_params(dai,
+++ p->source->priv, params);
+++ if (ret < 0)
+++ return ret;
} else {
--- ret = skl_tplg_be_set_src_pipe_params(
--- dai, p->source, params);
+++ ret = skl_tplg_be_set_src_pipe_params(dai,
+++ p->source, params);
if (ret < 0)
return ret;
}
if (p->connect && is_skl_dsp_widget_type(p->sink) &&
p->sink->priv) {
--- if (!p->sink->power) {
--- ret = skl_tplg_be_fill_pipe_params(
--- dai, p->sink->priv, params);
--- if (ret < 0)
--- return ret;
--- } else {
--- return -EBUSY;
--- }
---
+++ ret = skl_tplg_be_fill_pipe_params(dai,
+++ p->sink->priv, params);
+++ if (ret < 0)
+++ return ret;
} else {
ret = skl_tplg_be_set_sink_pipe_params(
dai, p->sink, params);
{SKL_PGA_EVENT, skl_tplg_pga_event},
};
+++ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = {
+++ {SKL_CONTROL_TYPE_BYTE_TLV, skl_tplg_tlv_control_get,
+++ skl_tplg_tlv_control_set},
+++ };
+++
/*
* The topology binary passes the pin info for a module so initialize the pin
* info passed into module instance
m_pin[i].id.instance_id = dfw_pin[i].instance_id;
m_pin[i].in_use = false;
m_pin[i].is_dynamic = is_dynamic;
+++ m_pin[i].pin_state = SKL_PIN_UNBIND;
}
}
return ppl->pipe;
}
+++ static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt,
+++ struct skl_dfw_module_fmt *src_fmt,
+++ int pins)
+++ {
+++ int i;
+++
+++ for (i = 0; i < pins; i++) {
+++ dst_fmt[i].channels = src_fmt[i].channels;
+++ dst_fmt[i].s_freq = src_fmt[i].freq;
+++ dst_fmt[i].bit_depth = src_fmt[i].bit_depth;
+++ dst_fmt[i].valid_bit_depth = src_fmt[i].valid_bit_depth;
+++ dst_fmt[i].ch_cfg = src_fmt[i].ch_cfg;
+++ dst_fmt[i].ch_map = src_fmt[i].ch_map;
+++ dst_fmt[i].interleaving_style = src_fmt[i].interleaving_style;
+++ dst_fmt[i].sample_type = src_fmt[i].sample_type;
+++ }
+++ }
+++
/*
* Topology core widget load callback
*
mconfig->max_in_queue = dfw_config->max_in_queue;
mconfig->max_out_queue = dfw_config->max_out_queue;
mconfig->is_loadable = dfw_config->is_loadable;
--- mconfig->in_fmt.channels = dfw_config->in_fmt.channels;
--- mconfig->in_fmt.s_freq = dfw_config->in_fmt.freq;
--- mconfig->in_fmt.bit_depth = dfw_config->in_fmt.bit_depth;
--- mconfig->in_fmt.valid_bit_depth =
--- dfw_config->in_fmt.valid_bit_depth;
--- mconfig->in_fmt.ch_cfg = dfw_config->in_fmt.ch_cfg;
--- mconfig->out_fmt.channels = dfw_config->out_fmt.channels;
--- mconfig->out_fmt.s_freq = dfw_config->out_fmt.freq;
--- mconfig->out_fmt.bit_depth = dfw_config->out_fmt.bit_depth;
--- mconfig->out_fmt.valid_bit_depth =
--- dfw_config->out_fmt.valid_bit_depth;
--- mconfig->out_fmt.ch_cfg = dfw_config->out_fmt.ch_cfg;
+++ skl_tplg_fill_fmt(mconfig->in_fmt, dfw_config->in_fmt,
+++ MODULE_MAX_IN_PINS);
+++ skl_tplg_fill_fmt(mconfig->out_fmt, dfw_config->out_fmt,
+++ MODULE_MAX_OUT_PINS);
+++
mconfig->params_fixup = dfw_config->params_fixup;
mconfig->converter = dfw_config->converter;
mconfig->m_type = dfw_config->module_type;
mconfig->vbus_id = dfw_config->vbus_id;
+++ mconfig->mem_pages = dfw_config->mem_pages;
pipe = skl_tplg_add_pipe(bus->dev, skl, &dfw_config->pipe);
if (pipe)
mconfig->time_slot = dfw_config->time_slot;
mconfig->formats_config.caps_size = dfw_config->caps.caps_size;
--- mconfig->m_in_pin = devm_kzalloc(bus->dev,
--- (mconfig->max_in_queue) *
--- sizeof(*mconfig->m_in_pin),
--- GFP_KERNEL);
+++ if (dfw_config->is_loadable)
+++ memcpy(mconfig->guid, dfw_config->uuid,
+++ ARRAY_SIZE(dfw_config->uuid));
+++
+++ mconfig->m_in_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) *
+++ sizeof(*mconfig->m_in_pin),
+++ GFP_KERNEL);
if (!mconfig->m_in_pin)
return -ENOMEM;
return -ENOMEM;
memcpy(mconfig->formats_config.caps, dfw_config->caps.caps,
--- dfw_config->caps.caps_size);
+++ dfw_config->caps.caps_size);
+++ mconfig->formats_config.param_id = dfw_config->caps.param_id;
+++ mconfig->formats_config.set_params = dfw_config->caps.set_params;
bind_event:
if (tplg_w->event_type == 0) {
return 0;
}
+++ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
+++ struct snd_soc_tplg_bytes_control *bc)
+++ {
+++ struct skl_algo_data *ac;
+++ struct skl_dfw_algo_data *dfw_ac =
+++ (struct skl_dfw_algo_data *)bc->priv.data;
+++
+++ ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL);
+++ if (!ac)
+++ return -ENOMEM;
+++
+++ /* Fill private data */
+++ ac->max = dfw_ac->max;
+++ ac->param_id = dfw_ac->param_id;
+++ ac->set_params = dfw_ac->set_params;
+++
+++ if (ac->max) {
+++ ac->params = (char *) devm_kzalloc(dev, ac->max, GFP_KERNEL);
+++ if (!ac->params)
+++ return -ENOMEM;
+++
+++ if (dfw_ac->params)
+++ memcpy(ac->params, dfw_ac->params, ac->max);
+++ }
+++
+++ be->dobj.private = ac;
+++ return 0;
+++ }
+++
+++ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
+++ struct snd_kcontrol_new *kctl,
+++ struct snd_soc_tplg_ctl_hdr *hdr)
+++ {
+++ struct soc_bytes_ext *sb;
+++ struct snd_soc_tplg_bytes_control *tplg_bc;
+++ struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
+++ struct hdac_bus *bus = ebus_to_hbus(ebus);
+++
+++ switch (hdr->ops.info) {
+++ case SND_SOC_TPLG_CTL_BYTES:
+++ tplg_bc = container_of(hdr,
+++ struct snd_soc_tplg_bytes_control, hdr);
+++ if (kctl->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+++ sb = (struct soc_bytes_ext *)kctl->private_value;
+++ if (tplg_bc->priv.size)
+++ return skl_init_algo_data(
+++ bus->dev, sb, tplg_bc);
+++ }
+++ break;
+++
+++ default:
+++ dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
+++ hdr->ops.get, hdr->ops.put, hdr->ops.info);
+++ break;
+++ }
+++
+++ return 0;
+++ }
+++
static struct snd_soc_tplg_ops skl_tplg_ops = {
.widget_load = skl_tplg_widget_load,
+++ .control_load = skl_tplg_control_load,
+++ .bytes_ext_ops = skl_tlv_ops,
+++ .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
};
/* This will be read from topology manifest, currently defined here */
*/
ret = snd_soc_tplg_component_load(&platform->component,
&skl_tplg_ops, fw, 0);
+++ release_firmware(fw);
if (ret < 0) {
dev_err(bus->dev, "tplg component load failed%d\n", ret);
return -EINVAL;