Skip to content

Commit

Permalink
ASoC: Add SOC_DOUBLE_R_SX_TLV control
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
apatard@mandriva.com authored and Mark Brown committed May 16, 2010
1 parent 6a2f1ee commit b6f4bb3
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
21 changes: 21 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
95 changes: 95 additions & 0 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b6f4bb3

Please sign in to comment.