mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-02 02:34:05 +08:00
ASoC: core: Add single controls with specified range of values
Control type added for cases where a specific range of values within a register are required for control. Added convenience macros: SOC_SINGLE_RANGE SOC_SINGLE_RANGE_TLV Added accessor implementations: snd_soc_info_volsw_range snd_soc_put_volsw_range snd_soc_get_volsw_range Signed-off-by: Michal Hajduk <Michal.Hajduk@diasemi.com> Signed-off-by: Adam Thomson <Adam.Thomson@diasemi.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
bc92657a11
commit
6c9d8cf637
@ -47,6 +47,13 @@
|
|||||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
|
||||||
.put = snd_soc_put_volsw, \
|
.put = snd_soc_put_volsw, \
|
||||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
|
||||||
|
#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
|
||||||
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||||
|
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
|
||||||
|
.put = snd_soc_put_volsw_range, \
|
||||||
|
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||||
|
{.reg = xreg, .shift = xshift, .min = xmin,\
|
||||||
|
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||||
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||||
@ -67,6 +74,16 @@
|
|||||||
{.reg = xreg, .rreg = xreg, \
|
{.reg = xreg, .rreg = xreg, \
|
||||||
.shift = xshift, .rshift = xshift, \
|
.shift = xshift, .rshift = xshift, \
|
||||||
.max = xmax, .min = xmin} }
|
.max = xmax, .min = xmin} }
|
||||||
|
#define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, xinvert, tlv_array) \
|
||||||
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||||
|
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||||
|
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||||
|
.tlv.p = (tlv_array), \
|
||||||
|
.info = snd_soc_info_volsw_range, \
|
||||||
|
.get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
|
||||||
|
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||||
|
{.reg = xreg, .shift = xshift, .min = xmin,\
|
||||||
|
.max = xmax, .platform_max = xmax, .invert = xinvert} }
|
||||||
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
|
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
|
||||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
|
||||||
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
|
||||||
@ -460,6 +477,12 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
|
|||||||
struct snd_ctl_elem_value *ucontrol);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
|
int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
|
int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo);
|
||||||
|
int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
|
int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
int snd_soc_limit_volume(struct snd_soc_codec *codec,
|
int snd_soc_limit_volume(struct snd_soc_codec *codec,
|
||||||
const char *name, int max);
|
const char *name, int max);
|
||||||
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
|
int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
|
||||||
|
@ -2791,6 +2791,104 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
|
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_soc_info_volsw_range - single mixer info callback with range.
|
||||||
|
* @kcontrol: mixer control
|
||||||
|
* @uinfo: control element information
|
||||||
|
*
|
||||||
|
* Callback to provide information, within a range, about a single
|
||||||
|
* mixer control.
|
||||||
|
*
|
||||||
|
* returns 0 for success.
|
||||||
|
*/
|
||||||
|
int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_info *uinfo)
|
||||||
|
{
|
||||||
|
struct soc_mixer_control *mc =
|
||||||
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
int platform_max;
|
||||||
|
int min = mc->min;
|
||||||
|
|
||||||
|
if (!mc->platform_max)
|
||||||
|
mc->platform_max = mc->max;
|
||||||
|
platform_max = mc->platform_max;
|
||||||
|
|
||||||
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||||
|
uinfo->count = 1;
|
||||||
|
uinfo->value.integer.min = 0;
|
||||||
|
uinfo->value.integer.max = platform_max - min;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_soc_put_volsw_range - single mixer put value callback with range.
|
||||||
|
* @kcontrol: mixer control
|
||||||
|
* @ucontrol: control element information
|
||||||
|
*
|
||||||
|
* Callback to set the value, within a range, for a single mixer control.
|
||||||
|
*
|
||||||
|
* Returns 0 for success.
|
||||||
|
*/
|
||||||
|
int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct soc_mixer_control *mc =
|
||||||
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
unsigned int reg = mc->reg;
|
||||||
|
unsigned int shift = mc->shift;
|
||||||
|
int min = mc->min;
|
||||||
|
int max = mc->max;
|
||||||
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
|
unsigned int invert = mc->invert;
|
||||||
|
unsigned int val, val_mask;
|
||||||
|
|
||||||
|
val = ((ucontrol->value.integer.value[0] + min) & mask);
|
||||||
|
if (invert)
|
||||||
|
val = max - val;
|
||||||
|
val_mask = mask << shift;
|
||||||
|
val = val << shift;
|
||||||
|
|
||||||
|
return snd_soc_update_bits_locked(codec, reg, val_mask, val);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snd_soc_get_volsw_range - single mixer get callback with range
|
||||||
|
* @kcontrol: mixer control
|
||||||
|
* @ucontrol: control element information
|
||||||
|
*
|
||||||
|
* Callback to get the value, within a range, of a single mixer control.
|
||||||
|
*
|
||||||
|
* Returns 0 for success.
|
||||||
|
*/
|
||||||
|
int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct soc_mixer_control *mc =
|
||||||
|
(struct soc_mixer_control *)kcontrol->private_value;
|
||||||
|
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||||
|
unsigned int reg = mc->reg;
|
||||||
|
unsigned int shift = mc->shift;
|
||||||
|
int min = mc->min;
|
||||||
|
int max = mc->max;
|
||||||
|
unsigned int mask = (1 << fls(max)) - 1;
|
||||||
|
unsigned int invert = mc->invert;
|
||||||
|
|
||||||
|
ucontrol->value.integer.value[0] =
|
||||||
|
(snd_soc_read(codec, reg) >> shift) & mask;
|
||||||
|
if (invert)
|
||||||
|
ucontrol->value.integer.value[0] =
|
||||||
|
max - ucontrol->value.integer.value[0];
|
||||||
|
ucontrol->value.integer.value[0] =
|
||||||
|
ucontrol->value.integer.value[0] - min;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_soc_limit_volume - Set new limit to an existing volume control.
|
* snd_soc_limit_volume - Set new limit to an existing volume control.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user