ASoC: Add SOC_DOUBLE_R_SX_TLV control
This patch is adding a new control which has the following capabilities: - tlv - variable data size (for instance, 7 ou 8 bit) - double mixer - data range centered around 0 Signed-off-by: Arnaud Patard <apatard@mandriva.com> Acked-by: Liam Girdwood <lrg@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
6a2f1ee1f9
commit
b6f4bb383d
2 changed files with 116 additions and 0 deletions
|
@ -170,6 +170,21 @@
|
|||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
|
||||
#define SOC_DOUBLE_R_SX_TLV(xname, xreg_left, xreg_right, xshift,\
|
||||
xmin, xmax, 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_2r_sx, \
|
||||
.get = snd_soc_get_volsw_2r_sx, \
|
||||
.put = snd_soc_put_volsw_2r_sx, \
|
||||
.private_value = (unsigned long)&(struct soc_mixer_control) \
|
||||
{.reg = xreg_left, \
|
||||
.rreg = xreg_right, .shift = xshift, \
|
||||
.min = xmin, .max = xmax} }
|
||||
|
||||
|
||||
/*
|
||||
* Simplified versions of above macros, declaring a struct and calculating
|
||||
* ARRAY_SIZE internally
|
||||
|
@ -329,6 +344,12 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_limit_volume(struct snd_soc_codec *codec,
|
||||
const char *name, int max);
|
||||
int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
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);
|
||||
|
||||
/**
|
||||
* struct snd_soc_jack_pin - Describes a pin to update based on jack detection
|
||||
|
|
|
@ -2351,6 +2351,101 @@ int snd_soc_limit_volume(struct snd_soc_codec *codec,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_limit_volume);
|
||||
|
||||
/**
|
||||
* snd_soc_info_volsw_2r_sx - double with tlv and variable data size
|
||||
* mixer info callback
|
||||
* @kcontrol: mixer control
|
||||
* @uinfo: control element information
|
||||
*
|
||||
* Returns 0 for success.
|
||||
*/
|
||||
int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
int max = mc->max;
|
||||
int min = mc->min;
|
||||
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 2;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = max-min;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r_sx);
|
||||
|
||||
/**
|
||||
* snd_soc_get_volsw_2r_sx - double with tlv and variable data size
|
||||
* mixer get callback
|
||||
* @kcontrol: mixer control
|
||||
* @uinfo: control element information
|
||||
*
|
||||
* Returns 0 for success.
|
||||
*/
|
||||
int snd_soc_get_volsw_2r_sx(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 mask = (1<<mc->shift)-1;
|
||||
int min = mc->min;
|
||||
int val = snd_soc_read(codec, mc->reg) & mask;
|
||||
int valr = snd_soc_read(codec, mc->rreg) & mask;
|
||||
|
||||
ucontrol->value.integer.value[0] = ((val & 0xff)-min);
|
||||
ucontrol->value.integer.value[1] = ((valr & 0xff)-min);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r_sx);
|
||||
|
||||
/**
|
||||
* snd_soc_put_volsw_2r_sx - double with tlv and variable data size
|
||||
* mixer put callback
|
||||
* @kcontrol: mixer control
|
||||
* @uinfo: control element information
|
||||
*
|
||||
* Returns 0 for success.
|
||||
*/
|
||||
int snd_soc_put_volsw_2r_sx(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 mask = (1<<mc->shift)-1;
|
||||
int min = mc->min;
|
||||
int ret;
|
||||
unsigned int val, valr, oval, ovalr;
|
||||
|
||||
val = ((ucontrol->value.integer.value[0]+min) & 0xff);
|
||||
val &= mask;
|
||||
valr = ((ucontrol->value.integer.value[1]+min) & 0xff);
|
||||
valr &= mask;
|
||||
|
||||
oval = snd_soc_read(codec, mc->reg) & mask;
|
||||
ovalr = snd_soc_read(codec, mc->rreg) & mask;
|
||||
|
||||
ret = 0;
|
||||
if (oval != val) {
|
||||
ret = snd_soc_write(codec, mc->reg, val);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
ret = 1;
|
||||
}
|
||||
if (ovalr != valr) {
|
||||
ret = snd_soc_write(codec, mc->rreg, valr);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
|
||||
|
||||
/**
|
||||
* snd_soc_dai_set_sysclk - configure DAI system or master clock.
|
||||
* @dai: DAI
|
||||
|
|
Loading…
Reference in a new issue