aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2016-05-27 08:45:36 -0400
committerMark Brown <broonie@kernel.org>2016-05-27 08:45:36 -0400
commit4c1c16d9a90a7dc3e2a950f7a8629e85a7e114e6 (patch)
tree5134a37f1bd8e2e2514d0148d6ee625804f97dc7
parent463f7e504a8400f0cc9b814662739050540c1a9d (diff)
parent8ea416748bb04b7a778cb8d2fd5ec7fa51b9d521 (diff)
Merge remote-tracking branch 'asoc/topic/topology' into asoc-next
-rw-r--r--include/uapi/sound/asoc.h44
-rw-r--r--sound/soc/soc-topology.c48
2 files changed, 87 insertions, 5 deletions
diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h
index c4cc1e40b35c..e4701a3c6331 100644
--- a/include/uapi/sound/asoc.h
+++ b/include/uapi/sound/asoc.h
@@ -116,6 +116,14 @@
116#define SND_SOC_TPLG_STREAM_PLAYBACK 0 116#define SND_SOC_TPLG_STREAM_PLAYBACK 0
117#define SND_SOC_TPLG_STREAM_CAPTURE 1 117#define SND_SOC_TPLG_STREAM_CAPTURE 1
118 118
119/* vendor tuple types */
120#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0
121#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1
122#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2
123#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3
124#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4
125#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5
126
119/* 127/*
120 * Block Header. 128 * Block Header.
121 * This header precedes all object and object arrays below. 129 * This header precedes all object and object arrays below.
@@ -132,6 +140,35 @@ struct snd_soc_tplg_hdr {
132 __le32 count; /* number of elements in block */ 140 __le32 count; /* number of elements in block */
133} __attribute__((packed)); 141} __attribute__((packed));
134 142
143/* vendor tuple for uuid */
144struct snd_soc_tplg_vendor_uuid_elem {
145 __le32 token;
146 char uuid[16];
147} __attribute__((packed));
148
149/* vendor tuple for a bool/byte/short/word value */
150struct snd_soc_tplg_vendor_value_elem {
151 __le32 token;
152 __le32 value;
153} __attribute__((packed));
154
155/* vendor tuple for string */
156struct snd_soc_tplg_vendor_string_elem {
157 __le32 token;
158 char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
159} __attribute__((packed));
160
161struct snd_soc_tplg_vendor_array {
162 __le32 size; /* size in bytes of the array, including all elements */
163 __le32 type; /* SND_SOC_TPLG_TUPLE_TYPE_ */
164 __le32 num_elems; /* number of elements in array */
165 union {
166 struct snd_soc_tplg_vendor_uuid_elem uuid[0];
167 struct snd_soc_tplg_vendor_value_elem value[0];
168 struct snd_soc_tplg_vendor_string_elem string[0];
169 };
170} __attribute__((packed));
171
135/* 172/*
136 * Private data. 173 * Private data.
137 * All topology objects may have private data that can be used by the driver or 174 * 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 */ 176 */
140struct snd_soc_tplg_private { 177struct snd_soc_tplg_private {
141 __le32 size; /* in bytes of private data */ 178 __le32 size; /* in bytes of private data */
142 char data[0]; 179 union {
180 char data[0];
181 struct snd_soc_tplg_vendor_array array[0];
182 };
143} __attribute__((packed)); 183} __attribute__((packed));
144 184
145/* 185/*
@@ -383,7 +423,7 @@ struct snd_soc_tplg_pcm {
383 __le32 size; /* in bytes of this structure */ 423 __le32 size; /* in bytes of this structure */
384 char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 424 char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
385 char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 425 char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
386 __le32 pcm_id; /* unique ID - used to match */ 426 __le32 pcm_id; /* unique ID - used to match with DAI link */
387 __le32 dai_id; /* unique ID - used to match */ 427 __le32 dai_id; /* unique ID - used to match */
388 __le32 playback; /* supports playback mode */ 428 __le32 playback; /* supports playback mode */
389 __le32 capture; /* supports capture mode */ 429 __le32 capture; /* supports capture mode */
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 1cf94d7fb9f4..ee7f15aa46fc 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,
1023 1023
1024 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; 1024 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
1025 1025
1026 if (control_hdr->size != sizeof(*control_hdr)) {
1027 dev_err(tplg->dev, "ASoC: invalid control size\n");
1028 return -EINVAL;
1029 }
1030
1026 switch (control_hdr->ops.info) { 1031 switch (control_hdr->ops.info) {
1027 case SND_SOC_TPLG_CTL_VOLSW: 1032 case SND_SOC_TPLG_CTL_VOLSW:
1028 case SND_SOC_TPLG_CTL_STROBE: 1033 case SND_SOC_TPLG_CTL_STROBE:
@@ -1476,6 +1481,8 @@ widget:
1476 widget->dobj.type = SND_SOC_DOBJ_WIDGET; 1481 widget->dobj.type = SND_SOC_DOBJ_WIDGET;
1477 widget->dobj.ops = tplg->ops; 1482 widget->dobj.ops = tplg->ops;
1478 widget->dobj.index = tplg->index; 1483 widget->dobj.index = tplg->index;
1484 kfree(template.sname);
1485 kfree(template.name);
1479 list_add(&widget->dobj.list, &tplg->comp->dobj_list); 1486 list_add(&widget->dobj.list, &tplg->comp->dobj_list);
1480 return 0; 1487 return 0;
1481 1488
@@ -1499,10 +1506,17 @@ static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg,
1499 1506
1500 for (i = 0; i < count; i++) { 1507 for (i = 0; i < count; i++) {
1501 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; 1508 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
1509 if (widget->size != sizeof(*widget)) {
1510 dev_err(tplg->dev, "ASoC: invalid widget size\n");
1511 return -EINVAL;
1512 }
1513
1502 ret = soc_tplg_dapm_widget_create(tplg, widget); 1514 ret = soc_tplg_dapm_widget_create(tplg, widget);
1503 if (ret < 0) 1515 if (ret < 0) {
1504 dev_err(tplg->dev, "ASoC: failed to load widget %s\n", 1516 dev_err(tplg->dev, "ASoC: failed to load widget %s\n",
1505 widget->name); 1517 widget->name);
1518 return ret;
1519 }
1506 } 1520 }
1507 1521
1508 return 0; 1522 return 0;
@@ -1586,6 +1600,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
1586 return snd_soc_register_dai(tplg->comp, dai_drv); 1600 return snd_soc_register_dai(tplg->comp, dai_drv);
1587} 1601}
1588 1602
1603/* create the FE DAI link */
1589static int soc_tplg_link_create(struct soc_tplg *tplg, 1604static int soc_tplg_link_create(struct soc_tplg *tplg,
1590 struct snd_soc_tplg_pcm *pcm) 1605 struct snd_soc_tplg_pcm *pcm)
1591{ 1606{
@@ -1598,6 +1613,16 @@ static int soc_tplg_link_create(struct soc_tplg *tplg,
1598 1613
1599 link->name = pcm->pcm_name; 1614 link->name = pcm->pcm_name;
1600 link->stream_name = pcm->pcm_name; 1615 link->stream_name = pcm->pcm_name;
1616 link->id = pcm->pcm_id;
1617
1618 link->cpu_dai_name = pcm->dai_name;
1619 link->codec_name = "snd-soc-dummy";
1620 link->codec_dai_name = "snd-soc-dummy-dai";
1621
1622 /* enable DPCM */
1623 link->dynamic = 1;
1624 link->dpcm_playback = pcm->playback;
1625 link->dpcm_capture = pcm->capture;
1601 1626
1602 /* pass control to component driver for optional further init */ 1627 /* pass control to component driver for optional further init */
1603 ret = soc_tplg_dai_link_load(tplg, link); 1628 ret = soc_tplg_dai_link_load(tplg, link);
@@ -1639,8 +1664,6 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
1639 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) 1664 if (tplg->pass != SOC_TPLG_PASS_PCM_DAI)
1640 return 0; 1665 return 0;
1641 1666
1642 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
1643
1644 if (soc_tplg_check_elem_count(tplg, 1667 if (soc_tplg_check_elem_count(tplg,
1645 sizeof(struct snd_soc_tplg_pcm), count, 1668 sizeof(struct snd_soc_tplg_pcm), count,
1646 hdr->payload_size, "PCM DAI")) { 1669 hdr->payload_size, "PCM DAI")) {
@@ -1650,7 +1673,13 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
1650 } 1673 }
1651 1674
1652 /* create the FE DAIs and DAI links */ 1675 /* create the FE DAIs and DAI links */
1676 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
1653 for (i = 0; i < count; i++) { 1677 for (i = 0; i < count; i++) {
1678 if (pcm->size != sizeof(*pcm)) {
1679 dev_err(tplg->dev, "ASoC: invalid pcm size\n");
1680 return -EINVAL;
1681 }
1682
1654 soc_tplg_pcm_create(tplg, pcm); 1683 soc_tplg_pcm_create(tplg, pcm);
1655 pcm++; 1684 pcm++;
1656 } 1685 }
@@ -1670,6 +1699,11 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg,
1670 return 0; 1699 return 0;
1671 1700
1672 manifest = (struct snd_soc_tplg_manifest *)tplg->pos; 1701 manifest = (struct snd_soc_tplg_manifest *)tplg->pos;
1702 if (manifest->size != sizeof(*manifest)) {
1703 dev_err(tplg->dev, "ASoC: invalid manifest size\n");
1704 return -EINVAL;
1705 }
1706
1673 tplg->pos += sizeof(struct snd_soc_tplg_manifest); 1707 tplg->pos += sizeof(struct snd_soc_tplg_manifest);
1674 1708
1675 if (tplg->comp && tplg->ops && tplg->ops->manifest) 1709 if (tplg->comp && tplg->ops && tplg->ops->manifest)
@@ -1686,6 +1720,14 @@ static int soc_valid_header(struct soc_tplg *tplg,
1686 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) 1720 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
1687 return 0; 1721 return 0;
1688 1722
1723 if (hdr->size != sizeof(*hdr)) {
1724 dev_err(tplg->dev,
1725 "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",
1726 hdr->type, soc_tplg_get_hdr_offset(tplg),
1727 tplg->fw->size);
1728 return -EINVAL;
1729 }
1730
1689 /* big endian firmware objects not supported atm */ 1731 /* big endian firmware objects not supported atm */
1690 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) { 1732 if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) {
1691 dev_err(tplg->dev, 1733 dev_err(tplg->dev,