From: mengdong.lin@linux.intel.com
To: alsa-devel@alsa-project.org, broonie@kernel.org
Cc: Mengdong Lin <mengdong.lin@linux.intel.com>,
tiwai@suse.de, hardik.t.shah@intel.com,
guneshwor.o.singh@intel.com, liam.r.girdwood@linux.intel.com,
vinod.koul@intel.com, rakesh.a.ughreja@intel.com,
mengdong.lin@intel.com
Subject: [PATCH v7 07/11] ASoC: topology: Add support to configure existing physical DAI links
Date: Thu, 3 Nov 2016 01:04:27 +0800 [thread overview]
Message-ID: <6bc394d703dcaf3afbb8bf35c8dc983360fc7cd0.1478071138.git.mengdong.lin@linux.intel.com> (raw)
In-Reply-To: <cover.1478071138.git.mengdong.lin@linux.intel.com>
From: Mengdong Lin <mengdong.lin@linux.intel.com>
Topology will find an existing physical link (including BE link for
DPCM) by checking its ID, name and stream name, and configure its physical
audio format and flags.
This support is backward compatible for old ABI v4.
Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 8baa176..b15a204 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -49,9 +49,10 @@
#define SOC_TPLG_PASS_GRAPH 5
#define SOC_TPLG_PASS_PINS 6
#define SOC_TPLG_PASS_BE_DAI 7
+#define SOC_TPLG_PASS_LINK 8
#define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST
-#define SOC_TPLG_PASS_END SOC_TPLG_PASS_BE_DAI
+#define SOC_TPLG_PASS_END SOC_TPLG_PASS_LINK
/*
* Old version of ABI structs, supported for backward compatibility.
@@ -101,6 +102,14 @@ struct snd_soc_tplg_pcm_v4 {
struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */
} __packed;
+/* Physical link config v4 */
+struct snd_soc_tplg_link_config_v4 {
+ __le32 size; /* in bytes of this structure */
+ __le32 id; /* unique ID - used to match */
+ struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
+ __le32 num_streams; /* number of streams */
+} __packed;
+
/* topology context */
struct soc_tplg {
const struct firmware *fw;
@@ -1868,7 +1877,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
/* create the FE DAIs and DAI links */
soc_tplg_pcm_create(tplg, _pcm);
-
/* offset by version-specific struct size and
* real priv data size
*/
@@ -1883,6 +1891,196 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
return 0;
}
+/**
+ * set_link_hw_format - Set the HW audio format of the physical DAI link.
+ * @tplg: topology context
+ * @cfg: physical link configs.
+ *
+ * Topology context contains a list of supported HW formats (configs) and
+ * a default format ID for the physical link. This function will use this
+ * default ID to choose the HW format to set the link's DAI format for init.
+ */
+static void set_link_hw_format(struct snd_soc_dai_link *link,
+ struct snd_soc_tplg_link_config *cfg)
+{
+ struct snd_soc_tplg_hw_config *hw_config;
+ unsigned char bclk_master, fsync_master;
+ unsigned char invert_bclk, invert_fsync;
+ int i;
+
+ for (i = 0; i < cfg->num_hw_configs; i++) {
+ hw_config = &cfg->hw_config[i];
+ if (hw_config->id != cfg->default_hw_config_id)
+ continue;
+
+ link->dai_fmt = hw_config->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+ /* clock signal polarity */
+ invert_bclk = hw_config->invert_bclk;
+ invert_fsync = hw_config->invert_fsync;
+ if (!invert_bclk && !invert_fsync)
+ link->dai_fmt |= SND_SOC_DAIFMT_NB_NF;
+ else if (!invert_bclk && invert_fsync)
+ link->dai_fmt |= SND_SOC_DAIFMT_NB_IF;
+ else if (invert_bclk && !invert_fsync)
+ link->dai_fmt |= SND_SOC_DAIFMT_IB_NF;
+ else
+ link->dai_fmt |= SND_SOC_DAIFMT_IB_IF;
+
+ /* clock masters */
+ bclk_master = hw_config->bclk_master;
+ fsync_master = hw_config->fsync_master;
+ if (!bclk_master && !fsync_master)
+ link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
+ else if (bclk_master && !fsync_master)
+ link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
+ else if (!bclk_master && fsync_master)
+ link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
+ else
+ link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
+ }
+}
+
+/**
+ * link_new_ver - Create a new physical link config from the old
+ * version of source.
+ * @toplogy: topology context
+ * @src: old version of phyical link config as a source
+ * @link: latest version of physical link config created from the source
+ *
+ * Support from vesion 4. User need free the returned link config manually.
+ */
+static int link_new_ver(struct soc_tplg *tplg,
+ struct snd_soc_tplg_link_config *src,
+ struct snd_soc_tplg_link_config **link)
+{
+ struct snd_soc_tplg_link_config *dest;
+ struct snd_soc_tplg_link_config_v4 *src_v4;
+ int i;
+
+ *link = NULL;
+
+ if (src->size != sizeof(struct snd_soc_tplg_link_config_v4)) {
+ dev_err(tplg->dev, "ASoC: invalid physical link config size\n");
+ return -EINVAL;
+ }
+
+ dev_warn(tplg->dev, "ASoC: old version of physical link config\n");
+
+ src_v4 = (struct snd_soc_tplg_link_config_v4 *)src;
+ dest = kzalloc(sizeof(*dest), GFP_KERNEL);
+ if (!dest)
+ return -ENOMEM;
+
+ dest->size = sizeof(*dest);
+ dest->id = src_v4->id;
+ dest->num_streams = src_v4->num_streams;
+ for (i = 0; i < dest->num_streams; i++)
+ memcpy(&dest->stream[i], &src_v4->stream[i],
+ sizeof(struct snd_soc_tplg_stream));
+
+ *link = dest;
+ return 0;
+}
+
+/* Find and configure an existing physical DAI link */
+static int soc_tplg_link_config(struct soc_tplg *tplg,
+ struct snd_soc_tplg_link_config *cfg)
+{
+ struct snd_soc_dai_link *link;
+ const char *name, *stream_name;
+ int ret;
+
+ name = strlen(cfg->name) ? cfg->name : NULL;
+ stream_name = strlen(cfg->stream_name) ? cfg->stream_name : NULL;
+
+ link = snd_soc_find_dai_link(tplg->comp->card, cfg->id,
+ name, stream_name);
+ if (!link) {
+ dev_err(tplg->dev, "ASoC: physical link %s (id %d) not exist\n",
+ name, cfg->id);
+ return -EINVAL;
+ }
+
+ /* hw format */
+ if (cfg->num_hw_configs)
+ set_link_hw_format(link, cfg);
+
+ /* flags */
+ if (cfg->flag_mask)
+ set_link_flags(link, cfg->flag_mask, cfg->flags);
+
+ /* pass control to component driver for optional further init */
+ ret = soc_tplg_dai_link_load(tplg, link);
+ if (ret < 0) {
+ dev_err(tplg->dev, "ASoC: physical link loading failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+/* Load physical link config elements from the topology context */
+static int soc_tplg_link_elems_load(struct soc_tplg *tplg,
+ struct snd_soc_tplg_hdr *hdr)
+{
+ struct snd_soc_tplg_link_config *link, *_link;
+ int count = hdr->count;
+ int i, ret;
+ bool abi_match;
+
+ if (tplg->pass != SOC_TPLG_PASS_LINK) {
+ tplg->pos += hdr->size + hdr->payload_size;
+ return 0;
+ };
+
+ /* check the element size and count */
+ link = (struct snd_soc_tplg_link_config *)tplg->pos;
+ if (link->size > sizeof(struct snd_soc_tplg_link_config)
+ || link->size < sizeof(struct snd_soc_tplg_link_config_v4)) {
+ dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n",
+ link->size);
+ return -EINVAL;
+ }
+
+ if (soc_tplg_check_elem_count(tplg,
+ link->size, count,
+ hdr->payload_size, "physical link config")) {
+ dev_err(tplg->dev, "ASoC: invalid count %d for physical link elems\n",
+ count);
+ return -EINVAL;
+ }
+
+ /* config physical DAI links */
+ for (i = 0; i < count; i++) {
+ link = (struct snd_soc_tplg_link_config *)tplg->pos;
+ if (link->size == sizeof(*link)) {
+ abi_match = true;
+ _link = link;
+ } else {
+ abi_match = false;
+ ret = link_new_ver(tplg, link, &_link);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = soc_tplg_link_config(tplg, _link);
+ if (ret < 0)
+ return ret;
+
+ /* offset by version-specific struct size and
+ * real priv data size
+ */
+ tplg->pos += link->size + _link->priv.size;
+
+ if (!abi_match)
+ kfree(_link); /* free the duplicated one */
+ }
+
+ return 0;
+}
+
/* *
* soc_tplg_be_dai_config - Find and configure an existing BE DAI.
* @tplg: topology context
@@ -2132,6 +2330,10 @@ static int soc_tplg_load_header(struct soc_tplg *tplg,
return soc_tplg_pcm_elems_load(tplg, hdr);
case SND_SOC_TPLG_TYPE_BE_DAI:
return soc_tplg_be_dai_elems_load(tplg, hdr);
+ case SND_SOC_TPLG_TYPE_DAI_LINK:
+ case SND_SOC_TPLG_TYPE_BACKEND_LINK:
+ /* physical link configurations */
+ return soc_tplg_link_elems_load(tplg, hdr);
case SND_SOC_TPLG_TYPE_MANIFEST:
return soc_tplg_manifest_load(tplg, hdr);
default:
--
2.7.4
next prev parent reply other threads:[~2016-11-02 17:03 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-02 16:59 [PATCH v7 00/11] ASoC: topology: Remaining kernel patches mengdong.lin
2016-11-02 17:00 ` [PATCH v7 01/11] ASoC: topology: Make PCM backward compatible from ABI v4 mengdong.lin
2016-11-03 16:12 ` Mark Brown
2016-11-03 16:23 ` Applied "ASoC: topology: Make PCM backward compatible from ABI v4" to the asoc tree Mark Brown
2016-11-02 17:02 ` [PATCH v7 02/11] ASoC: topology: Only use valid names of PCM for the kernel DAI & DAI link mengdong.lin
2016-11-03 16:55 ` Applied "ASoC: topology: Only use valid names of PCM for the kernel DAI & DAI link" to the asoc tree Mark Brown
2016-11-02 17:03 ` [PATCH v7 03/11] ASoC: topology: Support topology file of ABI v4 mengdong.lin
2016-11-02 17:03 ` [PATCH v7 04/11] ASoC: topology: ABI - Add flags and private data to PCM mengdong.lin
2016-11-03 16:55 ` Applied "ASoC: topology: ABI - Add flags and private data to PCM" to the asoc tree Mark Brown
2016-11-02 17:03 ` [PATCH v7 05/11] ASoC: topology: ABI - Update physical DAI link configuration for version 5 mengdong.lin
2016-11-02 17:04 ` [PATCH v7 06/11] ASoC: Define API to find a dai link mengdong.lin
2016-11-02 17:04 ` mengdong.lin [this message]
2016-11-04 17:22 ` [PATCH v7 07/11] ASoC: topology: Add support to configure existing physical DAI links Mark Brown
2016-11-05 13:35 ` Lin, Mengdong
2016-11-02 17:04 ` [PATCH v7 08/11] ASoC: topology: Rename the function to create a FE link mengdong.lin
2016-11-02 17:05 ` [PATCH v7 09/11] ASoC: topology: ABI - Rename struct and type for physical DAIs mengdong.lin
2016-11-02 17:05 ` [PATCH v7 10/11] ASoC: topology: Rename functions & variables " mengdong.lin
2016-11-02 17:05 ` [PATCH v7 11/11] ASoC: topology: ABI - Add voice wake up flag for DAI links mengdong.lin
2016-11-04 17:36 ` Mark Brown
2016-11-05 13:35 ` Lin, Mengdong
2016-11-04 17:38 ` Applied "ASoC: topology: ABI - Add voice wake up flag for DAI links" to the asoc tree Mark Brown
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=6bc394d703dcaf3afbb8bf35c8dc983360fc7cd0.1478071138.git.mengdong.lin@linux.intel.com \
--to=mengdong.lin@linux.intel.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=guneshwor.o.singh@intel.com \
--cc=hardik.t.shah@intel.com \
--cc=liam.r.girdwood@linux.intel.com \
--cc=mengdong.lin@intel.com \
--cc=rakesh.a.ughreja@intel.com \
--cc=tiwai@suse.de \
--cc=vinod.koul@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).