Commit 7523a271 authored by Omair Mohammed Abdullah's avatar Omair Mohammed Abdullah Committed by Mark Brown

ASoC: core: add a helper for extended byte controls using TLV

ALSA supports arbitrary length TLVs for each kcontrol that can be used
to pass metadata about the control (e.g. volumes, enum information). The
same transport mechanism is now used for arbitrary length data by
defining a new helper.
Signed-off-by: default avatarOmair Mohammed Abdullah <omair.m.abdullah@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 0cea76f3
...@@ -270,7 +270,14 @@ ...@@ -270,7 +270,14 @@
.get = xhandler_get, .put = xhandler_put, \ .get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&(struct soc_bytes_ext) \ .private_value = (unsigned long)&(struct soc_bytes_ext) \
{.max = xcount} } {.max = xcount} }
#define SND_SOC_BYTES_TLV(xname, xcount, xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
.tlv.c = (snd_soc_bytes_tlv_callback), \
.info = snd_soc_info_bytes_ext, \
.private_value = (unsigned long)&(struct soc_bytes_ext) \
{.max = xcount, .get = xhandler_get, .put = xhandler_put, } }
#define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \ #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
xmin, xmax, xinvert) \ xmin, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
...@@ -552,6 +559,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, ...@@ -552,6 +559,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol); struct snd_ctl_elem_value *ucontrol);
int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *ucontrol); struct snd_ctl_elem_info *ucontrol);
int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv);
int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo); struct snd_ctl_elem_info *uinfo);
int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
...@@ -1119,6 +1128,9 @@ struct soc_bytes { ...@@ -1119,6 +1128,9 @@ struct soc_bytes {
struct soc_bytes_ext { struct soc_bytes_ext {
int max; int max;
/* used for TLV byte control */
int (*get)(unsigned int __user *bytes, unsigned int size);
int (*put)(const unsigned int __user *bytes, unsigned int size);
}; };
/* multi register control */ /* multi register control */
......
...@@ -3267,6 +3267,27 @@ int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, ...@@ -3267,6 +3267,27 @@ int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
} }
EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext);
int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv)
{
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
unsigned int count = size < params->max ? size : params->max;
int ret = -ENXIO;
switch (op_flag) {
case SNDRV_CTL_TLV_OP_READ:
if (params->get)
ret = params->get(tlv, count);
break;
case SNDRV_CTL_TLV_OP_WRITE:
if (params->put)
ret = params->put(tlv, count);
break;
}
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback);
/** /**
* snd_soc_info_xr_sx - signed multi register info callback * snd_soc_info_xr_sx - signed multi register info callback
* @kcontrol: mreg control * @kcontrol: mreg control
......
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