summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMengdong Lin <mengdong.lin@intel.com>2015-08-18 18:12:20 +0800
committerMark Brown <broonie@kernel.org>2015-08-21 15:26:53 -0700
commit1a3232d2f61d2853a848464b7bde2d54960c58bb (patch)
treeb2f6daf4b73a6a8fe271f9c430ae27404c3fa0ab /sound/soc
parent2b5cdb9156f76162d5302e2847f84a79de8a3ad1 (diff)
downloadlinux-1a3232d2f61d2853a848464b7bde2d54960c58bb.tar.gz
linux-1a3232d2f61d2853a848464b7bde2d54960c58bb.tar.bz2
linux-1a3232d2f61d2853a848464b7bde2d54960c58bb.zip
ASoC: topology: Add support for TLV bytes controls
Allow vendor drivers to define bespoke bytes ext handlers and IDs for TLV bytes controls. And the topology core will bind these handlers by matching IDs defined by the vendor driver and user space topology data file. And TLV callback binding is moved to soc_tplg_kcontrol_bind_io(). This function process all handler binding now. Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/soc-topology.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index c4a58d7337b5..5690b7e7172e 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -70,6 +70,10 @@ struct soc_tplg {
const struct snd_soc_tplg_kcontrol_ops *io_ops;
int io_ops_count;
+ /* vendor specific bytes ext handlers, for TLV bytes controls */
+ const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops;
+ int bytes_ext_ops_count;
+
/* optional fw loading callbacks to component drivers */
struct snd_soc_tplg_ops *ops;
};
@@ -511,8 +515,40 @@ static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
const struct soc_tplg *tplg)
{
const struct snd_soc_tplg_kcontrol_ops *ops;
+ const struct snd_soc_tplg_bytes_ext_ops *ext_ops;
int num_ops, i;
+ if (hdr->ops.info == SND_SOC_TPLG_CTL_BYTES
+ && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER
+ && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
+ && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ struct soc_bytes_ext *sbe;
+ struct snd_soc_tplg_bytes_control *be;
+
+ sbe = (struct soc_bytes_ext *)k->private_value;
+ be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
+
+ /* TLV bytes controls need standard kcontrol info handler,
+ * TLV callback and extended put/get handlers.
+ */
+ k->info = snd_soc_bytes_info;
+ k->tlv.c = snd_soc_bytes_tlv_callback;
+
+ ext_ops = tplg->bytes_ext_ops;
+ num_ops = tplg->bytes_ext_ops_count;
+ for (i = 0; i < num_ops; i++) {
+ if (!sbe->put && ext_ops[i].id == be->ext_ops.put)
+ sbe->put = ext_ops[i].put;
+ if (!sbe->get && ext_ops[i].id == be->ext_ops.get)
+ sbe->get = ext_ops[i].get;
+ }
+
+ if (sbe->put && sbe->get)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
/* try and map vendor specific kcontrol handlers first */
ops = tplg->io_ops;
num_ops = tplg->io_ops_count;
@@ -613,9 +649,7 @@ static int soc_tplg_create_tlv(struct soc_tplg *tplg,
if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
return 0;
- if (tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
- kc->tlv.c = snd_soc_bytes_tlv_callback;
- } else {
+ if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
tplg_tlv = &tc->tlv;
switch (tplg_tlv->type) {
case SNDRV_CTL_TLVT_DB_SCALE:
@@ -1733,6 +1767,8 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
tplg.req_index = id;
tplg.io_ops = ops->io_ops;
tplg.io_ops_count = ops->io_ops_count;
+ tplg.bytes_ext_ops = ops->bytes_ext_ops;
+ tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
return soc_tplg_load(&tplg);
}