aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMengdong Lin <mengdong.lin@intel.com>2015-08-18 06:12:20 -0400
committerMark Brown <broonie@kernel.org>2015-08-21 18:26:53 -0400
commit1a3232d2f61d2853a848464b7bde2d54960c58bb (patch)
treeb2f6daf4b73a6a8fe271f9c430ae27404c3fa0ab
parent2b5cdb9156f76162d5302e2847f84a79de8a3ad1 (diff)
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>
-rw-r--r--include/sound/soc-topology.h11
-rw-r--r--sound/soc/soc-topology.c42
2 files changed, 50 insertions, 3 deletions
diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h
index a6541a1bc709..ea387ed8f98b 100644
--- a/include/sound/soc-topology.h
+++ b/include/sound/soc-topology.h
@@ -89,6 +89,13 @@ struct snd_soc_tplg_kcontrol_ops {
89 struct snd_ctl_elem_info *uinfo); 89 struct snd_ctl_elem_info *uinfo);
90}; 90};
91 91
92/* Bytes ext operations, for TLV byte controls */
93struct snd_soc_tplg_bytes_ext_ops {
94 u32 id;
95 int (*get)(unsigned int __user *bytes, unsigned int size);
96 int (*put)(const unsigned int __user *bytes, unsigned int size);
97};
98
92/* 99/*
93 * DAPM widget event handlers - used to map handlers onto widgets. 100 * DAPM widget event handlers - used to map handlers onto widgets.
94 */ 101 */
@@ -139,6 +146,10 @@ struct snd_soc_tplg_ops {
139 /* vendor specific kcontrol handlers available for binding */ 146 /* vendor specific kcontrol handlers available for binding */
140 const struct snd_soc_tplg_kcontrol_ops *io_ops; 147 const struct snd_soc_tplg_kcontrol_ops *io_ops;
141 int io_ops_count; 148 int io_ops_count;
149
150 /* vendor specific bytes ext handlers available for binding */
151 const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops;
152 int bytes_ext_ops_count;
142}; 153};
143 154
144/* gets a pointer to data from the firmware block header */ 155/* gets a pointer to data from the firmware block header */
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 {
70 const struct snd_soc_tplg_kcontrol_ops *io_ops; 70 const struct snd_soc_tplg_kcontrol_ops *io_ops;
71 int io_ops_count; 71 int io_ops_count;
72 72
73 /* vendor specific bytes ext handlers, for TLV bytes controls */
74 const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops;
75 int bytes_ext_ops_count;
76
73 /* optional fw loading callbacks to component drivers */ 77 /* optional fw loading callbacks to component drivers */
74 struct snd_soc_tplg_ops *ops; 78 struct snd_soc_tplg_ops *ops;
75}; 79};
@@ -511,8 +515,40 @@ static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
511 const struct soc_tplg *tplg) 515 const struct soc_tplg *tplg)
512{ 516{
513 const struct snd_soc_tplg_kcontrol_ops *ops; 517 const struct snd_soc_tplg_kcontrol_ops *ops;
518 const struct snd_soc_tplg_bytes_ext_ops *ext_ops;
514 int num_ops, i; 519 int num_ops, i;
515 520
521 if (hdr->ops.info == SND_SOC_TPLG_CTL_BYTES
522 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER
523 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
524 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
525 struct soc_bytes_ext *sbe;
526 struct snd_soc_tplg_bytes_control *be;
527
528 sbe = (struct soc_bytes_ext *)k->private_value;
529 be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr);
530
531 /* TLV bytes controls need standard kcontrol info handler,
532 * TLV callback and extended put/get handlers.
533 */
534 k->info = snd_soc_bytes_info;
535 k->tlv.c = snd_soc_bytes_tlv_callback;
536
537 ext_ops = tplg->bytes_ext_ops;
538 num_ops = tplg->bytes_ext_ops_count;
539 for (i = 0; i < num_ops; i++) {
540 if (!sbe->put && ext_ops[i].id == be->ext_ops.put)
541 sbe->put = ext_ops[i].put;
542 if (!sbe->get && ext_ops[i].id == be->ext_ops.get)
543 sbe->get = ext_ops[i].get;
544 }
545
546 if (sbe->put && sbe->get)
547 return 0;
548 else
549 return -EINVAL;
550 }
551
516 /* try and map vendor specific kcontrol handlers first */ 552 /* try and map vendor specific kcontrol handlers first */
517 ops = tplg->io_ops; 553 ops = tplg->io_ops;
518 num_ops = tplg->io_ops_count; 554 num_ops = tplg->io_ops_count;
@@ -613,9 +649,7 @@ static int soc_tplg_create_tlv(struct soc_tplg *tplg,
613 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)) 649 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
614 return 0; 650 return 0;
615 651
616 if (tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { 652 if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
617 kc->tlv.c = snd_soc_bytes_tlv_callback;
618 } else {
619 tplg_tlv = &tc->tlv; 653 tplg_tlv = &tc->tlv;
620 switch (tplg_tlv->type) { 654 switch (tplg_tlv->type) {
621 case SNDRV_CTL_TLVT_DB_SCALE: 655 case SNDRV_CTL_TLVT_DB_SCALE:
@@ -1733,6 +1767,8 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
1733 tplg.req_index = id; 1767 tplg.req_index = id;
1734 tplg.io_ops = ops->io_ops; 1768 tplg.io_ops = ops->io_ops;
1735 tplg.io_ops_count = ops->io_ops_count; 1769 tplg.io_ops_count = ops->io_ops_count;
1770 tplg.bytes_ext_ops = ops->bytes_ext_ops;
1771 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
1736 1772
1737 return soc_tplg_load(&tplg); 1773 return soc_tplg_load(&tplg);
1738} 1774}