From e42839b012eb8179ed2e3571bfcd133fba5df154 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Thu, 24 Mar 2016 10:53:14 +0800 Subject: ASoC: topology: ABI - Define types for vendor tuples Tuples, a pair of token and value, can be used to define vendor specific data, for controls and widgets. This can avoid importing binary data blob from other files. Vendor specific tuple arrays will be embeded in the private data buffer of a control or widget object. To be backward compatible, union is used to define the tuple arrays in the existing private data ABI object 'struct snd_soc_tplg_private'. Vendors need to make sure the token values defined by the topology conf file match those defined by their driver. Now supported tuple types are uuid, string, bool, byte, short and word. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index c4cc1e4..db86b447 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -116,6 +116,14 @@ #define SND_SOC_TPLG_STREAM_PLAYBACK 0 #define SND_SOC_TPLG_STREAM_CAPTURE 1 +/* vendor tuple types */ +#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0 +#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1 +#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2 +#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3 +#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 +#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 + /* * Block Header. * This header precedes all object and object arrays below. @@ -132,6 +140,35 @@ struct snd_soc_tplg_hdr { __le32 count; /* number of elements in block */ } __attribute__((packed)); +/* vendor tuple for uuid */ +struct snd_soc_tplg_vendor_uuid_elem { + __le32 token; + char uuid[16]; +} __attribute__((packed)); + +/* vendor tuple for a bool/byte/short/word value */ +struct snd_soc_tplg_vendor_value_elem { + __le32 token; + __le32 value; +} __attribute__((packed)); + +/* vendor tuple for string */ +struct snd_soc_tplg_vendor_string_elem { + __le32 token; + char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; +} __attribute__((packed)); + +struct snd_soc_tplg_vendor_array { + __le32 size; /* size in bytes of the array, including all elements */ + __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */ + __le32 num_elems; /* number of elements in array */ + union { + struct snd_soc_tplg_vendor_uuid_elem uuid[0]; + struct snd_soc_tplg_vendor_value_elem value[0]; + struct snd_soc_tplg_vendor_string_elem string[0]; + }; +} __attribute__((packed)); + /* * Private data. * All topology objects may have private data that can be used by the driver or @@ -139,7 +176,10 @@ struct snd_soc_tplg_hdr { */ struct snd_soc_tplg_private { __le32 size; /* in bytes of private data */ - char data[0]; + union { + char data[0]; + struct snd_soc_tplg_vendor_array array[0]; + }; } __attribute__((packed)); /* -- cgit v0.10.2 From b84fff5afb16627a8973256992f3951ac3e90d84 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Tue, 19 Apr 2016 13:12:43 +0800 Subject: ASoC: topology: Set the link ID when creating a FE DAI link Topology will set the link's generic id when creating a FE link. Device drivers can check the id for link specific initialization. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index db86b447..e4701a3 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -423,7 +423,7 @@ struct snd_soc_tplg_pcm { __le32 size; /* in bytes of this structure */ char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - __le32 pcm_id; /* unique ID - used to match */ + __le32 pcm_id; /* unique ID - used to match with DAI link */ __le32 dai_id; /* unique ID - used to match */ __le32 playback; /* supports playback mode */ __le32 capture; /* supports capture mode */ diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 1cf94d7..bdbfcef 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1598,6 +1598,7 @@ static int soc_tplg_link_create(struct soc_tplg *tplg, link->name = pcm->pcm_name; link->stream_name = pcm->pcm_name; + link->id = pcm->pcm_id; /* pass control to component driver for optional further init */ ret = soc_tplg_dai_link_load(tplg, link); -- cgit v0.10.2 From 67d1c21e37301ca3cea3705951950ce21f2723e1 Mon Sep 17 00:00:00 2001 From: Guneshwor Singh Date: Tue, 19 Apr 2016 13:12:50 +0800 Subject: ASoC: topology: Set CPU DAI name and enable DPCM by default for FE link When creating a FE link, the cpu_dai_name will come from topology and dpcm will be enabled by default. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index bdbfcef..ca5f828 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1586,6 +1586,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, return snd_soc_register_dai(tplg->comp, dai_drv); } +/* create the FE DAI link */ static int soc_tplg_link_create(struct soc_tplg *tplg, struct snd_soc_tplg_pcm *pcm) { @@ -1600,6 +1601,15 @@ static int soc_tplg_link_create(struct soc_tplg *tplg, link->stream_name = pcm->pcm_name; link->id = pcm->pcm_id; + link->cpu_dai_name = pcm->dai_name; + link->codec_name = "snd-soc-dummy"; + link->codec_dai_name = "snd-soc-dummy-dai"; + + /* enable DPCM */ + link->dynamic = 1; + link->dpcm_playback = pcm->playback; + link->dpcm_capture = pcm->capture; + /* pass control to component driver for optional further init */ ret = soc_tplg_dai_link_load(tplg, link); if (ret < 0) { -- cgit v0.10.2 From 7de76b621f77aba456f594e4621eca2e94a146f3 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Wed, 27 Apr 2016 14:52:38 +0800 Subject: ASoC: topology: Check failure to create a widget Stop loading topology info if error happens when creating a widget. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index ca5f828..0224a64 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1500,9 +1500,11 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, for (i = 0; i < count; i++) { widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; ret = soc_tplg_dapm_widget_create(tplg, widget); - if (ret < 0) + if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to load widget %s\n", widget->name); + return ret; + } } return 0; -- cgit v0.10.2 From 06eb49f72fa57f5a49acdf9f4af84d2d326513b3 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Wed, 27 Apr 2016 14:52:56 +0800 Subject: ASoC: topology: Check size mismatch of ABI objects before parsing If size mismatch of manifest, ABI headers or elements is found, stop parsing topology info and return the error. New fields may be append to the tail of ABI objects which will cause object size to increase. If user space and kernel use different versions of ABI, size mismatch will be detected here. Signed-off-by: Mengdong Lin Signed-off-by: Mark Brown diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 0224a64..29ae3d3 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1023,6 +1023,11 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; + if (control_hdr->size != sizeof(*control_hdr)) { + dev_err(tplg->dev, "ASoC: invalid control size\n"); + return -EINVAL; + } + switch (control_hdr->ops.info) { case SND_SOC_TPLG_CTL_VOLSW: case SND_SOC_TPLG_CTL_STROBE: @@ -1499,6 +1504,11 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, for (i = 0; i < count; i++) { widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; + if (widget->size != sizeof(*widget)) { + dev_err(tplg->dev, "ASoC: invalid widget size\n"); + return -EINVAL; + } + ret = soc_tplg_dapm_widget_create(tplg, widget); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to load widget %s\n", @@ -1652,8 +1662,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) return 0; - pcm = (struct snd_soc_tplg_pcm *)tplg->pos; - if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_pcm), count, hdr->payload_size, "PCM DAI")) { @@ -1663,7 +1671,13 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, } /* create the FE DAIs and DAI links */ + pcm = (struct snd_soc_tplg_pcm *)tplg->pos; for (i = 0; i < count; i++) { + if (pcm->size != sizeof(*pcm)) { + dev_err(tplg->dev, "ASoC: invalid pcm size\n"); + return -EINVAL; + } + soc_tplg_pcm_create(tplg, pcm); pcm++; } @@ -1683,6 +1697,11 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, return 0; manifest = (struct snd_soc_tplg_manifest *)tplg->pos; + if (manifest->size != sizeof(*manifest)) { + dev_err(tplg->dev, "ASoC: invalid manifest size\n"); + return -EINVAL; + } + tplg->pos += sizeof(struct snd_soc_tplg_manifest); if (tplg->comp && tplg->ops && tplg->ops->manifest) @@ -1699,6 +1718,14 @@ static int soc_valid_header(struct soc_tplg *tplg, if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) return 0; + if (hdr->size != sizeof(*hdr)) { + dev_err(tplg->dev, + "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n", + hdr->type, soc_tplg_get_hdr_offset(tplg), + tplg->fw->size); + return -EINVAL; + } + /* big endian firmware objects not supported atm */ if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) { dev_err(tplg->dev, -- cgit v0.10.2 From 8ea416748bb04b7a778cb8d2fd5ec7fa51b9d521 Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Thu, 5 May 2016 11:19:18 +0530 Subject: ASoC: topology: Fix memory leak in widget creation name and sname allocated in widget create are not freed when creation is successful, so free them. Signed-off-by: Jeeja KP Signed-off-by: Vinod Koul Signed-off-by: Mark Brown diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 29ae3d3..ee7f15a 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1481,6 +1481,8 @@ widget: widget->dobj.type = SND_SOC_DOBJ_WIDGET; widget->dobj.ops = tplg->ops; widget->dobj.index = tplg->index; + kfree(template.sname); + kfree(template.name); list_add(&widget->dobj.list, &tplg->comp->dobj_list); return 0; -- cgit v0.10.2