summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/i2c/other/ak4xxx-adda.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 0aea536a3371..89fc3cbc2356 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -284,11 +284,13 @@ EXPORT_SYMBOL(snd_akm4xxx_init);
#define AK_GET_CHIP(val) (((val) >> 8) & 0xff)
#define AK_GET_ADDR(val) ((val) & 0xff)
-#define AK_GET_SHIFT(val) (((val) >> 16) & 0x7f)
+#define AK_GET_SHIFT(val) (((val) >> 16) & 0x3f)
+#define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1)
#define AK_GET_INVERT(val) (((val) >> 23) & 1)
#define AK_GET_MASK(val) (((val) >> 24) & 0xff)
#define AK_COMPOSE(chip,addr,shift,mask) \
(((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24))
+#define AK_NEEDSMSB (1<<22)
#define AK_INVERT (1<<23)
static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol,
@@ -309,10 +311,13 @@ static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol,
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
+ int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value);
int invert = AK_GET_INVERT(kcontrol->private_value);
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
unsigned char val = snd_akm4xxx_get(ak, chip, addr);
-
+
+ if (needsmsb)
+ val &= 0x7f;
ucontrol->value.integer.value[0] = invert ? mask - val : val;
return 0;
}
@@ -323,6 +328,7 @@ static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
+ int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value);
int invert = AK_GET_INVERT(kcontrol->private_value);
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
unsigned char nval = ucontrol->value.integer.value[0] % (mask+1);
@@ -330,6 +336,8 @@ static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
if (invert)
nval = mask - nval;
+ if (needsmsb)
+ nval |= 0x80;
change = snd_akm4xxx_get(ak, chip, addr) != nval;
if (change)
snd_akm4xxx_write(ak, chip, addr, nval);
@@ -354,13 +362,19 @@ static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol,
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
+ int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value);
int invert = AK_GET_INVERT(kcontrol->private_value);
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
- unsigned char val = snd_akm4xxx_get(ak, chip, addr);
-
+ unsigned char val;
+
+ val = snd_akm4xxx_get(ak, chip, addr);
+ if (needsmsb)
+ val &= 0x7f;
ucontrol->value.integer.value[0] = invert ? mask - val : val;
val = snd_akm4xxx_get(ak, chip, addr+1);
+ if (needsmsb)
+ val &= 0x7f;
ucontrol->value.integer.value[1] = invert ? mask - val : val;
return 0;
@@ -372,6 +386,7 @@ static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
+ int needsmsb = AK_GET_NEEDSMSB(kcontrol->private_value);
int invert = AK_GET_INVERT(kcontrol->private_value);
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
unsigned char nval = ucontrol->value.integer.value[0] % (mask+1);
@@ -379,6 +394,8 @@ static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
if (invert)
nval = mask - nval;
+ if (needsmsb)
+ nval |= 0x80;
change0 = snd_akm4xxx_get(ak, chip, addr) != nval;
if (change0)
snd_akm4xxx_write(ak, chip, addr, nval);
@@ -386,6 +403,8 @@ static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
nval = ucontrol->value.integer.value[1] % (mask+1);
if (invert)
nval = mask - nval;
+ if (needsmsb)
+ nval |= 0x80;
change1 = snd_akm4xxx_get(ak, chip, addr+1) != nval;
if (change1)
snd_akm4xxx_write(ak, chip, addr+1, nval);
@@ -585,16 +604,13 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
/* register 4-9, chip #0 only */
ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255);
break;
- case SND_AK4358:
- if (idx >= 6)
- /* register 4-9, chip #0 only */
- ctl->private_value =
- AK_COMPOSE(0, idx + 5, 0, 255);
- else
- /* register 4-9, chip #0 only */
- ctl->private_value =
- AK_COMPOSE(0, idx + 4, 0, 255);
+ case SND_AK4358: {
+ /* register 4-9 and 11-12, chip #0 only */
+ int addr = idx < 6 ? idx + 4 : idx + 5;
+ ctl->private_value =
+ AK_COMPOSE(0, addr, 0, 127) | AK_NEEDSMSB;
break;
+ }
case SND_AK4381:
/* register 3 & 4 */
ctl->private_value =