alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
From: Vinod Koul <vinod.koul@intel.com>
To: alsa-devel@alsa-project.org
Cc: patches.audio@intel.com, liam.r.girdwood@linux.intel.com,
	Vinod Koul <vinod.koul@intel.com>,
	broonie@kernel.org, Jeeja KP <jeeja.kp@intel.com>,
	"Subhransu S. Prusty" <subhransu.s.prusty@intel.com>
Subject: [PATCH v4 4/8] ASoC: Intel: Skylake: Add FE and BE hw_params handling
Date: Wed,  7 Oct 2015 11:31:55 +0100	[thread overview]
Message-ID: <1444213919-32369-5-git-send-email-vinod.koul@intel.com> (raw)
In-Reply-To: <1444213919-32369-1-git-send-email-vinod.koul@intel.com>

For FE and BE, the PCM parameters come from FE and BE hw_params
values passed. For a FE we convert the FE params to DSP expected
module format and pass to DSP. For a BE we need to find the
gateway settings (i2s/PDM) to be applied. These are queried from
NHLT table and applied.

Further for BE based on direction the settings are applied as
either source or destination parameters.

These helpers here allow the format to be calculated and queried
as per firmware format.

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>
---
 sound/soc/intel/skylake/skl-topology.c | 238 +++++++++++++++++++++++++++++++++
 sound/soc/intel/skylake/skl-topology.h |  12 ++
 2 files changed, 250 insertions(+)

diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index 6d1d29aa933a..827f21db0eb2 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -773,3 +773,241 @@ static int skl_tplg_pga_event(struct snd_soc_dapm_widget *w,
 
 	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
+ * need to calculate the format in DSP module configuration, that
+ * conversion is done here
+ */
+int skl_tplg_update_pipe_params(struct device *dev,
+			struct skl_module_cfg *mconfig,
+			struct skl_pipe_params *params)
+{
+	struct skl_pipe *pipe = mconfig->pipe;
+	struct skl_module_fmt *format = NULL;
+
+	memcpy(pipe->p_params, params, sizeof(*params));
+
+	if (params->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		format = &mconfig->in_fmt;
+	else
+		format = &mconfig->out_fmt;
+
+	/* set the hw_params */
+	format->s_freq = params->s_freq;
+	format->channels = params->ch;
+	format->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 (format->valid_bit_depth) {
+	case SKL_DEPTH_16BIT:
+		format->bit_depth = format->valid_bit_depth;
+		break;
+
+	case SKL_DEPTH_24BIT:
+		format->bit_depth = SKL_DEPTH_32BIT;
+		break;
+
+	default:
+		dev_err(dev, "Invalid bit depth %x for pipe\n",
+				format->valid_bit_depth);
+		return -EINVAL;
+	}
+
+	if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		mconfig->ibs = (format->s_freq / 1000) *
+				(format->channels) *
+				(format->bit_depth >> 3);
+	} else {
+		mconfig->obs = (format->s_freq / 1000) *
+				(format->channels) *
+				(format->bit_depth >> 3);
+	}
+
+	return 0;
+}
+
+/*
+ * Query the module config for the FE DAI
+ * This is used to find the hw_params set for that DAI and apply to FE
+ * pipeline
+ */
+struct skl_module_cfg *
+skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream)
+{
+	struct snd_soc_dapm_widget *w;
+	struct snd_soc_dapm_path *p = NULL;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		w = dai->playback_widget;
+		snd_soc_dapm_widget_for_each_source_path(w, p) {
+			if (p->connect && p->sink->power &&
+					is_skl_dsp_widget_type(p->sink))
+				continue;
+
+			if (p->sink->priv) {
+				dev_dbg(dai->dev, "set params for %s\n",
+						p->sink->name);
+				return p->sink->priv;
+			}
+		}
+	} else {
+		w = dai->capture_widget;
+		snd_soc_dapm_widget_for_each_sink_path(w, p) {
+			if (p->connect && p->source->power &&
+					is_skl_dsp_widget_type(p->source))
+				continue;
+
+			if (p->source->priv) {
+				dev_dbg(dai->dev, "set params for %s\n",
+						p->source->name);
+				return p->source->priv;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+static u8 skl_tplg_be_link_type(int dev_type)
+{
+	int ret;
+
+	switch (dev_type) {
+	case SKL_DEVICE_BT:
+		ret = NHLT_LINK_SSP;
+		break;
+
+	case SKL_DEVICE_DMIC:
+		ret = NHLT_LINK_DMIC;
+		break;
+
+	case SKL_DEVICE_I2S:
+		ret = NHLT_LINK_SSP;
+		break;
+
+	case SKL_DEVICE_HDALINK:
+		ret = NHLT_LINK_HDA;
+		break;
+
+	default:
+		ret = NHLT_LINK_INVALID;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Fill the BE gateway parameters
+ * The BE gateway expects a blob of parameters which are kept in the ACPI
+ * NHLT blob, so query the blob for interface type (i2s/pdm) and instance.
+ * The port can have multiple settings so pick based on the PCM
+ * parameters
+ */
+static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai,
+				struct skl_module_cfg *mconfig,
+				struct skl_pipe_params *params)
+{
+	struct skl_pipe *pipe = mconfig->pipe;
+	struct nhlt_specific_cfg *cfg;
+	struct skl *skl = get_skl_ctx(dai->dev);
+	int link_type = skl_tplg_be_link_type(mconfig->dev_type);
+
+	memcpy(pipe->p_params, params, sizeof(*params));
+
+	/* update the blob based on virtual bus_id*/
+	cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type,
+					params->s_fmt, params->ch,
+					params->s_freq, params->stream);
+	if (cfg) {
+		mconfig->formats_config.caps_size = cfg->size;
+		memcpy(mconfig->formats_config.caps, &cfg->caps, cfg->size);
+	} else {
+		dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n",
+					mconfig->vbus_id, link_type,
+					params->stream);
+		dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n",
+				 params->ch, params->s_freq, params->s_fmt);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai,
+				struct snd_soc_dapm_widget *w,
+				struct skl_pipe_params *params)
+{
+	struct snd_soc_dapm_path *p;
+
+	snd_soc_dapm_widget_for_each_sink_path(w, p) {
+		if (p->connect && is_skl_dsp_widget_type(p->source) &&
+						p->source->priv) {
+
+			if (!p->source->power)
+				return skl_tplg_be_fill_pipe_params(
+						dai, p->source->priv,
+						params);
+			else
+				return -EBUSY;
+		} else {
+			return skl_tplg_be_set_src_pipe_params(
+						dai, p->source,	params);
+		}
+	}
+
+	return -EIO;
+}
+
+static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai,
+	struct snd_soc_dapm_widget *w, struct skl_pipe_params *params)
+{
+	struct snd_soc_dapm_path *p = NULL;
+
+	snd_soc_dapm_widget_for_each_source_path(w, p) {
+		if (p->connect && is_skl_dsp_widget_type(p->sink) &&
+						p->sink->priv) {
+
+			if (!p->sink->power)
+				return skl_tplg_be_fill_pipe_params(
+						dai, p->sink->priv, params);
+			else
+				return -EBUSY;
+
+		} else {
+			return skl_tplg_be_set_sink_pipe_params(
+						dai, p->sink, params);
+		}
+	}
+
+	return -EIO;
+}
+
+/*
+ * BE hw_params can be a source parameters (capture) or sink parameters
+ * (playback). Based on sink and source we need to either find the source
+ * list or the sink list and set the pipeline parameters
+ */
+int skl_tplg_be_update_params(struct snd_soc_dai *dai,
+				struct skl_pipe_params *params)
+{
+	struct snd_soc_dapm_widget *w;
+
+	if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		w = dai->playback_widget;
+
+		return skl_tplg_be_set_src_pipe_params(dai, w, params);
+
+	} else {
+		w = dai->capture_widget;
+
+		return skl_tplg_be_set_sink_pipe_params(dai, w, params);
+	}
+
+	return 0;
+}
diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h
index b3a22a6f8d27..12db94d238f2 100644
--- a/sound/soc/intel/skylake/skl-topology.h
+++ b/sound/soc/intel/skylake/skl-topology.h
@@ -280,6 +280,18 @@ static inline struct skl *get_skl_ctx(struct device *dev)
 	return ebus_to_skl(ebus);
 }
 
