Commit b663a8c5 authored by Jeeja KP's avatar Jeeja KP Committed by Mark Brown

ASoC: Intel: Skylake: Initialize and load DSP controls

Initialize and creates DSP controls if processing pipe capability
is supported by HW. Updates the dma_id, hw_params to module param
to be used when DSP module has to be configured.
Signed-off-by: default avatarJeeja KP <jeeja.kp@intel.com>
Signed-off-by: default avatarSubhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 3af36706
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "skl.h" #include "skl.h"
#include "skl-topology.h"
#define HDA_MONO 1 #define HDA_MONO 1
#define HDA_STEREO 2 #define HDA_STEREO 2
...@@ -214,6 +215,8 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -214,6 +215,8 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
struct hdac_ext_stream *stream = get_hdac_ext_stream(substream); struct hdac_ext_stream *stream = get_hdac_ext_stream(substream);
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct skl_pipe_params p_params = {0};
struct skl_module_cfg *m_cfg;
int ret, dma_id; int ret, dma_id;
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name); dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
...@@ -228,6 +231,16 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -228,6 +231,16 @@ static int skl_pcm_hw_params(struct snd_pcm_substream *substream,
dma_id = hdac_stream(stream)->stream_tag - 1; dma_id = hdac_stream(stream)->stream_tag - 1;
dev_dbg(dai->dev, "dma_id=%d\n", dma_id); dev_dbg(dai->dev, "dma_id=%d\n", dma_id);
p_params.s_fmt = snd_pcm_format_width(params_format(params));
p_params.ch = params_channels(params);
p_params.s_freq = params_rate(params);
p_params.host_dma_id = dma_id;
p_params.stream = substream->stream;
m_cfg = skl_tplg_fe_get_cpr_module(dai, p_params.stream);
if (m_cfg)
skl_tplg_update_pipe_params(dai->dev, m_cfg, &p_params);
return 0; return 0;
} }
...@@ -268,6 +281,46 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream, ...@@ -268,6 +281,46 @@ static int skl_pcm_hw_free(struct snd_pcm_substream *substream,
return skl_substream_free_pages(ebus_to_hbus(ebus), substream); return skl_substream_free_pages(ebus_to_hbus(ebus), substream);
} }
static int skl_be_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct skl_pipe_params p_params = {0};
p_params.s_fmt = snd_pcm_format_width(params_format(params));
p_params.ch = params_channels(params);
p_params.s_freq = params_rate(params);
p_params.stream = substream->stream;
skl_tplg_be_update_params(dai, &p_params);
return 0;
}
static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct skl *skl = get_skl_ctx(dai->dev);
struct skl_sst *ctx = skl->skl_sst;
struct skl_module_cfg *mconfig;
mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
if (!mconfig)
return -EIO;
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
return skl_run_pipe(ctx, mconfig->pipe);
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
return skl_stop_pipe(ctx, mconfig->pipe);
default:
return 0;
}
}
static int skl_link_hw_params(struct snd_pcm_substream *substream, static int skl_link_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
...@@ -277,9 +330,8 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, ...@@ -277,9 +330,8 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
struct skl_dma_params *dma_params; struct skl_dma_params *dma_params;
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
int dma_id; struct skl_pipe_params p_params = {0};
pr_debug("%s\n", __func__);
link_dev = snd_hdac_ext_stream_assign(ebus, substream, link_dev = snd_hdac_ext_stream_assign(ebus, substream,
HDAC_EXT_STREAM_TYPE_LINK); HDAC_EXT_STREAM_TYPE_LINK);
if (!link_dev) if (!link_dev)
...@@ -293,7 +345,14 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, ...@@ -293,7 +345,14 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
if (dma_params) if (dma_params)
dma_params->stream_tag = hdac_stream(link_dev)->stream_tag; dma_params->stream_tag = hdac_stream(link_dev)->stream_tag;
snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params); snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params);
dma_id = hdac_stream(link_dev)->stream_tag - 1;
p_params.s_fmt = snd_pcm_format_width(params_format(params));
p_params.ch = params_channels(params);
p_params.s_freq = params_rate(params);
p_params.stream = substream->stream;
p_params.link_dma_id = hdac_stream(link_dev)->stream_tag - 1;
skl_tplg_be_update_params(dai, &p_params);
return 0; return 0;
} }
...@@ -308,27 +367,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, ...@@ -308,27 +367,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
unsigned int format_val = 0; unsigned int format_val = 0;
struct skl_dma_params *dma_params; struct skl_dma_params *dma_params;
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_pcm_hw_params *params;
struct snd_interval *channels, *rate;
struct hdac_ext_link *link; struct hdac_ext_link *link;
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
if (link_dev->link_prepared) { if (link_dev->link_prepared) {
dev_dbg(dai->dev, "already stream is prepared - returning\n"); dev_dbg(dai->dev, "already stream is prepared - returning\n");
return 0; return 0;
} }
params = devm_kzalloc(dai->dev, sizeof(*params), GFP_KERNEL);
if (params == NULL)
return -ENOMEM;
channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
channels->min = channels->max = substream->runtime->channels;
rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
rate->min = rate->max = substream->runtime->rate;
snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
SNDRV_PCM_HW_PARAM_FIRST_MASK],
substream->runtime->format);
dma_params = (struct skl_dma_params *) dma_params = (struct skl_dma_params *)
snd_soc_dai_get_dma_data(codec_dai, substream); snd_soc_dai_get_dma_data(codec_dai, substream);
...@@ -399,13 +443,13 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream, ...@@ -399,13 +443,13 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int skl_hda_be_startup(struct snd_pcm_substream *substream, static int skl_be_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
return pm_runtime_get_sync(dai->dev); return pm_runtime_get_sync(dai->dev);
} }
static void skl_hda_be_shutdown(struct snd_pcm_substream *substream, static void skl_be_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
pm_runtime_mark_last_busy(dai->dev); pm_runtime_mark_last_busy(dai->dev);
...@@ -418,20 +462,28 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = { ...@@ -418,20 +462,28 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = {
.prepare = skl_pcm_prepare, .prepare = skl_pcm_prepare,
.hw_params = skl_pcm_hw_params, .hw_params = skl_pcm_hw_params,
.hw_free = skl_pcm_hw_free, .hw_free = skl_pcm_hw_free,
.trigger = skl_pcm_trigger,
}; };
static struct snd_soc_dai_ops skl_dmic_dai_ops = { static struct snd_soc_dai_ops skl_dmic_dai_ops = {
.startup = skl_hda_be_startup, .startup = skl_be_startup,
.shutdown = skl_hda_be_shutdown, .hw_params = skl_be_hw_params,
.shutdown = skl_be_shutdown,
};
static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
.startup = skl_be_startup,
.hw_params = skl_be_hw_params,
.shutdown = skl_be_shutdown,
}; };
static struct snd_soc_dai_ops skl_link_dai_ops = { static struct snd_soc_dai_ops skl_link_dai_ops = {
.startup = skl_hda_be_startup, .startup = skl_be_startup,
.prepare = skl_link_pcm_prepare, .prepare = skl_link_pcm_prepare,
.hw_params = skl_link_hw_params, .hw_params = skl_link_hw_params,
.hw_free = skl_link_hw_free, .hw_free = skl_link_hw_free,
.trigger = skl_link_pcm_trigger, .trigger = skl_link_pcm_trigger,
.shutdown = skl_hda_be_shutdown, .shutdown = skl_be_shutdown,
}; };
static struct snd_soc_dai_driver skl_platform_dai[] = { static struct snd_soc_dai_driver skl_platform_dai[] = {
...@@ -487,6 +539,24 @@ static struct snd_soc_dai_driver skl_platform_dai[] = { ...@@ -487,6 +539,24 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
}, },
}, },
/* BE CPU Dais */ /* BE CPU Dais */
{
.name = "SSP0 Pin",
.ops = &skl_be_ssp_dai_ops,
.playback = {
.stream_name = "ssp0 Tx",
.channels_min = HDA_STEREO,
.channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
.stream_name = "ssp0 Rx",
.channels_min = HDA_STEREO,
.channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
},
{ {
.name = "iDisp Pin", .name = "iDisp Pin",
.ops = &skl_link_dai_ops, .ops = &skl_link_dai_ops,
...@@ -544,7 +614,7 @@ static int skl_platform_open(struct snd_pcm_substream *substream) ...@@ -544,7 +614,7 @@ static int skl_platform_open(struct snd_pcm_substream *substream)
return 0; return 0;
} }
static int skl_pcm_trigger(struct snd_pcm_substream *substream, static int skl_coupled_trigger(struct snd_pcm_substream *substream,
int cmd) int cmd)
{ {
struct hdac_ext_bus *ebus = get_bus_ctx(substream); struct hdac_ext_bus *ebus = get_bus_ctx(substream);
...@@ -618,7 +688,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, ...@@ -618,7 +688,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int skl_dsp_trigger(struct snd_pcm_substream *substream, static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
int cmd) int cmd)
{ {
struct hdac_ext_bus *ebus = get_bus_ctx(substream); struct hdac_ext_bus *ebus = get_bus_ctx(substream);
...@@ -675,9 +745,9 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream, ...@@ -675,9 +745,9 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
struct hdac_ext_bus *ebus = get_bus_ctx(substream); struct hdac_ext_bus *ebus = get_bus_ctx(substream);
if (ebus->ppcap) if (ebus->ppcap)
return skl_dsp_trigger(substream, cmd); return skl_decoupled_trigger(substream, cmd);
else else
return skl_pcm_trigger(substream, cmd); return skl_coupled_trigger(substream, cmd);
} }
/* calculate runtime delay from LPIB */ /* calculate runtime delay from LPIB */
...@@ -844,7 +914,17 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd) ...@@ -844,7 +914,17 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
return retval; return retval;
} }
static int skl_platform_soc_probe(struct snd_soc_platform *platform)
{
struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev);
if (ebus->ppcap)
return skl_tplg_init(platform, ebus);
return 0;
}
static struct snd_soc_platform_driver skl_platform_drv = { static struct snd_soc_platform_driver skl_platform_drv = {
.probe = skl_platform_soc_probe,
.ops = &skl_platform_ops, .ops = &skl_platform_ops,
.pcm_new = skl_pcm_new, .pcm_new = skl_pcm_new,
.pcm_free = skl_pcm_free, .pcm_free = skl_pcm_free,
...@@ -857,6 +937,11 @@ static const struct snd_soc_component_driver skl_component = { ...@@ -857,6 +937,11 @@ static const struct snd_soc_component_driver skl_component = {
int skl_platform_register(struct device *dev) int skl_platform_register(struct device *dev)
{ {
int ret; int ret;
struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
struct skl *skl = ebus_to_skl(ebus);
INIT_LIST_HEAD(&skl->ppl_list);
INIT_LIST_HEAD(&skl->dapm_path_list);
ret = snd_soc_register_platform(dev, &skl_platform_drv); ret = snd_soc_register_platform(dev, &skl_platform_drv);
if (ret) { if (ret) {
......
...@@ -1089,8 +1089,8 @@ static struct skl_pipe *skl_tplg_add_pipe(struct device *dev, ...@@ -1089,8 +1089,8 @@ static struct skl_pipe *skl_tplg_add_pipe(struct device *dev,
* FW expects like ids, resource values, formats etc * FW expects like ids, resource values, formats etc
*/ */
static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
struct snd_soc_dapm_widget *w, struct snd_soc_dapm_widget *w,
struct snd_soc_tplg_dapm_widget *tplg_w) struct snd_soc_tplg_dapm_widget *tplg_w)
{ {
int ret; int ret;
struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt); struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
...@@ -1098,7 +1098,8 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, ...@@ -1098,7 +1098,8 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus);
struct skl_module_cfg *mconfig; struct skl_module_cfg *mconfig;
struct skl_pipe *pipe; struct skl_pipe *pipe;
struct skl_dfw_module *dfw_config = (struct skl_dfw_module *)tplg_w->priv.data; struct skl_dfw_module *dfw_config =
(struct skl_dfw_module *)tplg_w->priv.data;
if (!tplg_w->priv.size) if (!tplg_w->priv.size)
goto bind_event; goto bind_event;
...@@ -1121,12 +1122,14 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, ...@@ -1121,12 +1122,14 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
mconfig->in_fmt.channels = dfw_config->in_fmt.channels; mconfig->in_fmt.channels = dfw_config->in_fmt.channels;
mconfig->in_fmt.s_freq = dfw_config->in_fmt.freq; mconfig->in_fmt.s_freq = dfw_config->in_fmt.freq;
mconfig->in_fmt.bit_depth = dfw_config->in_fmt.bit_depth; 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.valid_bit_depth =
dfw_config->in_fmt.valid_bit_depth;
mconfig->in_fmt.ch_cfg = dfw_config->in_fmt.ch_cfg; mconfig->in_fmt.ch_cfg = dfw_config->in_fmt.ch_cfg;
mconfig->out_fmt.channels = dfw_config->out_fmt.channels; mconfig->out_fmt.channels = dfw_config->out_fmt.channels;
mconfig->out_fmt.s_freq = dfw_config->out_fmt.freq; mconfig->out_fmt.s_freq = dfw_config->out_fmt.freq;
mconfig->out_fmt.bit_depth = dfw_config->out_fmt.bit_depth; 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.valid_bit_depth =
dfw_config->out_fmt.valid_bit_depth;
mconfig->out_fmt.ch_cfg = dfw_config->out_fmt.ch_cfg; mconfig->out_fmt.ch_cfg = dfw_config->out_fmt.ch_cfg;
mconfig->params_fixup = dfw_config->params_fixup; mconfig->params_fixup = dfw_config->params_fixup;
mconfig->converter = dfw_config->converter; mconfig->converter = dfw_config->converter;
...@@ -1142,15 +1145,17 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, ...@@ -1142,15 +1145,17 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
mconfig->time_slot = dfw_config->time_slot; mconfig->time_slot = dfw_config->time_slot;
mconfig->formats_config.caps_size = dfw_config->caps.caps_size; mconfig->formats_config.caps_size = dfw_config->caps.caps_size;
mconfig->m_in_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) * mconfig->m_in_pin = devm_kzalloc(bus->dev,
sizeof(*mconfig->m_in_pin), (mconfig->max_in_queue) *
GFP_KERNEL); sizeof(*mconfig->m_in_pin),
GFP_KERNEL);
if (!mconfig->m_in_pin) if (!mconfig->m_in_pin)
return -ENOMEM; return -ENOMEM;
mconfig->m_out_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) * mconfig->m_out_pin = devm_kzalloc(bus->dev,
sizeof(*mconfig->m_out_pin), (mconfig->max_in_queue) *
GFP_KERNEL); sizeof(*mconfig->m_out_pin),
GFP_KERNEL);
if (!mconfig->m_out_pin) if (!mconfig->m_out_pin)
return -ENOMEM; return -ENOMEM;
...@@ -1163,13 +1168,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, ...@@ -1163,13 +1168,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
goto bind_event; goto bind_event;
mconfig->formats_config.caps = (u32 *)devm_kzalloc(bus->dev, mconfig->formats_config.caps = (u32 *)devm_kzalloc(bus->dev,
mconfig->formats_config.caps_size, GFP_KERNEL); mconfig->formats_config.caps_size, GFP_KERNEL);
if (mconfig->formats_config.caps == NULL) if (mconfig->formats_config.caps == NULL)
return -ENOMEM; return -ENOMEM;
memcpy(mconfig->formats_config.caps, dfw_config->caps.caps, memcpy(mconfig->formats_config.caps, dfw_config->caps.caps,
dfw_config->caps.caps_size); dfw_config->caps.caps_size);
bind_event: bind_event:
if (tplg_w->event_type == 0) { if (tplg_w->event_type == 0) {
...@@ -1178,7 +1183,8 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, ...@@ -1178,7 +1183,8 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
} }
ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops, ret = snd_soc_tplg_widget_bind_event(w, skl_tplg_widget_ops,
ARRAY_SIZE(skl_tplg_widget_ops), tplg_w->event_type); ARRAY_SIZE(skl_tplg_widget_ops),
tplg_w->event_type);
if (ret) { if (ret) {
dev_err(bus->dev, "%s: No matching event handlers found for %d\n", dev_err(bus->dev, "%s: No matching event handlers found for %d\n",
...@@ -1209,7 +1215,7 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus) ...@@ -1209,7 +1215,7 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
if (ret < 0) { if (ret < 0) {
dev_err(bus->dev, "config firmware %s request failed with %d\n", dev_err(bus->dev, "tplg fw %s load failed with %d\n",
"dfw_sst.bin", ret); "dfw_sst.bin", ret);
return ret; return ret;
} }
...@@ -1218,7 +1224,8 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus) ...@@ -1218,7 +1224,8 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
* The complete tplg for SKL is loaded as index 0, we don't use * The complete tplg for SKL is loaded as index 0, we don't use
* any other index * any other index
*/ */
ret = snd_soc_tplg_component_load(&platform->component, &skl_tplg_ops, fw, 0); ret = snd_soc_tplg_component_load(&platform->component,
&skl_tplg_ops, fw, 0);
if (ret < 0) { if (ret < 0) {
dev_err(bus->dev, "tplg component load failed%d\n", ret); dev_err(bus->dev, "tplg component load failed%d\n", ret);
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment