Commit 1a3232d2 authored by Mengdong Lin's avatar Mengdong Lin Committed by Mark Brown

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: default avatarMengdong Lin <mengdong.lin@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 2b5cdb91
......@@ -89,6 +89,13 @@ struct snd_soc_tplg_kcontrol_ops {
struct snd_ctl_elem_info *uinfo);
};
/* Bytes ext operations, for TLV byte controls */
struct snd_soc_tplg_bytes_ext_ops {
u32 id;
int (*get)(unsigned int __user *bytes, unsigned int size);
int (*put)(const unsigned int __user *bytes, unsigned int size);
};
/*
* DAPM widget event handlers - used to map handlers onto widgets.
*/
......@@ -139,6 +146,10 @@ struct snd_soc_tplg_ops {
/* vendor specific kcontrol handlers available for binding */
const struct snd_soc_tplg_kcontrol_ops *io_ops;
int io_ops_count;
/* vendor specific bytes ext handlers available for binding */
const struct snd_soc_tplg_bytes_ext_ops *bytes_ext_ops;
int bytes_ext_ops_count;
};
/* gets a pointer to data from the firmware block header */
......
......@@ -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);
}
......
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