+int skl_tplg_be_update_params(struct snd_soc_dai *dai,
+	struct skl_pipe_params *params);
+void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai,
+	struct skl_pipe_params *params, int stream);
+int skl_tplg_init(struct snd_soc_platform *platform,
+				struct hdac_ext_bus *ebus);
+struct skl_module_cfg *skl_tplg_fe_get_cpr_module(
+		struct snd_soc_dai *dai, int stream);
+int skl_tplg_update_pipe_params(struct device *dev,
+		struct skl_module_cfg *mconfig, struct skl_pipe_params *params);
+
+
 int skl_create_pipeline(struct skl_sst *ctx, struct skl_pipe *pipe);
 
 int skl_run_pipe(struct skl_sst *ctx, struct skl_pipe *pipe);
-- 
2.4.3

  parent reply	other threads:[~2015-10-07 10:32 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-07 10:31 [PATCH v4 0/8] Add DSP topology management for SKL Vinod Koul
2015-10-07 10:31 ` [PATCH v4 1/8] ASoC: Intel: Skylake: Add pipe and modules handlers Vinod Koul
2015-10-07 15:06   ` Applied "ASoC: Intel: Skylake: Add pipe and modules handlers" to the asoc tree Mark Brown
2015-10-07 10:31 ` [PATCH v4 2/8] ASoC: Intel: Skylake: Add module configuration helpers Vinod Koul
2015-10-07 15:06   ` Applied "ASoC: Intel: Skylake: Add module configuration helpers" to the asoc tree Mark Brown
2015-10-07 10:31 ` [PATCH v4 3/8] ASoC: Intel: Skylake: add DSP platform widget event handlers Vinod Koul
2015-10-07 15:06   ` Applied "ASoC: Intel: Skylake: add DSP platform widget event handlers" to the asoc tree Mark Brown
2015-10-07 10:31 ` Vinod Koul [this message]
2015-10-07 15:06   ` Applied "ASoC: Intel: Skylake: Add FE and BE hw_params handling" " Mark Brown
2015-10-07 10:31 ` [PATCH v4 5/8] ASoC: Intel: Skylake: Add topology core init and handlers Vinod Koul
2015-10-07 14:28   ` Mark Brown
2015-10-07 14:37     ` Koul, Vinod
2015-10-07 10:31 ` [PATCH v4 6/8] ASoC: Intel: Skylake: Initialize and load DSP controls Vinod Koul
2015-10-07 15:05   ` Applied "ASoC: Intel: Skylake: Initialize and load DSP controls" to the asoc tree Mark Brown
2015-10-07 10:31 ` [PATCH v4 7/8] ASoC: Intel: Skylake: Add DSP support and enable it Vinod Koul
2015-10-07 10:31 ` [PATCH v4 8/8] ASoC: Intel: Skylake: Initialize NHLT table Vinod Koul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1444213919-32369-5-git-send-email-vinod.koul@intel.com \
    --to=vinod.koul@intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=jeeja.kp@intel.com \
    --cc=liam.r.girdwood@linux.intel.com \
    --cc=patches.audio@intel.com \
    --cc=subhransu.s.prusty@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).