diff --git a/include/sound/soc.h b/include/sound/soc.h index 1e16d6e3f2a8..3e9cae001eab 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -185,6 +185,12 @@ .rreg = xreg_right, .shift = xshift, \ .min = xmin, .max = xmax} } +#define SND_SOC_BYTES(xname, xbase, xregs) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ + .put = snd_soc_bytes_put, .private_value = \ + ((unsigned long)&(struct soc_bytes) \ + {.base = xbase, .num_regs = xregs }) } /* * Simplified versions of above macros, declaring a struct and calculating @@ -413,6 +419,13 @@ int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo); +int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); + /** * struct snd_soc_reg_access - Describes whether a given register is @@ -888,6 +901,11 @@ struct soc_mixer_control { unsigned int reg, rreg, shift, rshift, invert; }; +struct soc_bytes { + int base; + int num_regs; +}; + /* enumerated kcontrol */ struct soc_enum { unsigned short reg; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3ca70594e242..a9786ab70504 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2736,6 +2736,55 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx); +int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_bytes *params = (void *)kcontrol->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = params->num_regs * codec->val_bytes; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_bytes_info); + +int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + int ret; + + if (codec->using_regmap) + ret = regmap_raw_read(codec->control_data, params->base, + ucontrol->value.bytes.data, + params->num_regs * codec->val_bytes); + else + ret = -EINVAL; + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_bytes_get); + +int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + int ret; + + if (codec->using_regmap) + ret = regmap_raw_write(codec->control_data, params->base, + ucontrol->value.bytes.data, + params->num_regs * codec->val_bytes); + else + ret = -EINVAL; + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_bytes_put); + /** * snd_soc_dai_set_sysclk - configure DAI system or master clock. * @dai: DAI