aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMengdong Lin <mengdong.lin@intel.com>2015-08-05 09:41:13 -0400
committerMark Brown <broonie@kernel.org>2015-08-06 07:34:46 -0400
commit28a87eebcad40101b1b273cbd4f2a02c104f9367 (patch)
tree09e5be519de6b8f9f19d3ce3122678dfa5560f89
parent113adf21cf1ed49b57098c1d0d6b38ffbe9ea1e6 (diff)
ASoC: topology: Update TLV support so we can support more TLV types
Currently the TLV topology structure is targeted at only supporting the DB scale data. This patch extends support for the other TLV types so they can be easily added at a later stage. TLV structure is moved to common topology control header since it's a common field for controls and can be processed in a general way. Users must set a proper access flag for a control since it's used to decide if the TLV field is valid and if a TLV callback is needed. Removed the following fields from topology TLV struct: - size/count: type can decide the size. - numid: not needed to initialize TLV for kcontrol. - data: replaced by the type specific struct. Added TLV structure to generic control header and removed TLV structure from mixer control. Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--include/uapi/sound/asoc.h19
-rw-r--r--sound/soc/soc-topology.c58
2 files changed, 54 insertions, 23 deletions
diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h
index 2819fc1f8458..aa3a79b42438 100644
--- a/include/uapi/sound/asoc.h
+++ b/include/uapi/sound/asoc.h
@@ -137,11 +137,19 @@ struct snd_soc_tplg_private {
137/* 137/*
138 * Kcontrol TLV data. 138 * Kcontrol TLV data.
139 */ 139 */
140struct snd_soc_tplg_tlv_dbscale {
141 __le32 min;
142 __le32 step;
143 __le32 mute;
144} __attribute__((packed));
145
140struct snd_soc_tplg_ctl_tlv { 146struct snd_soc_tplg_ctl_tlv {
141 __le32 size; /* in bytes aligned to 4 */ 147 __le32 size; /* in bytes of this structure */
142 __le32 numid; /* control element numeric identification */ 148 __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */
143 __le32 count; /* number of elem in data array */ 149 union {
144 __le32 data[SND_SOC_TPLG_TLV_SIZE]; 150 __le32 data[SND_SOC_TPLG_TLV_SIZE];
151 struct snd_soc_tplg_tlv_dbscale scale;
152 };
145} __attribute__((packed)); 153} __attribute__((packed));
146 154
147/* 155/*
@@ -172,7 +180,7 @@ struct snd_soc_tplg_ctl_hdr {
172 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; 180 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
173 __le32 access; 181 __le32 access;
174 struct snd_soc_tplg_kcontrol_ops_id ops; 182 struct snd_soc_tplg_kcontrol_ops_id ops;
175 __le32 tlv_size; /* non zero means control has TLV data */ 183 struct snd_soc_tplg_ctl_tlv tlv;
176} __attribute__((packed)); 184} __attribute__((packed));
177 185
178/* 186/*
@@ -260,7 +268,6 @@ struct snd_soc_tplg_mixer_control {
260 __le32 invert; 268 __le32 invert;
261 __le32 num_channels; 269 __le32 num_channels;
262 struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN]; 270 struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
263 struct snd_soc_tplg_ctl_tlv tlv;
264 struct snd_soc_tplg_private priv; 271 struct snd_soc_tplg_private priv;
265} __attribute__((packed)); 272} __attribute__((packed));
266 273
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 2c70f30d2d78..31068b8f3db0 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -33,6 +33,7 @@
33#include <sound/soc.h> 33#include <sound/soc.h>
34#include <sound/soc-dapm.h> 34#include <sound/soc-dapm.h>
35#include <sound/soc-topology.h> 35#include <sound/soc-topology.h>
36#include <sound/tlv.h>
36 37
37/* 38/*
38 * We make several passes over the data (since it wont necessarily be ordered) 39 * We make several passes over the data (since it wont necessarily be ordered)
@@ -579,28 +580,51 @@ static int soc_tplg_init_kcontrol(struct soc_tplg *tplg,
579 return 0; 580 return 0;
580} 581}
581 582
583
584static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg,
585 struct snd_kcontrol_new *kc, struct snd_soc_tplg_tlv_dbscale *scale)
586{
587 unsigned int item_len = 2 * sizeof(unsigned int);
588 unsigned int *p;
589
590 p = kzalloc(item_len + 2 * sizeof(unsigned int), GFP_KERNEL);
591 if (!p)
592 return -ENOMEM;
593
594 p[0] = SNDRV_CTL_TLVT_DB_SCALE;
595 p[1] = item_len;
596 p[2] = scale->min;
597 p[3] = (scale->step & TLV_DB_SCALE_MASK)
598 | (scale->mute ? TLV_DB_SCALE_MUTE : 0);
599
600 kc->tlv.p = (void *)p;
601 return 0;
602}
603
582static int soc_tplg_create_tlv(struct soc_tplg *tplg, 604static int soc_tplg_create_tlv(struct soc_tplg *tplg,
583 struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_tlv *tplg_tlv) 605 struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc)
584{ 606{
585 struct snd_ctl_tlv *tlv; 607 struct snd_soc_tplg_ctl_tlv *tplg_tlv;
586 int size;
587 608
588 if (tplg_tlv->count == 0) 609 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
589 return 0; 610 return 0;
590 611
591 size = ((tplg_tlv->count + (sizeof(unsigned int) - 1)) & 612 if (tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
592 ~(sizeof(unsigned int) - 1)); 613 kc->tlv.c = snd_soc_bytes_tlv_callback;
593 tlv = kzalloc(sizeof(*tlv) + size, GFP_KERNEL); 614 } else {
594 if (tlv == NULL) 615 tplg_tlv = &tc->tlv;
595 return -ENOMEM; 616 switch (tplg_tlv->type) {
596 617 case SNDRV_CTL_TLVT_DB_SCALE:
597 dev_dbg(tplg->dev, " created TLV type %d size %d bytes\n", 618 return soc_tplg_create_tlv_db_scale(tplg, kc,
598 tplg_tlv->numid, size); 619 &tplg_tlv->scale);
599 620
600 tlv->numid = tplg_tlv->numid; 621 /* TODO: add support for other TLV types */
601 tlv->length = size; 622 default:
602 memcpy(&tlv->tlv[0], tplg_tlv->data, size); 623 dev_dbg(tplg->dev, "Unsupported TLV type %d\n",
603 kc->tlv.p = (void *)tlv; 624 tplg_tlv->type);
625 return -EINVAL;
626 }
627 }
604 628
605 return 0; 629 return 0;
606} 630}
@@ -772,7 +796,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count,
772 } 796 }
773 797
774 /* create any TLV data */ 798 /* create any TLV data */
775 soc_tplg_create_tlv(tplg, &kc, &mc->tlv); 799 soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
776 800
777 /* register control here */ 801 /* register control here */
778 err = soc_tplg_add_kcontrol(tplg, &kc, 802 err = soc_tplg_add_kcontrol(tplg, &kc,