Skip to content

Commit

Permalink
ASoC: Intel: Skylake: Initialize and load DSP controls
Browse files Browse the repository at this point in the history
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: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Jeeja KP authored and Mark Brown committed Oct 7, 2015
1 parent 3af3670 commit b663a8c
Showing 2 changed files with 136 additions and 44 deletions.
141 changes: 113 additions & 28 deletions sound/soc/intel/skylake/skl-pcm.c
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "skl.h"
#include "skl-topology.h"

#define HDA_MONO 1
#define HDA_STEREO 2
@@ -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_stream *stream = get_hdac_ext_stream(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct skl_pipe_params p_params = {0};
struct skl_module_cfg *m_cfg;
int ret, dma_id;

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,
dma_id = hdac_stream(stream)->stream_tag - 1;
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;
}

@@ -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);
}

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,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -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 skl_dma_params *dma_params;
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,
HDAC_EXT_STREAM_TYPE_LINK);
if (!link_dev)
@@ -293,7 +345,14 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
if (dma_params)
dma_params->stream_tag = hdac_stream(link_dev)->stream_tag;
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;
}
@@ -308,27 +367,12 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
unsigned int format_val = 0;
struct skl_dma_params *dma_params;
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;

dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
if (link_dev->link_prepared) {
dev_dbg(dai->dev, "already stream is prepared - returning\n");
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 *)
snd_soc_dai_get_dma_data(codec_dai, substream);
@@ -399,13 +443,13 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
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)
{
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)
{
pm_runtime_mark_last_busy(dai->dev);
@@ -418,20 +462,28 @@ static struct snd_soc_dai_ops skl_pcm_dai_ops = {
.prepare = skl_pcm_prepare,
.hw_params = skl_pcm_hw_params,
.hw_free = skl_pcm_hw_free,
.trigger = skl_pcm_trigger,
};

static struct snd_soc_dai_ops skl_dmic_dai_ops = {
.startup = skl_hda_be_startup,
.shutdown = skl_hda_be_shutdown,
.startup = skl_be_startup,
.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 = {
.startup = skl_hda_be_startup,
.startup = skl_be_startup,
.prepare = skl_link_pcm_prepare,
.hw_params = skl_link_hw_params,
.hw_free = skl_link_hw_free,
.trigger = skl_link_pcm_trigger,
.shutdown = skl_hda_be_shutdown,
.shutdown = skl_be_shutdown,
};

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 */
{
.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",
.ops = &skl_link_dai_ops,
@@ -544,7 +614,7 @@ static int skl_platform_open(struct snd_pcm_substream *substream)
return 0;
}

static int skl_pcm_trigger(struct snd_pcm_substream *substream,
static int skl_coupled_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct hdac_ext_bus *ebus = get_bus_ctx(substream);
@@ -618,7 +688,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream,
return 0;
}

static int skl_dsp_trigger(struct snd_pcm_substream *substream,
static int skl_decoupled_trigger(struct snd_pcm_substream *substream,
int cmd)
{
struct hdac_ext_bus *ebus = get_bus_ctx(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);

if (ebus->ppcap)
return skl_dsp_trigger(substream, cmd);
return skl_decoupled_trigger(substream, cmd);
else
return skl_pcm_trigger(substream, cmd);
return skl_coupled_trigger(substream, cmd);
}

/* calculate runtime delay from LPIB */
@@ -844,7 +914,17 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
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 = {
.probe = skl_platform_soc_probe,
.ops = &skl_platform_ops,
.pcm_new = skl_pcm_new,
.pcm_free = skl_pcm_free,
@@ -857,6 +937,11 @@ static const struct snd_soc_component_driver skl_component = {
int skl_platform_register(struct device *dev)
{
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);
if (ret) {
39 changes: 23 additions & 16 deletions sound/soc/intel/skylake/skl-topology.c
Original file line number Diff line number Diff line change
@@ -1089,16 +1089,17 @@ static struct skl_pipe *skl_tplg_add_pipe(struct device *dev,
* FW expects like ids, resource values, formats etc
*/
static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
struct snd_soc_dapm_widget *w,
struct snd_soc_tplg_dapm_widget *tplg_w)
struct snd_soc_dapm_widget *w,
struct snd_soc_tplg_dapm_widget *tplg_w)
{
int ret;
struct hdac_ext_bus *ebus = snd_soc_component_get_drvdata(cmpnt);
struct skl *skl = ebus_to_skl(ebus);
struct hdac_bus *bus = ebus_to_hbus(ebus);
struct skl_module_cfg *mconfig;
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)
goto bind_event;
@@ -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.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.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.valid_bit_depth =
dfw_config->out_fmt.valid_bit_depth;
mconfig->out_fmt.ch_cfg = dfw_config->out_fmt.ch_cfg;
mconfig->params_fixup = dfw_config->params_fixup;
mconfig->converter = dfw_config->converter;
@@ -1142,15 +1145,17 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
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);
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;

mconfig->m_out_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) *
sizeof(*mconfig->m_out_pin),
GFP_KERNEL);
mconfig->m_out_pin = devm_kzalloc(bus->dev,
(mconfig->max_in_queue) *
sizeof(*mconfig->m_out_pin),
GFP_KERNEL);
if (!mconfig->m_out_pin)
return -ENOMEM;

@@ -1163,13 +1168,13 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt,
goto bind_event;

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)
return -ENOMEM;

memcpy(mconfig->formats_config.caps, dfw_config->caps.caps,
dfw_config->caps.caps_size);
dfw_config->caps.caps_size);

bind_event:
if (tplg_w->event_type == 0) {
@@ -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,
ARRAY_SIZE(skl_tplg_widget_ops), tplg_w->event_type);
ARRAY_SIZE(skl_tplg_widget_ops),
tplg_w->event_type);

if (ret) {
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)

ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
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);
return ret;
}
@@ -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
* 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) {
dev_err(bus->dev, "tplg component load failed%d\n", ret);
return -EINVAL;

0 comments on commit b663a8c

Please sign in to comment.