Commit a7a4ac86 authored by Philipp Zabel's avatar Philipp Zabel Committed by Jaroslav Kysela

[ALSA] ASoC TLV support

Add TLV support to ASoC.
Signed-off-by: default avatarPhilipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: default avatarLiam Girdwood <lg@opensource.wolfsonmicro.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 0b4d221b
...@@ -131,18 +131,34 @@ ...@@ -131,18 +131,34 @@
.shift = wshift, .invert = winvert} .shift = wshift, .invert = winvert}
/* dapm kcontrol types */ /* dapm kcontrol types */
#define SOC_DAPM_SINGLE(xname, reg, shift, mask, invert) \ #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \ .info = snd_soc_info_volsw, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) } .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
#define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, mask, invert, \ #define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, max, invert, \
power) \ power) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_volsw, \ .info = snd_soc_info_volsw, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\ .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
((mask) << 16) | ((invert) << 24) } ((max) << 16) | ((invert) << 24) }
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
.tlv.p = (tlv_array), \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
#define SOC_DAPM_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, \
power, 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, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
((max) << 16) | ((invert) << 24) }
#define SOC_DAPM_ENUM(xname, xenum) \ #define SOC_DAPM_ENUM(xname, xenum) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_enum_double, \ .info = snd_soc_info_enum_double, \
......
...@@ -26,27 +26,53 @@ ...@@ -26,27 +26,53 @@
/* /*
* Convenience kcontrol builders * Convenience kcontrol builders
*/ */
#define SOC_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) |\ #define SOC_SINGLE_VALUE(reg, shift, max, invert) ((reg) | ((shift) << 8) |\
((shift) << 12) | ((mask) << 16) | ((invert) << 24)) ((shift) << 12) | ((max) << 16) | ((invert) << 24))
#define SOC_SINGLE_VALUE_EXT(reg,mask,invert) ((reg) | ((mask) << 16) |\ #define SOC_SINGLE_VALUE_EXT(reg, max, invert) ((reg) | ((max) << 16) |\
((invert) << 31)) ((invert) << 31))
#define SOC_SINGLE(xname, reg, shift, mask, invert) \ #define SOC_SINGLE(xname, reg, shift, 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,\
.put = snd_soc_put_volsw, \ .put = snd_soc_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) } .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, 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, .get = snd_soc_get_volsw,\
.put = snd_soc_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, 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, \
.put = snd_soc_put_volsw, \ .put = snd_soc_put_volsw, \
.private_value = (reg) | ((shift_left) << 8) | \ .private_value = (reg) | ((shift_left) << 8) | \
((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } ((shift_right) << 12) | ((max) << 16) | ((invert) << 24) }
#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) \ #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_volsw_2r, \ .info = snd_soc_info_volsw_2r, \
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
.private_value = (reg_left) | ((shift) << 8) | \ .private_value = (reg_left) | ((shift) << 8) | \
((mask) << 12) | ((invert) << 20) | ((reg_right) << 24) } ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, 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, .get = snd_soc_get_volsw, \
.put = snd_soc_put_volsw, \
.private_value = (reg) | ((shift_left) << 8) | \
((shift_right) << 12) | ((max) << 16) | ((invert) << 24) }
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, 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, \
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
.private_value = (reg_left) | ((shift) << 8) | \
((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
.mask = xmask, .texts = xtexts } .mask = xmask, .texts = xtexts }
...@@ -103,10 +129,22 @@ ...@@ -103,10 +129,22 @@
#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */ #define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */ #define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */
/*
* DAI Sync
* Synchronous LR (Left Right) clocks and Frame signals.
*/
#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
/*
* TDM
*/
#define SND_SOC_DAIFMT_TDM (1 << 6)
/* /*
* DAI hardware signal inversions * DAI hardware signal inversions
*/ */
#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */ #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */
#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */ #define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */ #define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */ #define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
......
...@@ -1213,7 +1213,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, ...@@ -1213,7 +1213,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
memcpy(&template, _template, sizeof(template)); memcpy(&template, _template, sizeof(template));
if (long_name) if (long_name)
template.name = long_name; template.name = long_name;
template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
template.index = 0; template.index = 0;
return snd_ctl_new1(&template, data); return snd_ctl_new1(&template, data);
...@@ -1348,13 +1347,16 @@ EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext); ...@@ -1348,13 +1347,16 @@ EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo) struct snd_ctl_elem_info *uinfo)
{ {
int mask = kcontrol->private_value; int max = kcontrol->private_value;
if (max == 1)
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->type =
mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1; uinfo->count = 1;
uinfo->value.integer.min = 0; uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask; uinfo->value.integer.max = max;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
...@@ -1371,15 +1373,18 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); ...@@ -1371,15 +1373,18 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo) struct snd_ctl_elem_info *uinfo)
{ {
int mask = (kcontrol->private_value >> 16) & 0xff; int max = (kcontrol->private_value >> 16) & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f;
uinfo->type = if (max == 1)
mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = shift == rshift ? 1 : 2; uinfo->count = shift == rshift ? 1 : 2;
uinfo->value.integer.min = 0; uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask; uinfo->value.integer.max = max;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_info_volsw); EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
...@@ -1400,7 +1405,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, ...@@ -1400,7 +1405,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff; int max = (kcontrol->private_value >> 16) & 0xff;
int mask = (1 << fls(max)) - 1;
int invert = (kcontrol->private_value >> 24) & 0x01; int invert = (kcontrol->private_value >> 24) & 0x01;
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
...@@ -1410,10 +1416,10 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, ...@@ -1410,10 +1416,10 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
(snd_soc_read(codec, reg) >> rshift) & mask; (snd_soc_read(codec, reg) >> rshift) & mask;
if (invert) { if (invert) {
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
mask - ucontrol->value.integer.value[0]; max - ucontrol->value.integer.value[0];
if (shift != rshift) if (shift != rshift)
ucontrol->value.integer.value[1] = ucontrol->value.integer.value[1] =
mask - ucontrol->value.integer.value[1]; max - ucontrol->value.integer.value[1];
} }
return 0; return 0;
...@@ -1436,25 +1442,24 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -1436,25 +1442,24 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff; int max = (kcontrol->private_value >> 16) & 0xff;
int mask = (1 << fls(max)) - 1;
int invert = (kcontrol->private_value >> 24) & 0x01; int invert = (kcontrol->private_value >> 24) & 0x01;
int err;
unsigned short val, val2, val_mask; unsigned short val, val2, val_mask;
val = (ucontrol->value.integer.value[0] & mask); val = (ucontrol->value.integer.value[0] & mask);
if (invert) if (invert)
val = mask - val; val = max - val;
val_mask = mask << shift; val_mask = mask << shift;
val = val << shift; val = val << shift;
if (shift != rshift) { if (shift != rshift) {
val2 = (ucontrol->value.integer.value[1] & mask); val2 = (ucontrol->value.integer.value[1] & mask);
if (invert) if (invert)
val2 = mask - val2; val2 = max - val2;
val_mask |= mask << rshift; val_mask |= mask << rshift;
val |= val2 << rshift; val |= val2 << rshift;
} }
err = snd_soc_update_bits(codec, reg, val_mask, val); return snd_soc_update_bits(codec, reg, val_mask, val);
return err;
} }
EXPORT_SYMBOL_GPL(snd_soc_put_volsw); EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
...@@ -1471,13 +1476,16 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw); ...@@ -1471,13 +1476,16 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo) struct snd_ctl_elem_info *uinfo)
{ {
int mask = (kcontrol->private_value >> 12) & 0xff; int max = (kcontrol->private_value >> 12) & 0xff;
if (max == 1)
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->type =
mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2; uinfo->count = 2;
uinfo->value.integer.min = 0; uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask; uinfo->value.integer.max = max;
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
...@@ -1498,7 +1506,8 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, ...@@ -1498,7 +1506,8 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 24) & 0xff; int reg2 = (kcontrol->private_value >> 24) & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; int shift = (kcontrol->private_value >> 8) & 0x0f;
int mask = (kcontrol->private_value >> 12) & 0xff; int max = (kcontrol->private_value >> 12) & 0xff;
int mask = (1<<fls(max))-1;
int invert = (kcontrol->private_value >> 20) & 0x01; int invert = (kcontrol->private_value >> 20) & 0x01;
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
...@@ -1507,9 +1516,9 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, ...@@ -1507,9 +1516,9 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
(snd_soc_read(codec, reg2) >> shift) & mask; (snd_soc_read(codec, reg2) >> shift) & mask;
if (invert) { if (invert) {
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
mask - ucontrol->value.integer.value[0]; max - ucontrol->value.integer.value[0];
ucontrol->value.integer.value[1] = ucontrol->value.integer.value[1] =
mask - ucontrol->value.integer.value[1]; max - ucontrol->value.integer.value[1];
} }
return 0; return 0;
...@@ -1532,7 +1541,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, ...@@ -1532,7 +1541,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 24) & 0xff; int reg2 = (kcontrol->private_value >> 24) & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; int shift = (kcontrol->private_value >> 8) & 0x0f;
int mask = (kcontrol->private_value >> 12) & 0xff; int max = (kcontrol->private_value >> 12) & 0xff;
int mask = (1 << fls(max)) - 1;
int invert = (kcontrol->private_value >> 20) & 0x01; int invert = (kcontrol->private_value >> 20) & 0x01;
int err; int err;
unsigned short val, val2, val_mask; unsigned short val, val2, val_mask;
...@@ -1542,8 +1552,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, ...@@ -1542,8 +1552,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
val2 = (ucontrol->value.integer.value[1] & mask); val2 = (ucontrol->value.integer.value[1] & mask);
if (invert) { if (invert) {
val = mask - val; val = max - val;
val2 = mask - val2; val2 = max - val2;
} }
val = val << shift; val = val << shift;
......
...@@ -1018,8 +1018,9 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, ...@@ -1018,8 +1018,9 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff; int max = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0x01; int invert = (kcontrol->private_value >> 24) & 0x01;
int mask = (1 << fls(max)) - 1;
/* return the saved value if we are powered down */ /* return the saved value if we are powered down */
if (widget->id == snd_soc_dapm_pga && !widget->power) { if (widget->id == snd_soc_dapm_pga && !widget->power) {
...@@ -1034,10 +1035,10 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, ...@@ -1034,10 +1035,10 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
(snd_soc_read(widget->codec, reg) >> rshift) & mask; (snd_soc_read(widget->codec, reg) >> rshift) & mask;
if (invert) { if (invert) {
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
mask - ucontrol->value.integer.value[0]; max - ucontrol->value.integer.value[0];
if (shift != rshift) if (shift != rshift)
ucontrol->value.integer.value[1] = ucontrol->value.integer.value[1] =
mask - ucontrol->value.integer.value[1]; max - ucontrol->value.integer.value[1];
} }
return 0; return 0;
...@@ -1060,7 +1061,8 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -1060,7 +1061,8 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
int reg = kcontrol->private_value & 0xff; int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f; int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f; int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff; int max = (kcontrol->private_value >> 16) & 0xff;
int mask = (1 << fls(max)) - 1;
int invert = (kcontrol->private_value >> 24) & 0x01; int invert = (kcontrol->private_value >> 24) & 0x01;
unsigned short val, val2, val_mask; unsigned short val, val2, val_mask;
int ret; int ret;
...@@ -1068,13 +1070,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, ...@@ -1068,13 +1070,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
val = (ucontrol->value.integer.value[0] & mask); val = (ucontrol->value.integer.value[0] & mask);
if (invert) if (invert)
val = mask - val; val = max - val;
val_mask = mask << shift; val_mask = mask << shift;
val = val << shift; val = val << shift;
if (shift != rshift) { if (shift != rshift) {
val2 = (ucontrol->value.integer.value[1] & mask); val2 = (ucontrol->value.integer.value[1] & mask);
if (invert) if (invert)
val2 = mask - val2; val2 = max - val2;
val_mask |= mask << rshift; val_mask |= mask << rshift;
val |= val2 << rshift; val |= val2 << rshift;
} }
......
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