Commit 4c1c16d9 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/topology' into asoc-next

parents 463f7e50 8ea41674
...@@ -116,6 +116,14 @@ ...@@ -116,6 +116,14 @@
#define SND_SOC_TPLG_STREAM_PLAYBACK 0 #define SND_SOC_TPLG_STREAM_PLAYBACK 0
#define SND_SOC_TPLG_STREAM_CAPTURE 1 #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. * Block Header.
* This header precedes all object and object arrays below. * This header precedes all object and object arrays below.
...@@ -132,6 +140,35 @@ struct snd_soc_tplg_hdr { ...@@ -132,6 +140,35 @@ struct snd_soc_tplg_hdr {
__le32 count; /* number of elements in block */ __le32 count; /* number of elements in block */
} __attribute__((packed)); } __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. * Private data.
* All topology objects may have private data that can be used by the driver or * All topology objects may have private data that can be used by the driver or
...@@ -139,7 +176,10 @@ struct snd_soc_tplg_hdr { ...@@ -139,7 +176,10 @@ struct snd_soc_tplg_hdr {
*/ */
struct snd_soc_tplg_private { struct snd_soc_tplg_private {
__le32 size; /* in bytes of private data */ __le32 size; /* in bytes of private data */
char data[0]; union {
char data[0];
struct snd_soc_tplg_vendor_array array[0];
};
} __attribute__((packed)); } __attribute__((packed));
/* /*
...@@ -383,7 +423,7 @@ struct snd_soc_tplg_pcm { ...@@ -383,7 +423,7 @@ struct snd_soc_tplg_pcm {
__le32 size; /* in bytes of this structure */ __le32 size; /* in bytes of this structure */
char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
char dai_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 dai_id; /* unique ID - used to match */
__le32 playback; /* supports playback mode */ __le32 playback; /* supports playback mode */
__le32 capture; /* supports capture mode */ __le32 capture; /* supports capture mode */
......
...@@ -1023,6 +1023,11 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, ...@@ -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; 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) { switch (control_hdr->ops.info) {
case SND_SOC_TPLG_CTL_VOLSW: case SND_SOC_TPLG_CTL_VOLSW:
case SND_SOC_TPLG_CTL_STROBE: case SND_SOC_TPLG_CTL_STROBE:
...@@ -1476,6 +1481,8 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, ...@@ -1476,6 +1481,8 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
widget->dobj.type = SND_SOC_DOBJ_WIDGET; widget->dobj.type = SND_SOC_DOBJ_WIDGET;
widget->dobj.ops = tplg->ops; widget->dobj.ops = tplg->ops;
widget->dobj.index = tplg->index; widget->dobj.index = tplg->index;
kfree(template.sname);
kfree(template.name);
list_add(&widget->dobj.list, &tplg->comp->dobj_list); list_add(&widget->dobj.list, &tplg->comp->dobj_list);
return 0; return 0;
...@@ -1499,10 +1506,17 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, ...@@ -1499,10 +1506,17 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; 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); 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", dev_err(tplg->dev, "ASoC: failed to load widget %s\n",
widget->name); widget->name);
return ret;
}
} }
return 0; return 0;
...@@ -1586,6 +1600,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, ...@@ -1586,6 +1600,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
return snd_soc_register_dai(tplg->comp, dai_drv); return snd_soc_register_dai(tplg->comp, dai_drv);
} }
/* create the FE DAI link */
static int soc_tplg_link_create(struct soc_tplg *tplg, static int soc_tplg_link_create(struct soc_tplg *tplg,
struct snd_soc_tplg_pcm *pcm) struct snd_soc_tplg_pcm *pcm)
{ {
...@@ -1598,6 +1613,16 @@ static int soc_tplg_link_create(struct soc_tplg *tplg, ...@@ -1598,6 +1613,16 @@ static int soc_tplg_link_create(struct soc_tplg *tplg,
link->name = pcm->pcm_name; link->name = pcm->pcm_name;
link->stream_name = pcm->pcm_name; 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 */ /* pass control to component driver for optional further init */
ret = soc_tplg_dai_link_load(tplg, link); ret = soc_tplg_dai_link_load(tplg, link);
...@@ -1639,8 +1664,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, ...@@ -1639,8 +1664,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) if (tplg->pass != SOC_TPLG_PASS_PCM_DAI)
return 0; return 0;
pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
if (soc_tplg_check_elem_count(tplg, if (soc_tplg_check_elem_count(tplg,
sizeof(struct snd_soc_tplg_pcm), count, sizeof(struct snd_soc_tplg_pcm), count,
hdr->payload_size, "PCM DAI")) { hdr->payload_size, "PCM DAI")) {
...@@ -1650,7 +1673,13 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, ...@@ -1650,7 +1673,13 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
} }
/* create the FE DAIs and DAI links */ /* create the FE DAIs and DAI links */
pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
for (i = 0; i < count; i++) { 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); soc_tplg_pcm_create(tplg, pcm);
pcm++; pcm++;
} }
...@@ -1670,6 +1699,11 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, ...@@ -1670,6 +1699,11 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg,
return 0; return 0;
manifest = (struct snd_soc_tplg_manifest *)tplg->pos; 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); tplg->pos += sizeof(struct snd_soc_tplg_manifest);
if (tplg->comp && tplg->ops && tplg->ops->manifest) if (tplg->comp && tplg->ops && tplg->ops->manifest)
...@@ -1686,6 +1720,14 @@ static int soc_valid_header(struct soc_tplg *tplg, ...@@ -1686,6 +1720,14 @@ static int soc_valid_header(struct soc_tplg *tplg,
if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
return 0; 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 */ /* big endian firmware objects not supported atm */
if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) { if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) {
dev_err(tplg->dev, dev_err(tplg->dev,
......
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