* [RFC] Add dB scale information to AK4xxx codec
@ 2006-08-28 11:38 Takashi Iwai
2006-08-28 14:52 ` Takashi Iwai
2006-09-03 15:53 ` Jochen Voss
0 siblings, 2 replies; 21+ messages in thread
From: Takashi Iwai @ 2006-08-28 11:38 UTC (permalink / raw)
To: alsa-devel; +Cc: Jochen Voss
Hi,
the below is a patch to add dB scale information to ak4xxx-adda module
used by ice1712 and ice1724 drivers.
Could someone check whether this works, at least, it doesn't cause any
regressions? I could test some but not all these.
The patch is to the latest ALSA HG version with linear volume TLV.
Also, I found an error in AK5365 capture gain and fixed in this patch.
Now there are two capture volume controls, "Capture Volume" and
"Capture Gain Volume". The former is the attenuation up to 0dB, the
latter is IPGA (independent gain) in AK4524/4528. Jochen, please
try this patch with your revo 5.1 board.
Thanks,
Takashi
diff -r 61bfe5b3a7ae include/ak4xxx-adda.h
--- a/include/ak4xxx-adda.h Fri Aug 25 13:11:26 2006 +0200
+++ b/include/ak4xxx-adda.h Fri Aug 25 17:12:57 2006 +0200
@@ -44,9 +44,7 @@ struct snd_akm4xxx {
unsigned int num_adcs; /* AK4524 or AK4528 ADCs */
unsigned int num_dacs; /* AK4524 or AK4528 DACs */
unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */
- unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image
- * for IPGA (AK4528)
- */
+ unsigned char volumes[AK4XXX_IMAGE_SIZE]; /* saved volume values */
unsigned long private_value[AK4XXX_MAX_CHIPS]; /* helper for driver */
void *private_data[AK4XXX_MAX_CHIPS]; /* helper for driver */
/* template should fill the following fields */
@@ -73,9 +71,18 @@ int snd_akm4xxx_build_controls(struct sn
(ak)->images[(chip) * 16 + (reg)]
#define snd_akm4xxx_set(ak,chip,reg,val) \
((ak)->images[(chip) * 16 + (reg)] = (val))
+#define snd_akm4xxx_get_vol(ak,chip,reg) \
+ (ak)->volumes[(chip) * 16 + (reg)]
+#define snd_akm4xxx_set_vol(ak,chip,reg,val) \
+ ((ak)->volumes[(chip) * 16 + (reg)] = (val))
+
+/* Warning: IPGA is tricky - we assume the addr + 4 is unused
+ * so far, it's OK for all AK codecs with IPGA:
+ * AK4524, AK4528 and EK5365
+ */
#define snd_akm4xxx_get_ipga(ak,chip,reg) \
- (ak)->ipga_gain[chip][(reg)-4]
+ snd_akm4xxx_get_vol(ak, chip, (reg) + 4)
#define snd_akm4xxx_set_ipga(ak,chip,reg,val) \
- ((ak)->ipga_gain[chip][(reg)-4] = (val))
+ snd_akm4xxx_set_vol(ak, chip, (reg) + 4, val)
#endif /* __SOUND_AK4XXX_ADDA_H */
diff -r 61bfe5b3a7ae i2c/other/ak4xxx-adda.c
--- a/i2c/other/ak4xxx-adda.c Fri Aug 25 13:11:26 2006 +0200
+++ b/i2c/other/ak4xxx-adda.c Fri Aug 25 17:18:00 2006 +0200
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <sound/core.h>
#include <sound/control.h>
+#include <sound/tlv.h>
#include <sound/ak4xxx-adda.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
@@ -41,11 +42,12 @@ void snd_akm4xxx_write(struct snd_akm4xx
ak->ops.write(ak, chip, reg, val);
/* save the data */
- if (ak->type == SND_AK4524 || ak->type == SND_AK4528) {
+ if (ak->type == SND_AK4524 || ak->type == SND_AK4528 ||
+ ak->type == SND_AK5365) {
if ((reg != 0x04 && reg != 0x05) || (val & 0x80) == 0)
snd_akm4xxx_set(ak, chip, reg, val);
else
- snd_akm4xxx_set_ipga(ak, chip, reg, val);
+ snd_akm4xxx_set_ipga(ak, chip, reg, val & 0x7f);
} else {
/* AK4529, or else */
snd_akm4xxx_set(ak, chip, reg, val);
@@ -78,7 +80,7 @@ static void ak4524_reset(struct snd_akm4
/* IPGA */
for (reg = 0x04; reg < 0x06; reg++)
snd_akm4xxx_write(ak, chip, reg,
- snd_akm4xxx_get_ipga(ak, chip, reg));
+ snd_akm4xxx_get_ipga(ak, chip, reg) | 0x80);
}
}
@@ -143,6 +145,39 @@ void snd_akm4xxx_reset(struct snd_akm4xx
}
EXPORT_SYMBOL(snd_akm4xxx_reset);
+
+
+/*
+ * Volume conversion table for non-linear volumes
+ * from -63.5dB (mute) to 0dB step 0.5dB
+ *
+ * Used for AK4524 input/ouput attenuation, AK4528, and
+ * AK5365 input attenuation
+ */
+static unsigned char vol_cvt_datt[128] = {
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04,
+ 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06,
+ 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a,
+ 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f,
+ 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1c,
+ 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x23,
+ 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2d,
+ 0x2e, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, 0x40,
+ 0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a,
+ 0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53, 0x54,
+ 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x69,
+ 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73,
+ 0x75, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f,
+};
+
+static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1);
+static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1);
+static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1);
+static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0);
+static DECLARE_TLV_DB_SCALE(db_scale_ipga, 0, 50, 0);
/*
* initialize all the ak4xxx chips
@@ -284,12 +319,14 @@ 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) & 0x3f)
+#define AK_GET_SHIFT(val) (((val) >> 16) & 0x1f)
+#define AK_GET_VOL_CVT(val) (((val) >> 21) & 1)
#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_VOL_CVT (1<<21)
#define AK_NEEDSMSB (1<<22)
#define AK_INVERT (1<<23)
@@ -311,14 +348,8 @@ static int snd_akm4xxx_volume_get(struct
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;
+
+ ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr);
return 0;
}
@@ -328,20 +359,22 @@ static int snd_akm4xxx_volume_put(struct
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);
- int change;
-
- if (invert)
+ unsigned char nval;
+
+ nval = ucontrol->value.integer.value[0] % (mask+1);
+ if (snd_akm4xxx_get_vol(ak, chip, addr) == nval)
+ return 0;
+
+ snd_akm4xxx_set_vol(ak, chip, addr, nval);
+ if (AK_GET_VOL_CVT(kcontrol->private_value))
+ nval = vol_cvt_datt[nval];
+ if (AK_GET_INVERT(kcontrol->private_value))
nval = mask - nval;
- if (needsmsb)
+ if (AK_GET_NEEDSMSB(kcontrol->private_value))
nval |= 0x80;
- change = snd_akm4xxx_get(ak, chip, addr) != nval;
- if (change)
- snd_akm4xxx_write(ak, chip, addr, nval);
- return change;
+ snd_akm4xxx_write(ak, chip, addr, nval);
+ return 1;
}
static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,
@@ -362,66 +395,55 @@ static int snd_akm4xxx_stereo_volume_get
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
+
+ ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr);
+ ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1);
+ return 0;
+}
+
+static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ 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 vol_cvt = AK_GET_VOL_CVT(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;
-
- 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;
-}
-
-static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- 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);
- int change0, change1;
-
- if (invert)
- nval = mask - nval;
- if (needsmsb)
- nval |= 0x80;
- change0 = snd_akm4xxx_get(ak, chip, addr) != nval;
- if (change0)
+ unsigned char nval;
+ int change = 0;
+
+ nval = ucontrol->value.integer.value[0] % (mask+1);
+ if (snd_akm4xxx_get_vol(ak, chip, addr) != nval) {
+ change = 1;
+ snd_akm4xxx_set_vol(ak, chip, addr, nval);
+ if (vol_cvt)
+ nval = vol_cvt_datt[nval];
+ if (invert)
+ nval = mask - nval;
+ if (needsmsb)
+ nval |= 0x80;
snd_akm4xxx_write(ak, chip, addr, nval);
+ }
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);
-
-
- return change0 || change1;
-}
-
-static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 36;
- return 0;
-}
+ if (snd_akm4xxx_get_vol(ak, chip, addr + 1) != nval) {
+ change = 1;
+ snd_akm4xxx_set_vol(ak, chip, addr + 1, nval);
+ if (vol_cvt)
+ nval = vol_cvt_datt[nval];
+ if (invert)
+ nval = mask - nval;
+ if (needsmsb)
+ nval |= 0x80;
+ snd_akm4xxx_write(ak, chip, addr + 1, nval);
+ }
+
+ return change;
+}
+
+#define snd_akm4xxx_ipga_gain_info snd_akm4xxx_volume_info
static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -429,8 +451,9 @@ static int snd_akm4xxx_ipga_gain_get(str
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
+
ucontrol->value.integer.value[0] =
- snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f;
+ snd_akm4xxx_get_ipga(ak, chip, addr);
return 0;
}
@@ -440,10 +463,57 @@ static int snd_akm4xxx_ipga_gain_put(str
struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
- unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80;
- int change = snd_akm4xxx_get_ipga(ak, chip, addr) != nval;
- if (change)
- snd_akm4xxx_write(ak, chip, addr, nval);
+ unsigned int mask = AK_GET_MASK(kcontrol->private_value);
+ unsigned char nval;
+
+ nval = ucontrol->value.integer.value[0] % (mask + 1);
+ if (snd_akm4xxx_get_ipga(ak, chip, addr) == nval)
+ return 0;
+ snd_akm4xxx_set_ipga(ak, chip, addr, nval);
+ snd_akm4xxx_write(ak, chip, addr, nval | 0x80); /* need MSB */
+ return 1;
+}
+
+#define snd_akm4xxx_stereo_gain_info snd_akm4xxx_stereo_volume_info
+
+static int snd_akm4xxx_stereo_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
+
+ ucontrol->value.integer.value[0] =
+ snd_akm4xxx_get_ipga(ak, chip, addr);
+ ucontrol->value.integer.value[1] =
+ snd_akm4xxx_get_ipga(ak, chip, addr + 1);
+ return 0;
+}
+
+static int snd_akm4xxx_stereo_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
+ unsigned int mask = AK_GET_MASK(kcontrol->private_value);
+ unsigned char nval;
+ int change = 0;
+
+ nval = ucontrol->value.integer.value[0] % (mask + 1);
+ if (snd_akm4xxx_get_ipga(ak, chip, addr) != nval) {
+ change = 1;
+ snd_akm4xxx_set_ipga(ak, chip, addr, nval);
+ snd_akm4xxx_write(ak, chip, addr, nval | 0x80); /* need MSB */
+ }
+
+ nval = ucontrol->value.integer.value[1] % (mask+1);
+ if (snd_akm4xxx_get_ipga(ak, chip, addr + 1) != nval) {
+ change = 1;
+ snd_akm4xxx_set_ipga(ak, chip, addr + 1, nval);
+ snd_akm4xxx_write(ak, chip, addr + 1, nval | 0x80);
+ }
+
return change;
}
@@ -586,35 +656,43 @@ int snd_akm4xxx_build_controls(struct sn
case SND_AK4524:
/* register 6 & 7 */
ctl->private_value =
- AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127);
+ AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127) |
+ AK_VOL_CVT;
+ ctl->tlv.p = db_scale_vol_datt;
break;
case SND_AK4528:
/* register 4 & 5 */
ctl->private_value =
- AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127);
+ AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) |
+ AK_VOL_CVT;
+ ctl->tlv.p = db_scale_vol_datt;
break;
case SND_AK4529: {
/* registers 2-7 and b,c */
int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb;
ctl->private_value =
AK_COMPOSE(0, val, 0, 255) | AK_INVERT;
+ ctl->tlv.p = db_scale_8bit;
break;
}
case SND_AK4355:
/* register 4-9, chip #0 only */
ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255);
+ ctl->tlv.p = db_scale_8bit;
break;
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;
+ ctl->tlv.p = db_scale_7bit;
break;
}
case SND_AK4381:
/* register 3 & 4 */
ctl->private_value =
AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255);
+ ctl->tlv.p = db_scale_linear;
break;
default:
err = -EINVAL;
@@ -624,7 +702,8 @@ int snd_akm4xxx_build_controls(struct sn
ctl->private_data = ak;
err = snd_ctl_add(ak->card,
snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|
- SNDRV_CTL_ELEM_ACCESS_WRITE));
+ SNDRV_CTL_ELEM_ACCESS_WRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ));
if (err < 0)
goto __error;
@@ -642,11 +721,14 @@ int snd_akm4xxx_build_controls(struct sn
ctl->put = snd_akm4xxx_volume_put;
/* register 4 & 5 */
ctl->private_value =
- AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127);
+ AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) |
+ AK_VOL_CVT;
ctl->private_data = ak;
+ ctl->tlv.p = db_scale_vol_datt;
err = snd_ctl_add(ak->card,
snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|
- SNDRV_CTL_ELEM_ACCESS_WRITE));
+ SNDRV_CTL_ELEM_ACCESS_WRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ));
if (err < 0)
goto __error;
@@ -659,11 +741,13 @@ int snd_akm4xxx_build_controls(struct sn
ctl->get = snd_akm4xxx_ipga_gain_get;
ctl->put = snd_akm4xxx_ipga_gain_put;
/* register 4 & 5 */
- ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0);
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 36);
ctl->private_data = ak;
+ ctl->tlv.p = db_scale_ipga;
err = snd_ctl_add(ak->card,
snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|
- SNDRV_CTL_ELEM_ACCESS_WRITE));
+ SNDRV_CTL_ELEM_ACCESS_WRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ));
if (err < 0)
goto __error;
}
@@ -681,13 +765,33 @@ int snd_akm4xxx_build_controls(struct sn
ctl->get = snd_akm4xxx_stereo_volume_get;
ctl->put = snd_akm4xxx_stereo_volume_put;
/* Registers 4 & 5 (see AK5365 data sheet, pages 34 and 35):
- * valid values are from 0x00 (mute) to 0x98 (+12dB). */
+ * valid values are from 0x00 (mute) to 0x7f (0dB) */
ctl->private_value =
- AK_COMPOSE(0, 4, 0, 0x98);
+ AK_COMPOSE(0, 4, 0, 127) | AK_VOL_CVT;
ctl->private_data = ak;
+ ctl->tlv.p = db_scale_vol_datt;
err = snd_ctl_add(ak->card,
snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|
SNDRV_CTL_ELEM_ACCESS_WRITE));
+ if (err < 0)
+ goto __error;
+
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "Capture Gain Volume");
+ ctl->id.index = ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_stereo_gain_info;
+ ctl->get = snd_akm4xxx_stereo_gain_get;
+ ctl->put = snd_akm4xxx_stereo_gain_put;
+ /* register 4 & 5 - IPGA */
+ ctl->private_value = AK_COMPOSE(0, 4, 0, 24);
+ ctl->private_data = ak;
+ ctl->tlv.p = db_scale_ipga;
+ err = snd_ctl_add(ak->card,
+ snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|
+ SNDRV_CTL_ELEM_ACCESS_WRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ));
if (err < 0)
goto __error;
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [RFC] Add dB scale information to AK4xxx codec 2006-08-28 11:38 [RFC] Add dB scale information to AK4xxx codec Takashi Iwai @ 2006-08-28 14:52 ` Takashi Iwai 2006-09-03 15:53 ` Jochen Voss 1 sibling, 0 replies; 21+ messages in thread From: Takashi Iwai @ 2006-08-28 14:52 UTC (permalink / raw) To: alsa-devel; +Cc: Jochen Voss At Mon, 28 Aug 2006 13:38:21 +0200, I wrote: > > Hi, > > the below is a patch to add dB scale information to ak4xxx-adda module > used by ice1712 and ice1724 drivers. > > Could someone check whether this works, at least, it doesn't cause any > regressions? I could test some but not all these. > > The patch is to the latest ALSA HG version with linear volume TLV. > > Also, I found an error in AK5365 capture gain and fixed in this patch. > Now there are two capture volume controls, "Capture Volume" and > "Capture Gain Volume". The former is the attenuation up to 0dB, the > latter is IPGA (independent gain) in AK4524/4528. Jochen, please > try this patch with your revo 5.1 board. Below is a newer version including more supports for VT1720/24-based boards. Takashi diff -r 375a71e84412 i2c/other/ak4xxx-adda.c --- a/i2c/other/ak4xxx-adda.c Mon Aug 28 16:52:41 2006 +0200 +++ b/i2c/other/ak4xxx-adda.c Mon Aug 28 16:42:43 2006 +0200 @@ -28,6 +28,7 @@ #include <linux/init.h> #include <sound/core.h> #include <sound/control.h> +#include <sound/tlv.h> #include <sound/ak4xxx-adda.h> MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>"); @@ -41,15 +42,10 @@ void snd_akm4xxx_write(struct snd_akm4xx ak->ops.write(ak, chip, reg, val); /* save the data */ - if (ak->type == SND_AK4524 || ak->type == SND_AK4528) { - if ((reg != 0x04 && reg != 0x05) || (val & 0x80) == 0) - snd_akm4xxx_set(ak, chip, reg, val); - else - snd_akm4xxx_set_ipga(ak, chip, reg, val); - } else { - /* AK4529, or else */ + /* don't overwrite with IPGA data */ + if ((ak->type != SND_AK4524 && ak->type != SND_AK5365) || + (reg != 0x04 && reg != 0x05) || (val & 0x80) == 0) snd_akm4xxx_set(ak, chip, reg, val); - } ak->ops.unlock(ak, chip); } @@ -78,7 +74,7 @@ static void ak4524_reset(struct snd_akm4 /* IPGA */ for (reg = 0x04; reg < 0x06; reg++) snd_akm4xxx_write(ak, chip, reg, - snd_akm4xxx_get_ipga(ak, chip, reg)); + snd_akm4xxx_get_ipga(ak, chip, reg) | 0x80); } } @@ -143,6 +139,39 @@ void snd_akm4xxx_reset(struct snd_akm4xx } EXPORT_SYMBOL(snd_akm4xxx_reset); + + +/* + * Volume conversion table for non-linear volumes + * from -63.5dB (mute) to 0dB step 0.5dB + * + * Used for AK4524 input/ouput attenuation, AK4528, and + * AK5365 input attenuation + */ +static unsigned char vol_cvt_datt[128] = { + 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, + 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, + 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, + 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x23, + 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2d, + 0x2e, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a, + 0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x69, + 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73, + 0x75, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f, +}; + +static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); +static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); +static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); +static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); +static DECLARE_TLV_DB_SCALE(db_scale_ipga, 0, 50, 0); /* * initialize all the ak4xxx chips @@ -265,6 +294,9 @@ void snd_akm4xxx_init(struct snd_akm4xxx inits = inits_ak4381; num_chips = ak->num_dacs / 2; break; + case SND_AK5365: + /* FIXME: any init sequence? */ + return; default: snd_BUG(); return; @@ -284,12 +316,14 @@ 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) & 0x3f) +#define AK_GET_SHIFT(val) (((val) >> 16) & 0x1f) +#define AK_GET_VOL_CVT(val) (((val) >> 21) & 1) #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_VOL_CVT (1<<21) #define AK_NEEDSMSB (1<<22) #define AK_INVERT (1<<23) @@ -311,14 +345,8 @@ static int snd_akm4xxx_volume_get(struct 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; + + ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); return 0; } @@ -328,20 +356,22 @@ static int snd_akm4xxx_volume_put(struct 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); - int change; - - if (invert) + unsigned char nval; + + nval = ucontrol->value.integer.value[0] % (mask+1); + if (snd_akm4xxx_get_vol(ak, chip, addr) == nval) + return 0; + + snd_akm4xxx_set_vol(ak, chip, addr, nval); + if (AK_GET_VOL_CVT(kcontrol->private_value)) + nval = vol_cvt_datt[nval]; + if (AK_GET_INVERT(kcontrol->private_value)) nval = mask - nval; - if (needsmsb) + if (AK_GET_NEEDSMSB(kcontrol->private_value)) nval |= 0x80; - change = snd_akm4xxx_get(ak, chip, addr) != nval; - if (change) - snd_akm4xxx_write(ak, chip, addr, nval); - return change; + snd_akm4xxx_write(ak, chip, addr, nval); + return 1; } static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, @@ -362,66 +392,55 @@ static int snd_akm4xxx_stereo_volume_get struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); + + ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); + ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1); + return 0; +} + +static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + 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 vol_cvt = AK_GET_VOL_CVT(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; - - 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; -} - -static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - 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); - int change0, change1; - - if (invert) - nval = mask - nval; - if (needsmsb) - nval |= 0x80; - change0 = snd_akm4xxx_get(ak, chip, addr) != nval; - if (change0) + unsigned char nval; + int change = 0; + + nval = ucontrol->value.integer.value[0] % (mask+1); + if (snd_akm4xxx_get_vol(ak, chip, addr) != nval) { + change = 1; + snd_akm4xxx_set_vol(ak, chip, addr, nval); + if (vol_cvt) + nval = vol_cvt_datt[nval]; + if (invert) + nval = mask - nval; + if (needsmsb) + nval |= 0x80; snd_akm4xxx_write(ak, chip, addr, nval); + } 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); - - - return change0 || change1; -} - -static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 36; - return 0; -} + if (snd_akm4xxx_get_vol(ak, chip, addr + 1) != nval) { + change = 1; + snd_akm4xxx_set_vol(ak, chip, addr + 1, nval); + if (vol_cvt) + nval = vol_cvt_datt[nval]; + if (invert) + nval = mask - nval; + if (needsmsb) + nval |= 0x80; + snd_akm4xxx_write(ak, chip, addr + 1, nval); + } + + return change; +} + +#define snd_akm4xxx_ipga_gain_info snd_akm4xxx_volume_info static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -429,8 +448,9 @@ static int snd_akm4xxx_ipga_gain_get(str struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); + ucontrol->value.integer.value[0] = - snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; + snd_akm4xxx_get_ipga(ak, chip, addr); return 0; } @@ -440,10 +460,57 @@ static int snd_akm4xxx_ipga_gain_put(str struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); - unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80; - int change = snd_akm4xxx_get_ipga(ak, chip, addr) != nval; - if (change) - snd_akm4xxx_write(ak, chip, addr, nval); + unsigned int mask = AK_GET_MASK(kcontrol->private_value); + unsigned char nval; + + nval = ucontrol->value.integer.value[0] % (mask + 1); + if (snd_akm4xxx_get_ipga(ak, chip, addr) == nval) + return 0; + snd_akm4xxx_set_ipga(ak, chip, addr, nval); + snd_akm4xxx_write(ak, chip, addr, nval | 0x80); /* need MSB */ + return 1; +} + +#define snd_akm4xxx_stereo_gain_info snd_akm4xxx_stereo_volume_info + +static int snd_akm4xxx_stereo_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); + int chip = AK_GET_CHIP(kcontrol->private_value); + int addr = AK_GET_ADDR(kcontrol->private_value); + + ucontrol->value.integer.value[0] = + snd_akm4xxx_get_ipga(ak, chip, addr); + ucontrol->value.integer.value[1] = + snd_akm4xxx_get_ipga(ak, chip, addr + 1); + return 0; +} + +static int snd_akm4xxx_stereo_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); + int chip = AK_GET_CHIP(kcontrol->private_value); + int addr = AK_GET_ADDR(kcontrol->private_value); + unsigned int mask = AK_GET_MASK(kcontrol->private_value); + unsigned char nval; + int change = 0; + + nval = ucontrol->value.integer.value[0] % (mask + 1); + if (snd_akm4xxx_get_ipga(ak, chip, addr) != nval) { + change = 1; + snd_akm4xxx_set_ipga(ak, chip, addr, nval); + snd_akm4xxx_write(ak, chip, addr, nval | 0x80); /* need MSB */ + } + + nval = ucontrol->value.integer.value[1] % (mask+1); + if (snd_akm4xxx_get_ipga(ak, chip, addr + 1) != nval) { + change = 1; + snd_akm4xxx_set_ipga(ak, chip, addr + 1, nval); + snd_akm4xxx_write(ak, chip, addr + 1, nval | 0x80); + } + return change; } @@ -562,13 +629,13 @@ int snd_akm4xxx_build_controls(struct sn for (idx = 0; idx < ak->num_dacs; ) { memset(ctl, 0, sizeof(*ctl)); - if (ak->channel_names == NULL) { + if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { strcpy(ctl->id.name, "DAC Volume"); num_stereo = 1; ctl->id.index = mixer_ch + ak->idx_offset * 2; } else { - strcpy(ctl->id.name, ak->channel_names[mixer_ch]); - num_stereo = ak->num_stereo[mixer_ch]; + strcpy(ctl->id.name, ak->dac_info[mixer_ch].name); + num_stereo = ak->dac_info[mixer_ch].num_channels; ctl->id.index = 0; } ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; @@ -586,35 +653,43 @@ int snd_akm4xxx_build_controls(struct sn case SND_AK4524: /* register 6 & 7 */ ctl->private_value = - AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); + AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127) | + AK_VOL_CVT; + ctl->tlv.p = db_scale_vol_datt; break; case SND_AK4528: /* register 4 & 5 */ ctl->private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | + AK_VOL_CVT; + ctl->tlv.p = db_scale_vol_datt; break; case SND_AK4529: { /* registers 2-7 and b,c */ int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; ctl->private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT; + ctl->tlv.p = db_scale_8bit; break; } case SND_AK4355: /* register 4-9, chip #0 only */ ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); + ctl->tlv.p = db_scale_8bit; break; 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; + ctl->tlv.p = db_scale_7bit; break; } case SND_AK4381: /* register 3 & 4 */ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); + ctl->tlv.p = db_scale_linear; break; default: err = -EINVAL; @@ -624,95 +699,124 @@ int snd_akm4xxx_build_controls(struct sn ctl->private_data = ak; err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); + SNDRV_CTL_ELEM_ACCESS_WRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ)); if (err < 0) goto __error; idx += num_stereo; mixer_ch++; } - for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) { + + if (ak->type != SND_AK4524 && ak->type != SND_AK5365) + goto no_gain; + + mixer_ch = 0; + for (idx = 0; idx < ak->num_adcs;) { memset(ctl, 0, sizeof(*ctl)); - strcpy(ctl->id.name, "ADC Volume"); - ctl->id.index = idx + ak->idx_offset * 2; + if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { + strcpy(ctl->id.name, "ADC Volume"); + num_stereo = 1; + ctl->id.index = mixer_ch + ak->idx_offset * 2; + } else { + strcpy(ctl->id.name, ak->adc_info[mixer_ch].name); + num_stereo = ak->adc_info[mixer_ch].num_channels; + ctl->id.index = 0; + } ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; ctl->count = 1; - ctl->info = snd_akm4xxx_volume_info; - ctl->get = snd_akm4xxx_volume_get; - ctl->put = snd_akm4xxx_volume_put; + if (num_stereo == 2) { + ctl->info = snd_akm4xxx_stereo_volume_info; + ctl->get = snd_akm4xxx_stereo_volume_get; + ctl->put = snd_akm4xxx_stereo_volume_put; + } else { + ctl->info = snd_akm4xxx_volume_info; + ctl->get = snd_akm4xxx_volume_get; + ctl->put = snd_akm4xxx_volume_put; + } /* register 4 & 5 */ ctl->private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | + AK_VOL_CVT; ctl->private_data = ak; + ctl->tlv.p = db_scale_vol_datt; err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); + SNDRV_CTL_ELEM_ACCESS_WRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ)); if (err < 0) goto __error; memset(ctl, 0, sizeof(*ctl)); - strcpy(ctl->id.name, "IPGA Analog Capture Volume"); - ctl->id.index = idx + ak->idx_offset * 2; + if (! ak->adc_info || ! ak->adc_info[mixer_ch].gain_name) { + strcpy(ctl->id.name, "IPGA Analog Capture Volume"); + num_stereo = 1; + ctl->id.index = mixer_ch + ak->idx_offset * 2; + } else { + strcpy(ctl->id.name, ak->adc_info[mixer_ch].gain_name); + num_stereo = ak->adc_info[mixer_ch].num_channels; + ctl->id.index = 0; + } ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; ctl->count = 1; - ctl->info = snd_akm4xxx_ipga_gain_info; - ctl->get = snd_akm4xxx_ipga_gain_get; - ctl->put = snd_akm4xxx_ipga_gain_put; + if (num_stereo == 2) { + ctl->info = snd_akm4xxx_stereo_gain_info; + ctl->get = snd_akm4xxx_stereo_gain_get; + ctl->put = snd_akm4xxx_stereo_gain_put; + } else { + ctl->info = snd_akm4xxx_ipga_gain_info; + ctl->get = snd_akm4xxx_ipga_gain_get; + ctl->put = snd_akm4xxx_ipga_gain_put; + } /* register 4 & 5 */ - ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); + if (ak->type == SND_AK4524) + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, + 24); + else /* AK5365 */ + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, + 36); ctl->private_data = ak; + ctl->tlv.p = db_scale_ipga; err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); + SNDRV_CTL_ELEM_ACCESS_WRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ)); if (err < 0) goto __error; - } - - if (ak->type == SND_AK5365) { - memset(ctl, 0, sizeof(*ctl)); - if (ak->channel_names == NULL) - strcpy(ctl->id.name, "Capture Volume"); - else - strcpy(ctl->id.name, ak->channel_names[0]); - ctl->id.index = ak->idx_offset * 2; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - ctl->count = 1; - ctl->info = snd_akm4xxx_stereo_volume_info; - ctl->get = snd_akm4xxx_stereo_volume_get; - ctl->put = snd_akm4xxx_stereo_volume_put; - /* Registers 4 & 5 (see AK5365 data sheet, pages 34 and 35): - * valid values are from 0x00 (mute) to 0x98 (+12dB). */ - ctl->private_value = - AK_COMPOSE(0, 4, 0, 0x98); - ctl->private_data = ak; - err = snd_ctl_add(ak->card, - snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); - if (err < 0) - goto __error; - - memset(ctl, 0, sizeof(*ctl)); - if (ak->channel_names == NULL) - strcpy(ctl->id.name, "Capture Switch"); - else - strcpy(ctl->id.name, ak->channel_names[1]); - ctl->id.index = ak->idx_offset * 2; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - ctl->count = 1; - ctl->info = ak4xxx_switch_info; - ctl->get = ak4xxx_switch_get; - ctl->put = ak4xxx_switch_put; - /* register 2, bit 0 (SMUTE): 0 = normal operation, 1 = mute */ - ctl->private_value = - AK_COMPOSE(0, 2, 0, 0) | AK_INVERT; - ctl->private_data = ak; - err = snd_ctl_add(ak->card, - snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); - if (err < 0) - goto __error; - } - + + if (ak->type == SND_AK5365 && (idx % 2) == 0) { + memset(ctl, 0, sizeof(*ctl)); + if (! ak->adc_info || + ! ak->adc_info[mixer_ch].switch_name) { + strcpy(ctl->id.name, "Capture Switch"); + ctl->id.index = mixer_ch + ak->idx_offset * 2; + } else { + strcpy(ctl->id.name, + ak->adc_info[mixer_ch].switch_name); + ctl->id.index = 0; + } + ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + ctl->count = 1; + ctl->info = ak4xxx_switch_info; + ctl->get = ak4xxx_switch_get; + ctl->put = ak4xxx_switch_put; + /* register 2, bit 0 (SMUTE): 0 = normal operation, + 1 = mute */ + ctl->private_value = + AK_COMPOSE(idx/2, 2, 0, 0) | AK_INVERT; + ctl->private_data = ak; + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); + if (err < 0) + goto __error; + } + + idx += num_stereo; + mixer_ch++; + } + + no_gain: if (ak->type == SND_AK4355 || ak->type == SND_AK4358) num_emphs = 1; else diff -r 375a71e84412 include/ak4xxx-adda.h --- a/include/ak4xxx-adda.h Mon Aug 28 16:52:41 2006 +0200 +++ b/include/ak4xxx-adda.h Mon Aug 28 15:47:09 2006 +0200 @@ -39,14 +39,26 @@ struct snd_ak4xxx_ops { #define AK4XXX_IMAGE_SIZE (AK4XXX_MAX_CHIPS * 16) /* 64 bytes */ +/* DAC label and channels */ +struct snd_akm4xxx_dac_channel { + char *name; /* mixer volume name */ + unsigned int num_channels; +}; + +/* ADC labels and channels */ +struct snd_akm4xxx_adc_channel { + char *name; /* capture gain volume label */ + char *gain_name; /* IPGA */ + char *switch_name; /* capture switch */ + unsigned int num_channels; +}; + struct snd_akm4xxx { struct snd_card *card; unsigned int num_adcs; /* AK4524 or AK4528 ADCs */ unsigned int num_dacs; /* AK4524 or AK4528 DACs */ unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */ - unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image - * for IPGA (AK4528) - */ + unsigned char volumes[AK4XXX_IMAGE_SIZE]; /* saved volume values */ unsigned long private_value[AK4XXX_MAX_CHIPS]; /* helper for driver */ void *private_data[AK4XXX_MAX_CHIPS]; /* helper for driver */ /* template should fill the following fields */ @@ -56,10 +68,11 @@ struct snd_akm4xxx { SND_AK4355, SND_AK4358, SND_AK4381, SND_AK5365 } type; - unsigned int *num_stereo; /* array of combined counts - * for the mixer - */ - char **channel_names; /* array of mixer channel names */ + + /* (array) information of combined codecs */ + struct snd_akm4xxx_dac_channel *dac_info; + struct snd_akm4xxx_adc_channel *adc_info; + struct snd_ak4xxx_ops ops; }; @@ -73,9 +86,18 @@ int snd_akm4xxx_build_controls(struct sn (ak)->images[(chip) * 16 + (reg)] #define snd_akm4xxx_set(ak,chip,reg,val) \ ((ak)->images[(chip) * 16 + (reg)] = (val)) +#define snd_akm4xxx_get_vol(ak,chip,reg) \ + (ak)->volumes[(chip) * 16 + (reg)] +#define snd_akm4xxx_set_vol(ak,chip,reg,val) \ + ((ak)->volumes[(chip) * 16 + (reg)] = (val)) + +/* Warning: IPGA is tricky - we assume the addr + 4 is unused + * so far, it's OK for all AK codecs with IPGA: + * AK4524, AK4528 and EK5365 + */ #define snd_akm4xxx_get_ipga(ak,chip,reg) \ - (ak)->ipga_gain[chip][(reg)-4] + snd_akm4xxx_get_vol(ak, chip, (reg) + 4) #define snd_akm4xxx_set_ipga(ak,chip,reg,val) \ - ((ak)->ipga_gain[chip][(reg)-4] = (val)) + snd_akm4xxx_set_vol(ak, chip, (reg) + 4, val) #endif /* __SOUND_AK4XXX_ADDA_H */ diff -r 375a71e84412 pci/ice1712/aureon.c --- a/pci/ice1712/aureon.c Mon Aug 28 16:52:41 2006 +0200 +++ b/pci/ice1712/aureon.c Mon Aug 28 16:39:08 2006 +0200 @@ -60,6 +60,7 @@ #include "ice1712.h" #include "envy24ht.h" #include "aureon.h" +#include <sound/tlv.h> /* WM8770 registers */ #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ @@ -660,6 +661,12 @@ static int aureon_ac97_mmute_put(struct return change; } +static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); +static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); +static DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0); +static DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0); +static DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0); + /* * Logarithmic volume values for WM8770 * Computed as 20 * Log10(255 / x) @@ -1409,10 +1416,13 @@ static struct snd_kcontrol_new aureon_da }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Master Playback Volume", .info = wm_master_vol_info, .get = wm_master_vol_get, - .put = wm_master_vol_put + .put = wm_master_vol_put, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1424,11 +1434,14 @@ static struct snd_kcontrol_new aureon_da }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Front Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 0 + .private_value = (2 << 8) | 0, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1440,11 +1453,14 @@ static struct snd_kcontrol_new aureon_da }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Rear Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 2 + .private_value = (2 << 8) | 2, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1456,11 +1472,14 @@ static struct snd_kcontrol_new aureon_da }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Center Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 4 + .private_value = (1 << 8) | 4, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1472,11 +1491,14 @@ static struct snd_kcontrol_new aureon_da }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "LFE Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 5 + .private_value = (1 << 8) | 5, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1488,11 +1510,14 @@ static struct snd_kcontrol_new aureon_da }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Side Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 6 + .private_value = (2 << 8) | 6, + .tlv = { .p = db_scale_wm_dac } } }; @@ -1506,10 +1531,13 @@ static struct snd_kcontrol_new wm_contro }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "PCM Playback Volume", .info = wm_pcm_vol_info, .get = wm_pcm_vol_get, - .put = wm_pcm_vol_put + .put = wm_pcm_vol_put, + .tlv = { .p = db_scale_wm_pcm } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1520,10 +1548,13 @@ static struct snd_kcontrol_new wm_contro }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Capture Volume", .info = wm_adc_vol_info, .get = wm_adc_vol_get, - .put = wm_adc_vol_put + .put = wm_adc_vol_put, + .tlv = { .p = db_scale_wm_adc } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1567,11 +1598,14 @@ static struct snd_kcontrol_new ac97_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "AC97 Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MASTER|AUREON_AC97_STEREO + .private_value = AC97_MASTER|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_master } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1583,11 +1617,14 @@ static struct snd_kcontrol_new ac97_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "CD Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_CD|AUREON_AC97_STEREO + .private_value = AC97_CD|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1599,11 +1636,14 @@ static struct snd_kcontrol_new ac97_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Aux Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_AUX|AUREON_AC97_STEREO + .private_value = AC97_AUX|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1615,11 +1655,14 @@ static struct snd_kcontrol_new ac97_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Line Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_LINE|AUREON_AC97_STEREO + .private_value = AC97_LINE|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1631,11 +1674,14 @@ static struct snd_kcontrol_new ac97_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Mic Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MIC + .private_value = AC97_MIC, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1657,11 +1703,14 @@ static struct snd_kcontrol_new universe_ }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "AC97 Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MASTER|AUREON_AC97_STEREO + .private_value = AC97_MASTER|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_master } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1673,11 +1722,14 @@ static struct snd_kcontrol_new universe_ }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "CD Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_AUX|AUREON_AC97_STEREO + .private_value = AC97_AUX|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1685,15 +1737,18 @@ static struct snd_kcontrol_new universe_ .info = aureon_ac97_mute_info, .get = aureon_ac97_mute_get, .put = aureon_ac97_mute_put, - .private_value = AC97_CD, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .private_value = AC97_CD + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Phono Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_CD|AUREON_AC97_STEREO + .private_value = AC97_CD|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1705,11 +1760,14 @@ static struct snd_kcontrol_new universe_ }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Line Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_LINE|AUREON_AC97_STEREO + .private_value = AC97_LINE|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1721,11 +1779,14 @@ static struct snd_kcontrol_new universe_ }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Mic Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MIC + .private_value = AC97_MIC, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1744,11 +1805,14 @@ static struct snd_kcontrol_new universe_ }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Aux Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_VIDEO|AUREON_AC97_STEREO + .private_value = AC97_VIDEO|AUREON_AC97_STEREO, + .tlv = { .p = db_scale_ac97_gain } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, diff -r 375a71e84412 pci/ice1712/phase.c --- a/pci/ice1712/phase.c Mon Aug 28 16:52:41 2006 +0200 +++ b/pci/ice1712/phase.c Mon Aug 28 16:40:51 2006 +0200 @@ -46,6 +46,7 @@ #include "ice1712.h" #include "envy24ht.h" #include "phase.h" +#include <sound/tlv.h> /* WM8770 registers */ #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ @@ -696,6 +697,9 @@ static int phase28_oversampling_put(stru return 0; } +static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); +static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); + static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -706,10 +710,13 @@ static struct snd_kcontrol_new phase28_d }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Master Playback Volume", .info = wm_master_vol_info, .get = wm_master_vol_get, - .put = wm_master_vol_put + .put = wm_master_vol_put, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -721,11 +728,14 @@ static struct snd_kcontrol_new phase28_d }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Front Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 0 + .private_value = (2 << 8) | 0, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -737,11 +747,14 @@ static struct snd_kcontrol_new phase28_d }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Rear Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 2 + .private_value = (2 << 8) | 2, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -753,11 +766,14 @@ static struct snd_kcontrol_new phase28_d }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Center Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 4 + .private_value = (1 << 8) | 4, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -769,11 +785,14 @@ static struct snd_kcontrol_new phase28_d }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "LFE Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 5 + .private_value = (1 << 8) | 5, + .tlv = { .p = db_scale_wm_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -785,11 +804,14 @@ static struct snd_kcontrol_new phase28_d }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Side Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 6 + .private_value = (2 << 8) | 6, + .tlv = { .p = db_scale_wm_dac } } }; @@ -803,10 +825,13 @@ static struct snd_kcontrol_new wm_contro }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "PCM Playback Volume", .info = wm_pcm_vol_info, .get = wm_pcm_vol_get, - .put = wm_pcm_vol_put + .put = wm_pcm_vol_put, + .tlv = { .p = db_scale_wm_pcm } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, diff -r 375a71e84412 pci/ice1712/prodigy192.c --- a/pci/ice1712/prodigy192.c Mon Aug 28 16:52:41 2006 +0200 +++ b/pci/ice1712/prodigy192.c Mon Aug 28 16:36:33 2006 +0200 @@ -35,6 +35,7 @@ #include "envy24ht.h" #include "prodigy192.h" #include "stac946x.h" +#include <sound/tlv.h> static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) { @@ -356,6 +357,9 @@ static int aureon_oversampling_put(struc } #endif +static DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); +static DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); + /* * mixers */ @@ -368,14 +372,18 @@ static struct snd_kcontrol_new stac_cont .get = stac9460_dac_mute_get, .put = stac9460_dac_mute_put, .private_value = 1, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .tlv = { .p = db_scale_dac } + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Master Playback Volume", .info = stac9460_dac_vol_info, .get = stac9460_dac_vol_get, .put = stac9460_dac_vol_put, .private_value = 1, + .tlv = { .p = db_scale_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -387,11 +395,14 @@ static struct snd_kcontrol_new stac_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "DAC Volume", .count = 6, .info = stac9460_dac_vol_info, .get = stac9460_dac_vol_get, .put = stac9460_dac_vol_put, + .tlv = { .p = db_scale_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -404,11 +415,14 @@ static struct snd_kcontrol_new stac_cont }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "ADC Volume", .count = 1, .info = stac9460_adc_vol_info, .get = stac9460_adc_vol_get, .put = stac9460_adc_vol_put, + .tlv = { .p = db_scale_adc } }, #if 0 { diff -r 375a71e84412 pci/ice1712/revo.c --- a/pci/ice1712/revo.c Mon Aug 28 16:52:41 2006 +0200 +++ b/pci/ice1712/revo.c Mon Aug 28 16:05:47 2006 +0200 @@ -87,19 +87,34 @@ static void revo_set_rate_val(struct snd * initialize the chips on M-Audio Revolution cards */ -static unsigned int revo71_num_stereo_front[] = {2}; -static char *revo71_channel_names_front[] = {"PCM Playback Volume"}; - -static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2}; -static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume", - "PCM Side Playback Volume", "PCM Rear Playback Volume"}; - -static unsigned int revo51_num_stereo[] = {2, 1, 1, 2}; -static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume", - "PCM LFE Playback Volume", "PCM Rear Playback Volume"}; - -static unsigned int revo51_adc_num_stereo[] = {2}; -static char *revo51_adc_channel_names[] = {"PCM Capture Volume","PCM Capture Switch"}; +#define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } + +static struct snd_akm4xxx_dac_channel revo71_front[] = { + AK_DAC("PCM Playback Volume", 2) +}; + +static struct snd_akm4xxx_dac_channel revo71_surround[] = { + AK_DAC("PCM Center Playback Volume", 1), + AK_DAC("PCM LFE Playback Volume", 1), + AK_DAC("PCM Side Playback Volume", 2), + AK_DAC("PCM Rear Playback Volume", 2), +}; + +static struct snd_akm4xxx_dac_channel revo51_dac[] = { + AK_DAC("PCM Playback Volume", 2), + AK_DAC("PCM Center Playback Volume", 1), + AK_DAC("PCM LFE Playback Volume", 1), + AK_DAC("PCM Rear Playback Volume", 2), +}; + +static struct snd_akm4xxx_adc_channel revo51_adc[] = { + { + .name = "PCM Capture Volume", + .gain_name = "PCM Capture Gain Volume", + .switch_name = "PCM Capture Switch", + .num_channels = 2 + }, +}; static struct snd_akm4xxx akm_revo_front __devinitdata = { .type = SND_AK4381, @@ -107,8 +122,7 @@ static struct snd_akm4xxx akm_revo_front .ops = { .set_rate_val = revo_set_rate_val }, - .num_stereo = revo71_num_stereo_front, - .channel_names = revo71_channel_names_front + .dac_info = revo71_front, }; static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { @@ -130,8 +144,7 @@ static struct snd_akm4xxx akm_revo_surro .ops = { .set_rate_val = revo_set_rate_val }, - .num_stereo = revo71_num_stereo_surround, - .channel_names = revo71_channel_names_surround + .dac_info = revo71_surround, }; static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { @@ -152,8 +165,7 @@ static struct snd_akm4xxx akm_revo51 __d .ops = { .set_rate_val = revo_set_rate_val }, - .num_stereo = revo51_num_stereo, - .channel_names = revo51_channel_names + .dac_info = revo51_dac, }; static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { @@ -171,8 +183,7 @@ static struct snd_akm4xxx akm_revo51_adc static struct snd_akm4xxx akm_revo51_adc __devinitdata = { .type = SND_AK5365, .num_adcs = 2, - .num_stereo = revo51_adc_num_stereo, - .channel_names = revo51_adc_channel_names + .adc_info = revo51_adc, }; static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = { ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-08-28 11:38 [RFC] Add dB scale information to AK4xxx codec Takashi Iwai 2006-08-28 14:52 ` Takashi Iwai @ 2006-09-03 15:53 ` Jochen Voss 2006-09-04 9:58 ` Takashi Iwai 1 sibling, 1 reply; 21+ messages in thread From: Jochen Voss @ 2006-09-03 15:53 UTC (permalink / raw) To: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 1220 bytes --] Hi Takashi, sorry about the delay, I was travelling again. On Mon, Aug 28, 2006 at 01:38:21PM +0200, Takashi Iwai wrote: > Also, I found an error in AK5365 capture gain and fixed in this patch. > Now there are two capture volume controls, "Capture Volume" and > "Capture Gain Volume". The former is the attenuation up to 0dB, the > latter is IPGA (independent gain) in AK4524/4528. Jochen, please > try this patch with your revo 5.1 board. I do not quite understand the new volume controls. I think something is wrong, now. What is the expected behaviour of the controls? From table 17 (page 35) of the AK5365 specs I think that IPGA and DATT are only separate units inside the chip, but should be treated as one continuous scale for the purpose of the driver. The table looks like the input volume can be adjusted in steps from "mute" to +12dB. Why would we want two controls here? Also I notice the presence of a "PCM Capture Gain Capture" control, which looks wrong. I can change "PCM Capture Gain Capture" on its own, but when I change "PCM Capture Gain", the "PCM Capture Gain Capture" control jumps to have the same value. I hope this helps, Jochen -- http://seehuhn.de/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-03 15:53 ` Jochen Voss @ 2006-09-04 9:58 ` Takashi Iwai 2006-09-04 11:13 ` Jochen Voß 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-04 9:58 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel At Sun, 3 Sep 2006 16:53:57 +0100, Jochen Voss wrote: > > Hi Takashi, > > sorry about the delay, I was travelling again. > > On Mon, Aug 28, 2006 at 01:38:21PM +0200, Takashi Iwai wrote: > > Also, I found an error in AK5365 capture gain and fixed in this patch. > > Now there are two capture volume controls, "Capture Volume" and > > "Capture Gain Volume". The former is the attenuation up to 0dB, the > > latter is IPGA (independent gain) in AK4524/4528. Jochen, please > > try this patch with your revo 5.1 board. > > I do not quite understand the new volume controls. I think something > is wrong, now. What is the expected behaviour of the controls? > > From table 17 (page 35) of the AK5365 specs I think that IPGA and DATT > are only separate units inside the chip, but should be treated as one > continuous scale for the purpose of the driver. The table looks like > the input volume can be adjusted in steps from "mute" to +12dB. Why > would we want two controls here? Actually they are treated independently in the chip. IPGA works like a preamp, and the total volume is IPGA + DATT. Even if you set a value to IPGA with MSB, say 0x82, DATT won't be changed and the old value is kept. And it's vice versa - if you set 0x02 later, IPGA will stay as 0x82. This is so, at least with AK4524 and AK4528. Possibly this was changed on AK5365, though... > Also I notice the presence of a "PCM Capture Gain Capture" control, > which looks wrong. I can change "PCM Capture Gain Capture" on its > own, but when I change "PCM Capture Gain", the "PCM Capture Gain > Capture" control jumps to have the same value. Hm, there is no "PCM Capture Gain Capture", maybe "PCM Capture Gain Volume"? It's IPGA. Takashi ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-04 9:58 ` Takashi Iwai @ 2006-09-04 11:13 ` Jochen Voß 2006-09-04 11:35 ` Takashi Iwai 2006-09-04 17:41 ` Jochen Voss 0 siblings, 2 replies; 21+ messages in thread From: Jochen Voß @ 2006-09-04 11:13 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 1126 bytes --] Hi Takashi, On Mon, Sep 04, 2006 at 11:58:57AM +0200, Takashi Iwai wrote: > > From table 17 (page 35) of the AK5365 specs I think that IPGA and DATT > > are only separate units inside the chip, but should be treated as one > > continuous scale for the purpose of the driver. The table looks like > > the input volume can be adjusted in steps from "mute" to +12dB. Why > > would we want two controls here? > > Actually they are treated independently in the chip. IPGA works like > a preamp, and the total volume is IPGA + DATT. Even if you set a > value to IPGA with MSB, say 0x82, DATT won't be changed and the old > value is kept. And it's vice versa - if you set 0x02 later, IPGA will > stay as 0x82. This is so, at least with AK4524 and AK4528. Possibly > this was changed on AK5365, though... Did you have a look at table 17? I think the old behaviour was better. > Hm, there is no "PCM Capture Gain Capture", maybe "PCM Capture Gain > Volume"? It's IPGA. I will send the amixer output this evening when I get back home. All the best, Jochen -- http://www.maths.warwick.ac.uk/~voss/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-04 11:13 ` Jochen Voß @ 2006-09-04 11:35 ` Takashi Iwai 2006-09-04 12:12 ` Jochen Voß 2006-09-04 17:41 ` Jochen Voss 1 sibling, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-04 11:35 UTC (permalink / raw) To: Jochen Voß; +Cc: alsa-devel At Mon, 4 Sep 2006 12:13:06 +0100, Jochen Voß wrote: > > Hi Takashi, > > On Mon, Sep 04, 2006 at 11:58:57AM +0200, Takashi Iwai wrote: > > > From table 17 (page 35) of the AK5365 specs I think that IPGA and DATT > > > are only separate units inside the chip, but should be treated as one > > > continuous scale for the purpose of the driver. The table looks like > > > the input volume can be adjusted in steps from "mute" to +12dB. Why > > > would we want two controls here? > > > > Actually they are treated independently in the chip. IPGA works like > > a preamp, and the total volume is IPGA + DATT. Even if you set a > > value to IPGA with MSB, say 0x82, DATT won't be changed and the old > > value is kept. And it's vice versa - if you set 0x02 later, IPGA will > > stay as 0x82. This is so, at least with AK4524 and AK4528. Possibly > > this was changed on AK5365, though... > Did you have a look at table 17? I think the old behaviour was better. Yes, the exactly same table appears in AK4524 datasheet, too. The only question is whether they really behave _indenpendently_. On AK4524, IPGA and IATT are actually two different values. As I wrote, 0x82 only changes IPGA value but doesn't change IATT. 0x02 changes only IATT but not IPGA. And the total volume is IPGA + IATT. Takashi ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-04 11:35 ` Takashi Iwai @ 2006-09-04 12:12 ` Jochen Voß 0 siblings, 0 replies; 21+ messages in thread From: Jochen Voß @ 2006-09-04 12:12 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 563 bytes --] Hi Takashi, On Mon, Sep 04, 2006 at 01:35:31PM +0200, Takashi Iwai wrote: > Yes, the exactly same table appears in AK4524 datasheet, too. > The only question is whether they really behave _indenpendently_. > > On AK4524, IPGA and IATT are actually two different values. As I > wrote, 0x82 only changes IPGA value but doesn't change IATT. 0x02 > changes only IATT but not IPGA. And the total volume is IPGA + IATT. Ok, I will try to play with my card and figure this out tonight. All the best, Jochen -- http://www.maths.warwick.ac.uk/~voss/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-04 11:13 ` Jochen Voß 2006-09-04 11:35 ` Takashi Iwai @ 2006-09-04 17:41 ` Jochen Voss 2006-09-04 18:28 ` Takashi Iwai 1 sibling, 1 reply; 21+ messages in thread From: Jochen Voss @ 2006-09-04 17:41 UTC (permalink / raw) To: alsa-devel; +Cc: Takashi Iwai [-- Attachment #1.1: Type: text/plain, Size: 527 bytes --] Hi Takashi, On Mon, Sep 04, 2006 at 12:13:06PM +0100, Jochen Voß wrote: > > Hm, there is no "PCM Capture Gain Capture", maybe "PCM Capture Gain > > Volume"? It's IPGA. > I will send the amixer output this evening when I get back home. Ok, it seems to be a problem with alsamixer (maybe caused by the fact that I still used v1.0.11). The amixer output looks better and does not have the strange "PCM Capture Gain Capture". My apologies for the confusion caused. All the best, Jochen -- http://seehuhn.de/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-04 17:41 ` Jochen Voss @ 2006-09-04 18:28 ` Takashi Iwai 2006-09-04 19:27 ` Jochen Voss 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-04 18:28 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel At Mon, 4 Sep 2006 18:41:24 +0100, Jochen Voss wrote: > > Hi Takashi, > > On Mon, Sep 04, 2006 at 12:13:06PM +0100, Jochen Voß wrote: > > > Hm, there is no "PCM Capture Gain Capture", maybe "PCM Capture Gain > > > Volume"? It's IPGA. > > I will send the amixer output this evening when I get back home. > > Ok, it seems to be a problem with alsamixer (maybe caused by the fact > that I still used v1.0.11). The amixer output looks better and does > not have the strange "PCM Capture Gain Capture". My apologies for the > confusion caused. OK, maybe the problem is its naming. What happens if you change it as "PCM Gain Capture Volume"? Then you'll get "PCM Gain" in the capture section of alsamixer. Anyway, I'd like to know whether IPGA and IATT are really independen on AK5365 codec chip. Try to compare the volumes recorded in the two conditions: IPGA = non-zero, Capture = below 0dB (e.g. 80%) and IPGA = 0 (=0dB), Capture = same value as above In both cases, make sure that you "reset" the volume, that is, once set the volume to 0 (or else) then set to another target value. The sequence to test is to first set IPGA (Capture Gain) then set Catpure Volume. You can use amixer, % amixer set "PCM Gain" 2 % amixer set "PCM Gain" 0 % amixer set "Capture" 0 % amixer set "Capture" 80% recording... % amixer set "PCM Gain" 0 % amixer set "PCM Gain" 2 % amixer set "Capture" 0 % amixer set "Capture" 80% recording... If the volumes of two cases are same, the IPGA isn't independent and both controls should be merged to a single control. Takashi ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-04 18:28 ` Takashi Iwai @ 2006-09-04 19:27 ` Jochen Voss 2006-09-05 9:36 ` Takashi Iwai 0 siblings, 1 reply; 21+ messages in thread From: Jochen Voss @ 2006-09-04 19:27 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 6190 bytes --] Hi Takashi, On Mon, Sep 04, 2006 at 08:28:32PM +0200, Takashi Iwai wrote: > OK, maybe the problem is its naming. I ignored this for the moment. Once we are sure how many controls there are, we can think about the naming. > % amixer set "PCM Gain" 2 > % amixer set "PCM Gain" 0 > % amixer set "Capture" 0 > % amixer set "Capture" 80% > recording... > > % amixer set "PCM Gain" 0 > % amixer set "PCM Gain" 2 > % amixer set "Capture" 0 > % amixer set "Capture" 80% > recording... > > If the volumes of two cases are same, the IPGA isn't independent and > both controls should be merged to a single control. I read the AK4524 data sheet and I see now what you mean. The descriptions there are almost identical. I tried the following. My amixer output is at the end of the mail for reference. first I created two shell scripts: -- s1.sh ------------------------------------------------------------- #! /bin/sh amixer set "PCM Capture Gain" 2 amixer set "PCM Capture Gain" 0 amixer set "PCM" 0 amixer set "PCM" 80% ---------------------------------------------------------------------- -- s2.sh ------------------------------------------------------------- #! /bin/sh amixer set "PCM Capture Gain" 0 amixer set "PCM Capture Gain" 2 amixer set "PCM" 0 amixer set "PCM" 80% ---------------------------------------------------------------------- and then I run the following command on the shell while true; do ./s1.sh; sleep 1; ./s2.sh; sleep 1; done While this was running I recorded a wav file with arecord. The volume of the recorded file was extremely low (is this normal?) so I normalised it with audacity. I looked at the wave form in audacity and I played the normalised file with alsamixer. Results: 1) I cannot hear or see the difference between the settings from s1.sh and s2.sh. 2) As a test I tried the following: I can hear (and maybe just see) the difference between 80% (value 102) and 82% (value 104). I cannot notice any difference between 80% (value 102) and 81% (value 103). Do you have any idea how different the volumes would be if IPGA and DATT were independent? All the best, Jochen -- amixer output ----------------------------------------------------- Simple mixer control 'PCM',0 Capabilities: pvolume cvolume cswitch cswitch-joined Playback channels: Front Left - Front Right Capture channels: Front Left - Front Right Limits: Playback 0 - 127 Capture 0 - 127 Front Left: Playback 102 [80%] Capture 102 [80%] [on] Front Right: Playback 102 [80%] Capture 102 [80%] [on] Simple mixer control 'PCM Capture Gain',0 Capabilities: volume Playback channels: Front Left - Front Right Capture channels: Front Left - Front Right Limits: 0 - 36 Front Left: 2 [6%] Front Right: 2 [6%] Simple mixer control 'PCM Center',0 Capabilities: pvolume pvolume-joined Playback channels: Mono Limits: Playback 0 - 127 Mono: Playback 127 [100%] Simple mixer control 'PCM LFE',0 Capabilities: pvolume pvolume-joined Playback channels: Mono Limits: Playback 0 - 127 Mono: Playback 127 [100%] Simple mixer control 'PCM Rear',0 Capabilities: pvolume Playback channels: Front Left - Front Right Limits: Playback 0 - 127 Mono: Front Left: Playback 127 [100%] Front Right: Playback 127 [100%] Simple mixer control 'IEC958',0 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'H/W In 0' Simple mixer control 'IEC958 Output',0 Capabilities: pswitch pswitch-joined Playback channels: Mono Mono: Playback [on] Simple mixer control 'IEC958',1 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'H/W In 1' Simple mixer control 'Deemphasis',0 Capabilities: enum Items: '44.1kHz' 'Off' '48kHz' '32kHz' Item0: 'Off' Simple mixer control 'H/W',0 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'PCM Out' Simple mixer control 'H/W',1 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'PCM Out' Simple mixer control 'H/W',2 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'H/W In 0' Simple mixer control 'H/W',3 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'H/W In 1' Simple mixer control 'H/W',4 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'IEC958 In L' Simple mixer control 'H/W',5 Capabilities: enum Items: 'PCM Out' 'H/W In 0' 'H/W In 1' 'IEC958 In L' 'IEC958 In R' Item0: 'IEC958 In R' Simple mixer control 'Multi Track Internal Clock',0 Capabilities: enum Items: '8000' '9600' '11025' '12000' '16000' '22050' '24000' '32000' '44100' '48000' '64000' '88200' '96000' '176400' '192000' 'IEC958 Input' Item0: '44100' Simple mixer control 'Multi Track Peak',0 Capabilities: volume Playback channels: Front Left - Front Right - Rear Left - Rear Right - Front Center - Woofer - Side Left - Side Right - Rear Center - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? Capture channels: Front Left - Front Right - Rear Left - Rear Right - Front Center - Woofer - Side Left - Side Right - Rear Center - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? - ? Limits: 0 - 255 Front Left: 0 [0%] Front Right: 0 [0%] Rear Left: 0 [0%] Rear Right: 0 [0%] Front Center: 0 [0%] Woofer: 0 [0%] Side Left: 0 [0%] Side Right: 0 [0%] Rear Center: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] ?: 0 [0%] Simple mixer control 'Multi Track Rate Locking',0 Capabilities: pswitch pswitch-joined Playback channels: Mono Mono: Playback [on] Simple mixer control 'Multi Track Rate Reset',0 Capabilities: pswitch pswitch-joined Playback channels: Mono Mono: Playback [on] ---------------------------------------------------------------------- [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-04 19:27 ` Jochen Voss @ 2006-09-05 9:36 ` Takashi Iwai 2006-09-05 19:24 ` Jochen Voss 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-05 9:36 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel At Mon, 4 Sep 2006 20:27:41 +0100, Jochen Voss wrote: > > Hi Takashi, > > On Mon, Sep 04, 2006 at 08:28:32PM +0200, Takashi Iwai wrote: > > OK, maybe the problem is its naming. > I ignored this for the moment. Once we are sure how many controls > there are, we can think about the naming. > > > % amixer set "PCM Gain" 2 > > % amixer set "PCM Gain" 0 > > % amixer set "Capture" 0 > > % amixer set "Capture" 80% > > recording... > > > > % amixer set "PCM Gain" 0 > > % amixer set "PCM Gain" 2 > > % amixer set "Capture" 0 > > % amixer set "Capture" 80% > > recording... > > > > If the volumes of two cases are same, the IPGA isn't independent and > > both controls should be merged to a single control. > > I read the AK4524 data sheet and I see now what you mean. The > descriptions there are almost identical. > > I tried the following. My amixer output is at the end of the mail for > reference. first I created two shell scripts: > > -- s1.sh ------------------------------------------------------------- > #! /bin/sh > amixer set "PCM Capture Gain" 2 > amixer set "PCM Capture Gain" 0 > amixer set "PCM" 0 > amixer set "PCM" 80% > ---------------------------------------------------------------------- > > -- s2.sh ------------------------------------------------------------- > #! /bin/sh > amixer set "PCM Capture Gain" 0 > amixer set "PCM Capture Gain" 2 > amixer set "PCM" 0 > amixer set "PCM" 80% > ---------------------------------------------------------------------- > > and then I run the following command on the shell > > while true; do ./s1.sh; sleep 1; ./s2.sh; sleep 1; done > > While this was running I recorded a wav file with arecord. The volume > of the recorded file was extremely low (is this normal?) so I > normalised it with audacity. I looked at the wave form in audacity > and I played the normalised file with alsamixer. In s2.sh, use a higher value for "PCM Capture Gain", such as 20. If the volume is still low, then IPGA is not independent. > 1) I cannot hear or see the difference between the settings from s1.sh > and s2.sh. > > 2) As a test I tried the following: I can hear (and maybe just see) > the difference between 80% (value 102) and 82% (value 104). I cannot > notice any difference between 80% (value 102) and 81% (value 103). This doesn't matter. The ATT volume is corrected slightly to be linear to dB. Takashi ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-05 9:36 ` Takashi Iwai @ 2006-09-05 19:24 ` Jochen Voss 2006-09-07 10:09 ` Takashi Iwai 0 siblings, 1 reply; 21+ messages in thread From: Jochen Voss @ 2006-09-05 19:24 UTC (permalink / raw) To: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 2584 bytes --] Hello Takashi, I do not completely understand the suggested test, do I just blindly follow your suggestions. I am sorry about the absence of more intelligent contributions from my side here. On Tue, Sep 05, 2006 at 11:36:50AM +0200, Takashi Iwai wrote: > > I tried the following. My amixer output is at the end of the mail for > > reference. first I created two shell scripts: > > > > -- s1.sh ------------------------------------------------------------- > > #! /bin/sh > > amixer set "PCM Capture Gain" 2 > > amixer set "PCM Capture Gain" 0 > > amixer set "PCM" 0 > > amixer set "PCM" 80% > > ---------------------------------------------------------------------- > > > > -- s2.sh ------------------------------------------------------------- > > #! /bin/sh > > amixer set "PCM Capture Gain" 0 > > amixer set "PCM Capture Gain" 2 > > amixer set "PCM" 0 > > amixer set "PCM" 80% > > ---------------------------------------------------------------------- > > > > and then I run the following command on the shell > > > > while true; do ./s1.sh; sleep 1; ./s2.sh; sleep 1; done > > > > While this was running I recorded a wav file with arecord. The volume > > of the recorded file was extremely low (is this normal?) so I > > normalised it with audacity. I looked at the wave form in audacity > > and I played the normalised file with alsamixer. > > In s2.sh, use a higher value for "PCM Capture Gain", such as 20. > If the volume is still low, then IPGA is not independent. I used 'amixer set "PCM Capture Gain" 20' now in s2.sh only. Was this the plan? Result: there is now an audible crack when s2.sh is executed, but the volume before and after the cracks still seems to be the same. I also tried something else: when I alternate between ---------------------------------------------------------------------- amixer set "PCM Capture Gain" 0 amixer set "PCM Capture Gain" 20 amixer set "PCM" 0 amixer set "PCM" 80% ---------------------------------------------------------------------- and ---------------------------------------------------------------------- amixer set "PCM" 0 amixer set "PCM" 80% amixer set "PCM Capture Gain" 0 amixer set "PCM Capture Gain" 20 ---------------------------------------------------------------------- the recording has alternating load and quiete stretches. Whatever this might tell us about the ADC, it looks like a bug to me: the order of setting the two controls shouldn't matter. Or am I confused again? I hope this helps, Jochen -- http://seehuhn.de/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-05 19:24 ` Jochen Voss @ 2006-09-07 10:09 ` Takashi Iwai 2006-09-07 10:29 ` Jochen Voss 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-07 10:09 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel At Tue, 5 Sep 2006 20:24:55 +0100, Jochen Voss wrote: > > Hello Takashi, > > I do not completely understand the suggested test, do I just blindly > follow your suggestions. I am sorry about the absence of more > intelligent contributions from my side here. > > On Tue, Sep 05, 2006 at 11:36:50AM +0200, Takashi Iwai wrote: > > > I tried the following. My amixer output is at the end of the mail for > > > reference. first I created two shell scripts: > > > > > > -- s1.sh ------------------------------------------------------------- > > > #! /bin/sh > > > amixer set "PCM Capture Gain" 2 > > > amixer set "PCM Capture Gain" 0 > > > amixer set "PCM" 0 > > > amixer set "PCM" 80% > > > ---------------------------------------------------------------------- > > > > > > -- s2.sh ------------------------------------------------------------- > > > #! /bin/sh > > > amixer set "PCM Capture Gain" 0 > > > amixer set "PCM Capture Gain" 2 > > > amixer set "PCM" 0 > > > amixer set "PCM" 80% > > > ---------------------------------------------------------------------- > > > > > > and then I run the following command on the shell > > > > > > while true; do ./s1.sh; sleep 1; ./s2.sh; sleep 1; done > > > > > > While this was running I recorded a wav file with arecord. The volume > > > of the recorded file was extremely low (is this normal?) so I > > > normalised it with audacity. I looked at the wave form in audacity > > > and I played the normalised file with alsamixer. > > > > In s2.sh, use a higher value for "PCM Capture Gain", such as 20. > > If the volume is still low, then IPGA is not independent. > > I used 'amixer set "PCM Capture Gain" 20' now in s2.sh only. Was this > the plan? Result: there is now an audible crack when s2.sh is > executed, but the volume before and after the cracks still seems to be > the same. The crack doesn't matter seriously, but just the volume. > I also tried something else: when I alternate between > ---------------------------------------------------------------------- > amixer set "PCM Capture Gain" 0 > amixer set "PCM Capture Gain" 20 > amixer set "PCM" 0 > amixer set "PCM" 80% > ---------------------------------------------------------------------- > and > ---------------------------------------------------------------------- > amixer set "PCM" 0 > amixer set "PCM" 80% > amixer set "PCM Capture Gain" 0 > amixer set "PCM Capture Gain" 20 > ---------------------------------------------------------------------- > the recording has alternating load and quiete stretches. Whatever this > might tell us about the ADC, it looks like a bug to me: the order of > setting the two controls shouldn't matter. Or am I confused again? Well, assume that "PCM Capture" and "PCM Capture Gain" are independent. If so, the above two should result in the same state. If it's not independent but the register 4 & 5 take single values (that was the behavior of your original implementation), the above two cases must make a clear difference: in the former case, the gain is below 0dB, and in the latter it's +10dB. Was it so through your tests? Also, it's possible that I did make a silly mistake. Put a debug printk around ak->ops.write() in snd_akm4xxx_write() to check what values are written to register 4 and 5. Takashi ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-07 10:09 ` Takashi Iwai @ 2006-09-07 10:29 ` Jochen Voss 2006-09-07 10:33 ` Takashi Iwai 0 siblings, 1 reply; 21+ messages in thread From: Jochen Voss @ 2006-09-07 10:29 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 2886 bytes --] Hi Takashi, On Thu, Sep 07, 2006 at 12:09:05PM +0200, Takashi Iwai wrote: > > > > -- s1.sh ------------------------------------------------------------- > > > > #! /bin/sh > > > > amixer set "PCM Capture Gain" 2 > > > > amixer set "PCM Capture Gain" 0 > > > > amixer set "PCM" 0 > > > > amixer set "PCM" 80% > > > > ---------------------------------------------------------------------- > > > > > > > > -- s2.sh ------------------------------------------------------------- > > > > #! /bin/sh > > > > amixer set "PCM Capture Gain" 0 > > > > amixer set "PCM Capture Gain" 2 > > > > amixer set "PCM" 0 > > > > amixer set "PCM" 80% > > > > ---------------------------------------------------------------------- > > I used 'amixer set "PCM Capture Gain" 20' now in s2.sh only. Was this > > the plan? Result: there is now an audible crack when s2.sh is > > executed, but the volume before and after the cracks still seems to be > > the same. > > The crack doesn't matter seriously, but just the volume. The volume is the same. Why is everything assigned twice (e.g. first 0 then 2) in this test? > > I also tried something else: when I alternate between > > ---------------------------------------------------------------------- > > amixer set "PCM Capture Gain" 0 > > amixer set "PCM Capture Gain" 20 > > amixer set "PCM" 0 > > amixer set "PCM" 80% > > ---------------------------------------------------------------------- > > and > > ---------------------------------------------------------------------- > > amixer set "PCM" 0 > > amixer set "PCM" 80% > > amixer set "PCM Capture Gain" 0 > > amixer set "PCM Capture Gain" 20 > > ---------------------------------------------------------------------- > > the recording has alternating load and quiete stretches. Whatever this > > might tell us about the ADC, it looks like a bug to me: the order of > > setting the two controls shouldn't matter. Or am I confused again? > > Well, assume that "PCM Capture" and "PCM Capture Gain" are > independent. If so, the above two should result in the same state. > > If it's not independent but the register 4 & 5 take single values > (that was the behavior of your original implementation), the above two > cases must make a clear difference: in the former case, the gain is > below 0dB, and in the latter it's +10dB. Was it so through your > tests? Yes, the recording had alternating load and quite stretches, corresponding to the two settings. So both tests seem to indicate that for the AK5365 registers 4 and 5 take only a single value. Correct? > Also, it's possible that I did make a silly mistake. Put a debug > printk around ak->ops.write() in snd_akm4xxx_write() to check what > values are written to register 4 and 5. I will try this in the evening. Many thanks, Jochen -- http://seehuhn.de/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-07 10:29 ` Jochen Voss @ 2006-09-07 10:33 ` Takashi Iwai 2006-09-07 11:00 ` Jochen Voss 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-07 10:33 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel At Thu, 7 Sep 2006 11:29:54 +0100, Jochen Voss wrote: > > Hi Takashi, > > On Thu, Sep 07, 2006 at 12:09:05PM +0200, Takashi Iwai wrote: > > > > > -- s1.sh ------------------------------------------------------------- > > > > > #! /bin/sh > > > > > amixer set "PCM Capture Gain" 2 > > > > > amixer set "PCM Capture Gain" 0 > > > > > amixer set "PCM" 0 > > > > > amixer set "PCM" 80% > > > > > ---------------------------------------------------------------------- > > > > > > > > > > -- s2.sh ------------------------------------------------------------- > > > > > #! /bin/sh > > > > > amixer set "PCM Capture Gain" 0 > > > > > amixer set "PCM Capture Gain" 2 > > > > > amixer set "PCM" 0 > > > > > amixer set "PCM" 80% > > > > > ---------------------------------------------------------------------- > > > > I used 'amixer set "PCM Capture Gain" 20' now in s2.sh only. Was this > > > the plan? Result: there is now an audible crack when s2.sh is > > > executed, but the volume before and after the cracks still seems to be > > > the same. > > > > The crack doesn't matter seriously, but just the volume. > > The volume is the same. > > Why is everything assigned twice (e.g. first 0 then 2) in this test? > > > > I also tried something else: when I alternate between > > > ---------------------------------------------------------------------- > > > amixer set "PCM Capture Gain" 0 > > > amixer set "PCM Capture Gain" 20 > > > amixer set "PCM" 0 > > > amixer set "PCM" 80% > > > ---------------------------------------------------------------------- > > > and > > > ---------------------------------------------------------------------- > > > amixer set "PCM" 0 > > > amixer set "PCM" 80% > > > amixer set "PCM Capture Gain" 0 > > > amixer set "PCM Capture Gain" 20 > > > ---------------------------------------------------------------------- > > > the recording has alternating load and quiete stretches. Whatever this > > > might tell us about the ADC, it looks like a bug to me: the order of > > > setting the two controls shouldn't matter. Or am I confused again? > > > > Well, assume that "PCM Capture" and "PCM Capture Gain" are > > independent. If so, the above two should result in the same state. > > > > If it's not independent but the register 4 & 5 take single values > > (that was the behavior of your original implementation), the above two > > cases must make a clear difference: in the former case, the gain is > > below 0dB, and in the latter it's +10dB. Was it so through your > > tests? > > Yes, the recording had alternating load and quite stretches, > corresponding to the two settings. > > So both tests seem to indicate that for the AK5365 registers 4 and 5 > take only a single value. Correct? Yes. Then we need to take the controls back to a single one. Will do later. I still wonder whether this is also true for AK4524... > > Also, it's possible that I did make a silly mistake. Put a debug > > printk around ak->ops.write() in snd_akm4xxx_write() to check what > > values are written to register 4 and 5. > > I will try this in the evening. Thanks, Takashi ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-07 10:33 ` Takashi Iwai @ 2006-09-07 11:00 ` Jochen Voss 2006-09-07 12:49 ` Takashi Iwai 0 siblings, 1 reply; 21+ messages in thread From: Jochen Voss @ 2006-09-07 11:00 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 2075 bytes --] Hello Takashi, On Thu, Sep 07, 2006 at 12:33:18PM +0200, Takashi Iwai wrote: > Yes. Then we need to take the controls back to a single one. > Will do later. Ok. > I still wonder whether this is also true for AK4524... No idea about this, I do not have an AK4524 so I cannot test. > > > Also, it's possible that I did make a silly mistake. Put a debug > > > printk around ak->ops.write() in snd_akm4xxx_write() to check what > > > values are written to register 4 and 5. > > > > I will try this in the evening. This sounded more fun than the simulation I am supposed to do for work, so I sneaked away and did this first ;-) I used the following printk: ====================================================================== --- ak4xxx-adda.c~ 2006-08-31 01:00:11.000000000 +0100 +++ ak4xxx-adda.c 2006-09-07 11:49:57.394999424 +0100 @@ -40,6 +40,9 @@ unsigned char val) { ak->ops.lock(ak, chip); + if (ak->type == SND_AK5365 && (reg==4 || reg==5)) { + printk (KERN_INFO "reg%d <- %02x\n", reg, val); + } ak->ops.write(ak, chip, reg, val); /* save the data */ ====================================================================== Results from my second test (s2.sh vs s3.sh): s2.sh: The commands amixer set "PCM Capture Gain" 0 amixer set "PCM Capture Gain" 20 amixer set "PCM" 0 amixer set "PCM" 80% translate into reg4 <- 80 reg5 <- 80 reg4 <- 94 reg5 <- 94 reg4 <- 00 reg5 <- 00 reg4 <- 5e reg5 <- 5e s3.sh: The commands amixer set "PCM" 0 amixer set "PCM" 80% amixer set "PCM Capture Gain" 0 amixer set "PCM Capture Gain" 20 translate into reg4 <- 00 reg5 <- 00 reg4 <- 5e reg5 <- 5e reg4 <- 80 reg5 <- 80 reg4 <- 94 reg5 <- 94 This seems to be the expected register assignments. As stated before, these settings lead to different recording volume. All the best, Jochen -- http://seehuhn.de/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-07 11:00 ` Jochen Voss @ 2006-09-07 12:49 ` Takashi Iwai 2006-09-07 14:52 ` Takashi Iwai 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-07 12:49 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel At Thu, 7 Sep 2006 12:00:30 +0100, Jochen Voss wrote: > > Hello Takashi, > > On Thu, Sep 07, 2006 at 12:33:18PM +0200, Takashi Iwai wrote: > > Yes. Then we need to take the controls back to a single one. > > Will do later. > Ok. > > > I still wonder whether this is also true for AK4524... > No idea about this, I do not have an AK4524 so I cannot test. > > > > > Also, it's possible that I did make a silly mistake. Put a debug > > > > printk around ak->ops.write() in snd_akm4xxx_write() to check what > > > > values are written to register 4 and 5. > > > > > > I will try this in the evening. > > This sounded more fun than the simulation I am supposed to do for work, > so I sneaked away and did this first ;-) > > I used the following printk: > > ====================================================================== > --- ak4xxx-adda.c~ 2006-08-31 01:00:11.000000000 +0100 > +++ ak4xxx-adda.c 2006-09-07 11:49:57.394999424 +0100 > @@ -40,6 +40,9 @@ > unsigned char val) > { > ak->ops.lock(ak, chip); > + if (ak->type == SND_AK5365 && (reg==4 || reg==5)) { > + printk (KERN_INFO "reg%d <- %02x\n", reg, val); > + } > ak->ops.write(ak, chip, reg, val); > > /* save the data */ > ====================================================================== > > Results from my second test (s2.sh vs s3.sh): > > s2.sh: The commands > > amixer set "PCM Capture Gain" 0 > amixer set "PCM Capture Gain" 20 > amixer set "PCM" 0 > amixer set "PCM" 80% > > translate into > > reg4 <- 80 > reg5 <- 80 > reg4 <- 94 > reg5 <- 94 > reg4 <- 00 > reg5 <- 00 > reg4 <- 5e > reg5 <- 5e > > s3.sh: The commands > > amixer set "PCM" 0 > amixer set "PCM" 80% > amixer set "PCM Capture Gain" 0 > amixer set "PCM Capture Gain" 20 > > translate into > > reg4 <- 00 > reg5 <- 00 > reg4 <- 5e > reg5 <- 5e > reg4 <- 80 > reg5 <- 80 > reg4 <- 94 > reg5 <- 94 > > This seems to be the expected register assignments. As stated before, > these settings lead to different recording volume. OK, thanks for confirmation. The untested patch for removing IPGA is below. Please give it a shot. I'll check a board with AK4524 (well I have to dig the boxes) whether it shows shows the same behavior like AK5365. Takashi diff -r 4f27a5064cda i2c/other/ak4xxx-adda.c --- a/i2c/other/ak4xxx-adda.c Thu Sep 07 12:40:00 2006 +0200 +++ b/i2c/other/ak4xxx-adda.c Thu Sep 07 14:46:39 2006 +0200 @@ -324,13 +324,15 @@ EXPORT_SYMBOL(snd_akm4xxx_init); /* * Mixer callbacks */ +#define AK_IPGA (1<<20) /* including IPGA */ #define AK_VOL_CVT (1<<21) /* need dB conversion */ #define AK_NEEDSMSB (1<<22) /* need MSB update bit */ #define AK_INVERT (1<<23) /* data is inverted */ #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) #define AK_GET_ADDR(val) ((val) & 0xff) -#define AK_GET_SHIFT(val) (((val) >> 16) & 0x1f) +#define AK_GET_SHIFT(val) (((val) >> 16) & 0x0f) #define AK_GET_VOL_CVT(val) (((val) >> 21) & 1) +#define AK_GET_IPGA(val) (((val) >> 20) & 1) #define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1) #define AK_GET_INVERT(val) (((val) >> 23) & 1) #define AK_GET_MASK(val) (((val) >> 24) & 0xff) @@ -371,8 +373,10 @@ static int put_ak_reg(struct snd_kcontro return 0; snd_akm4xxx_set_vol(ak, chip, addr, nval); - if (AK_GET_VOL_CVT(kcontrol->private_value)) + if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128) nval = vol_cvt_datt[nval]; + if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128) + nval++; if (AK_GET_INVERT(kcontrol->private_value)) nval = mask - nval; if (AK_GET_NEEDSMSB(kcontrol->private_value)) @@ -702,13 +706,21 @@ static int build_adc_controls(struct snd knew.put = snd_akm4xxx_volume_put; } /* register 4 & 5 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | - AK_VOL_CVT; + if (ak->type == SND_AK5365) + knew.private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | + AK_VOL_CVT | AK_IPGA; + else + knew.private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | + AK_VOL_CVT; knew.tlv.p = db_scale_vol_datt; err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); if (err < 0) return err; + + if (ak->type == SND_AK5365) + goto no_ipga; if (! ak->adc_info || ! ak->adc_info[mixer_ch].gain_name) knew.name = "IPGA Analog Capture Volume"; @@ -723,18 +735,13 @@ static int build_adc_controls(struct snd knew.get = snd_akm4xxx_ipga_gain_get; knew.put = snd_akm4xxx_ipga_gain_put; } - /* register 4 & 5 */ - if (ak->type == SND_AK4524) - knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, - 24); - else /* AK5365 */ - knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, - 36); + knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 36); knew.tlv.p = db_scale_ipga; err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); if (err < 0) return err; + no_ipga: if (ak->type == SND_AK5365 && (idx % 2) == 0) { if (! ak->adc_info || ! ak->adc_info[mixer_ch].switch_name) ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-07 12:49 ` Takashi Iwai @ 2006-09-07 14:52 ` Takashi Iwai 2006-09-07 22:18 ` Jochen Voss 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-07 14:52 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel [-- Attachment #1: Type: text/plain, Size: 2947 bytes --] At Thu, 07 Sep 2006 14:49:24 +0200, I wrote: > > At Thu, 7 Sep 2006 12:00:30 +0100, > Jochen Voss wrote: > > > > Hello Takashi, > > > > On Thu, Sep 07, 2006 at 12:33:18PM +0200, Takashi Iwai wrote: > > > Yes. Then we need to take the controls back to a single one. > > > Will do later. > > Ok. > > > > > I still wonder whether this is also true for AK4524... > > No idea about this, I do not have an AK4524 so I cannot test. > > > > > > > Also, it's possible that I did make a silly mistake. Put a debug > > > > > printk around ak->ops.write() in snd_akm4xxx_write() to check what > > > > > values are written to register 4 and 5. > > > > > > > > I will try this in the evening. > > > > This sounded more fun than the simulation I am supposed to do for work, > > so I sneaked away and did this first ;-) > > > > I used the following printk: > > > > ====================================================================== > > --- ak4xxx-adda.c~ 2006-08-31 01:00:11.000000000 +0100 > > +++ ak4xxx-adda.c 2006-09-07 11:49:57.394999424 +0100 > > @@ -40,6 +40,9 @@ > > unsigned char val) > > { > > ak->ops.lock(ak, chip); > > + if (ak->type == SND_AK5365 && (reg==4 || reg==5)) { > > + printk (KERN_INFO "reg%d <- %02x\n", reg, val); > > + } > > ak->ops.write(ak, chip, reg, val); > > > > /* save the data */ > > ====================================================================== > > > > Results from my second test (s2.sh vs s3.sh): > > > > s2.sh: The commands > > > > amixer set "PCM Capture Gain" 0 > > amixer set "PCM Capture Gain" 20 > > amixer set "PCM" 0 > > amixer set "PCM" 80% > > > > translate into > > > > reg4 <- 80 > > reg5 <- 80 > > reg4 <- 94 > > reg5 <- 94 > > reg4 <- 00 > > reg5 <- 00 > > reg4 <- 5e > > reg5 <- 5e > > > > s3.sh: The commands > > > > amixer set "PCM" 0 > > amixer set "PCM" 80% > > amixer set "PCM Capture Gain" 0 > > amixer set "PCM Capture Gain" 20 > > > > translate into > > > > reg4 <- 00 > > reg5 <- 00 > > reg4 <- 5e > > reg5 <- 5e > > reg4 <- 80 > > reg5 <- 80 > > reg4 <- 94 > > reg5 <- 94 > > > > This seems to be the expected register assignments. As stated before, > > these settings lead to different recording volume. > > OK, thanks for confirmation. > > The untested patch for removing IPGA is below. Please give it a > shot. > > I'll check a board with AK4524 (well I have to dig the boxes) whether > it shows shows the same behavior like AK5365. I confirmed that the same behavior appears on AK4524. So, it makes much more sense to combine ADC and IPGA controls to a single control. The patch below is the final version I have on my local tree. Please check whether it works for you. FYI, the second patch is for envy24control to make it work correctly after changing ADC ranges. Takashi [-- Attachment #2: ak4xxx-adda-ipga-fix.diff --] [-- Type: application/octet-stream, Size: 8220 bytes --] diff -r 4f27a5064cda i2c/other/ak4xxx-adda.c --- a/i2c/other/ak4xxx-adda.c Thu Sep 07 12:40:00 2006 +0200 +++ b/i2c/other/ak4xxx-adda.c Thu Sep 07 16:50:00 2006 +0200 @@ -43,10 +43,7 @@ void snd_akm4xxx_write(struct snd_akm4xx ak->ops.write(ak, chip, reg, val); /* save the data */ - /* don't overwrite with IPGA data */ - if ((ak->type != SND_AK4524 && ak->type != SND_AK5365) || - (reg != 0x04 && reg != 0x05) || (val & 0x80) == 0) - snd_akm4xxx_set(ak, chip, reg, val); + snd_akm4xxx_set(ak, chip, reg, val); ak->ops.unlock(ak, chip); } @@ -70,12 +67,6 @@ static void ak4524_reset(struct snd_akm4 for (reg = 0x04; reg < maxreg; reg++) snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get(ak, chip, reg)); - if (ak->type == SND_AK4528) - continue; - /* IPGA */ - for (reg = 0x04; reg < 0x06; reg++) - snd_akm4xxx_write(ak, chip, reg, - snd_akm4xxx_get_ipga(ak, chip, reg) | 0x80); } } @@ -175,7 +166,6 @@ static DECLARE_TLV_DB_SCALE(db_scale_8bi static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); -static DECLARE_TLV_DB_SCALE(db_scale_ipga, 0, 50, 0); /* * initialize all the ak4xxx chips @@ -190,8 +180,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx 0x01, 0x03, /* 1: ADC/DAC enable */ 0x04, 0x00, /* 4: ADC left muted */ 0x05, 0x00, /* 5: ADC right muted */ - 0x04, 0x80, /* 4: ADC IPGA gain 0dB */ - 0x05, 0x80, /* 5: ADC IPGA gain 0dB */ 0x06, 0x00, /* 6: DAC left muted */ 0x07, 0x00, /* 7: DAC right muted */ 0xff, 0xff @@ -324,13 +312,15 @@ EXPORT_SYMBOL(snd_akm4xxx_init); /* * Mixer callbacks */ +#define AK_IPGA (1<<20) /* including IPGA */ #define AK_VOL_CVT (1<<21) /* need dB conversion */ #define AK_NEEDSMSB (1<<22) /* need MSB update bit */ #define AK_INVERT (1<<23) /* data is inverted */ #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) #define AK_GET_ADDR(val) ((val) & 0xff) -#define AK_GET_SHIFT(val) (((val) >> 16) & 0x1f) +#define AK_GET_SHIFT(val) (((val) >> 16) & 0x0f) #define AK_GET_VOL_CVT(val) (((val) >> 21) & 1) +#define AK_GET_IPGA(val) (((val) >> 20) & 1) #define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1) #define AK_GET_INVERT(val) (((val) >> 23) & 1) #define AK_GET_MASK(val) (((val) >> 24) & 0xff) @@ -371,8 +361,10 @@ static int put_ak_reg(struct snd_kcontro return 0; snd_akm4xxx_set_vol(ak, chip, addr, nval); - if (AK_GET_VOL_CVT(kcontrol->private_value)) + if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128) nval = vol_cvt_datt[nval]; + if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128) + nval++; /* need to correct + 1 since both 127 and 128 are 0dB */ if (AK_GET_INVERT(kcontrol->private_value)) nval = mask - nval; if (AK_GET_NEEDSMSB(kcontrol->private_value)) @@ -421,68 +413,6 @@ static int snd_akm4xxx_stereo_volume_put change = put_ak_reg(kcontrol, addr, ucontrol->value.integer.value[0]); change |= put_ak_reg(kcontrol, addr + 1, ucontrol->value.integer.value[1]); - return change; -} - -#define snd_akm4xxx_ipga_gain_info snd_akm4xxx_volume_info - -static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - - ucontrol->value.integer.value[0] = - snd_akm4xxx_get_ipga(ak, chip, addr); - return 0; -} - -static int put_ak_ipga(struct snd_kcontrol *kcontrol, int addr, - unsigned char nval) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - - if (snd_akm4xxx_get_ipga(ak, chip, addr) == nval) - return 0; - snd_akm4xxx_set_ipga(ak, chip, addr, nval); - snd_akm4xxx_write(ak, chip, addr, nval | 0x80); /* need MSB */ - return 1; -} - -static int snd_akm4xxx_ipga_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return put_ak_ipga(kcontrol, AK_GET_ADDR(kcontrol->private_value), - ucontrol->value.integer.value[0]); -} - -#define snd_akm4xxx_stereo_gain_info snd_akm4xxx_stereo_volume_info - -static int snd_akm4xxx_stereo_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - - ucontrol->value.integer.value[0] = - snd_akm4xxx_get_ipga(ak, chip, addr); - ucontrol->value.integer.value[1] = - snd_akm4xxx_get_ipga(ak, chip, addr + 1); - return 0; -} - -static int snd_akm4xxx_stereo_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int addr = AK_GET_ADDR(kcontrol->private_value); - int change; - - change = put_ak_ipga(kcontrol, addr, ucontrol->value.integer.value[0]); - change |= put_ak_ipga(kcontrol, addr + 1, - ucontrol->value.integer.value[1]); return change; } @@ -702,35 +632,15 @@ static int build_adc_controls(struct snd knew.put = snd_akm4xxx_volume_put; } /* register 4 & 5 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | - AK_VOL_CVT; + if (ak->type == SND_AK5365) + knew.private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | + AK_VOL_CVT | AK_IPGA; + else + knew.private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | + AK_VOL_CVT | AK_IPGA; knew.tlv.p = db_scale_vol_datt; - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - - if (! ak->adc_info || ! ak->adc_info[mixer_ch].gain_name) - knew.name = "IPGA Analog Capture Volume"; - else - knew.name = ak->adc_info[mixer_ch].gain_name; - if (num_stereo == 2) { - knew.info = snd_akm4xxx_stereo_gain_info; - knew.get = snd_akm4xxx_stereo_gain_get; - knew.put = snd_akm4xxx_stereo_gain_put; - } else { - knew.info = snd_akm4xxx_ipga_gain_info; - knew.get = snd_akm4xxx_ipga_gain_get; - knew.put = snd_akm4xxx_ipga_gain_put; - } - /* register 4 & 5 */ - if (ak->type == SND_AK4524) - knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, - 24); - else /* AK5365 */ - knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, - 36); - knew.tlv.p = db_scale_ipga; err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); if (err < 0) return err; @@ -811,11 +721,9 @@ int snd_akm4xxx_build_controls(struct sn if (err < 0) return err; - if (ak->type == SND_AK4524 || ak->type == SND_AK5365) { - err = build_adc_controls(ak); - if (err < 0) - return err; - } + err = build_adc_controls(ak); + if (err < 0) + return err; if (ak->type == SND_AK4355 || ak->type == SND_AK4358) num_emphs = 1; diff -r 4f27a5064cda include/ak4xxx-adda.h --- a/include/ak4xxx-adda.h Thu Sep 07 12:40:00 2006 +0200 +++ b/include/ak4xxx-adda.h Thu Sep 07 16:47:07 2006 +0200 @@ -48,7 +48,6 @@ struct snd_akm4xxx_dac_channel { /* ADC labels and channels */ struct snd_akm4xxx_adc_channel { char *name; /* capture gain volume label */ - char *gain_name; /* IPGA */ char *switch_name; /* capture switch */ unsigned int num_channels; }; @@ -91,13 +90,4 @@ int snd_akm4xxx_build_controls(struct sn #define snd_akm4xxx_set_vol(ak,chip,reg,val) \ ((ak)->volumes[(chip) * 16 + (reg)] = (val)) -/* Warning: IPGA is tricky - we assume the addr + 4 is unused - * so far, it's OK for all AK codecs with IPGA: - * AK4524, AK4528 and EK5365 - */ -#define snd_akm4xxx_get_ipga(ak,chip,reg) \ - snd_akm4xxx_get_vol(ak, chip, (reg) + 4) -#define snd_akm4xxx_set_ipga(ak,chip,reg,val) \ - snd_akm4xxx_set_vol(ak, chip, (reg) + 4, val) - #endif /* __SOUND_AK4XXX_ADDA_H */ diff -r 4f27a5064cda pci/ice1712/revo.c --- a/pci/ice1712/revo.c Thu Sep 07 12:40:00 2006 +0200 +++ b/pci/ice1712/revo.c Thu Sep 07 16:47:37 2006 +0200 @@ -110,7 +110,6 @@ static struct snd_akm4xxx_adc_channel re static struct snd_akm4xxx_adc_channel revo51_adc[] = { { .name = "PCM Capture Volume", - .gain_name = "PCM Capture Gain Volume", .switch_name = "PCM Capture Switch", .num_channels = 2 }, [-- Attachment #3: envy24-ipga-fix.diff --] [-- Type: application/octet-stream, Size: 2368 bytes --] diff -r 1b93db14895f envy24control/envy24control.c --- a/envy24control/envy24control.c Fri Aug 04 14:28:19 2006 +0200 +++ b/envy24control/envy24control.c Thu Sep 07 16:40:10 2006 +0200 @@ -1570,7 +1570,7 @@ static void create_analog_volume(GtkWidg gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 6); } - adj = gtk_adjustment_new(0, -127, 0, 1, 16, 0); + adj = gtk_adjustment_new(0, -(envy_adc_max()), 0, 1, 16, 0); av_adc_volume_adj[i] = adj; vscale = gtk_vscale_new(GTK_ADJUSTMENT(adj)); gtk_scale_set_draw_value(GTK_SCALE(vscale), FALSE); diff -r 1b93db14895f envy24control/envy24control.h --- a/envy24control/envy24control.h Fri Aug 04 14:28:19 2006 +0200 +++ b/envy24control/envy24control.h Thu Sep 07 16:40:20 2006 +0200 @@ -217,6 +217,7 @@ int envy_dac_volumes(void); int envy_dac_volumes(void); int envy_dac_max(void); int envy_adc_volumes(void); +int envy_adc_max(void); int envy_ipga_volumes(void); int envy_dac_senses(void); int envy_adc_senses(void); diff -r 1b93db14895f envy24control/volume.c --- a/envy24control/volume.c Fri Aug 04 14:28:19 2006 +0200 +++ b/envy24control/volume.c Thu Sep 07 16:44:41 2006 +0200 @@ -33,6 +33,7 @@ static int dac_volumes; static int dac_max = 127; +static int adc_max = 127; static int adc_volumes; static int ipga_volumes; static int dac_senses; @@ -58,6 +59,11 @@ int envy_adc_volumes(void) return adc_volumes; } +int envy_adc_max(void) +{ + return adc_max; +} + int envy_ipga_volumes(void) { return ipga_volumes; @@ -138,8 +144,9 @@ void adc_volume_update(int idx) g_print("Unable to read ipga volume: %s\n", snd_strerror(err)); return; } - gtk_adjustment_set_value(GTK_ADJUSTMENT(av_ipga_volume_adj[idx]), - -0); + if (ipga_volumes > 0) + gtk_adjustment_set_value(GTK_ADJUSTMENT(av_ipga_volume_adj[idx]), + -0); } void ipga_volume_update(int idx) @@ -165,7 +172,7 @@ void ipga_volume_update(int idx) // set ADC volume to max if IPGA volume greater 0 if (ipga_vol) gtk_adjustment_set_value(GTK_ADJUSTMENT(av_adc_volume_adj[idx]), - -127); + -adc_max); } void dac_sense_update(int idx) @@ -342,6 +349,7 @@ void analog_volume_init(void) snd_ctl_elem_info_set_index(info, i); if (snd_ctl_elem_info(ctl, info) < 0) break; + adc_max = snd_ctl_elem_info_get_max(info); } if (i < input_channels - 1) adc_volumes = i; [-- Attachment #4: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #5: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-07 14:52 ` Takashi Iwai @ 2006-09-07 22:18 ` Jochen Voss 2006-09-08 10:32 ` Takashi Iwai 0 siblings, 1 reply; 21+ messages in thread From: Jochen Voss @ 2006-09-07 22:18 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 2301 bytes --] Hi Takashi, On Thu, Sep 07, 2006 at 04:52:58PM +0200, Takashi Iwai wrote: > I confirmed that the same behavior appears on AK4524. > So, it makes much more sense to combine ADC and IPGA controls to a > single control. Great, this should simplify things considerably. > The patch below is the final version I have on my local tree. > Please check whether it works for you. It works nice. I now get Simple mixer control 'PCM',0 Capabilities: pvolume cvolume cswitch cswitch-joined Playback channels: Front Left - Front Right Capture channels: Front Left - Front Right Limits: Playback 0 - 127 Capture 0 - 151 Front Left: Playback 127 [100%] Capture 0 [0%] [on] Front Right: Playback 127 [100%] Capture 151 [100%] [on] One remaining problem: Unfortunatly left and right volume are exchanged when recording. When I record with the setting above (using arecord) and then replay the recording with aplay all the sound comes from the left (!) speaker. I reactivated my register write spying patch and got reg4 <- 00 reg5 <- 98 for the setting above. So the actual register writes seem to be ok. It seems that register 5 corresponds to the left channel (and 4 to the right channel) on the revolution 5.1 card. Otherwise everything seems fine. Minor nit: the code (from ak4xxx-adda.c) /* register 4 & 5 */ if (ak->type == SND_AK5365) knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | AK_VOL_CVT | AK_IPGA; else knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | AK_VOL_CVT | AK_IPGA; looks unnecessarily complicated. The AK5365 has just two channels, so shouldn't it be just as follows? /* register 4 & 5 */ if (ak->type == SND_AK5365) knew.private_value = AK_COMPOSE(0, idx + 4, 0, 151) | AK_VOL_CVT | AK_IPGA; else knew.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | AK_VOL_CVT | AK_IPGA; > FYI, the second patch is for envy24control to make it work correctly > after changing ADC ranges. I only tried envy24control a long time ago. Then it didn't recognise my card and I ignored it afterwards. Is it useful? Should I give this a try? Many thanks, Jochen -- http://seehuhn.de/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-07 22:18 ` Jochen Voss @ 2006-09-08 10:32 ` Takashi Iwai 2006-09-10 22:38 ` Jochen Voss 0 siblings, 1 reply; 21+ messages in thread From: Takashi Iwai @ 2006-09-08 10:32 UTC (permalink / raw) To: Jochen Voss; +Cc: alsa-devel At Thu, 7 Sep 2006 23:18:45 +0100, Jochen Voss wrote: > > Hi Takashi, > > On Thu, Sep 07, 2006 at 04:52:58PM +0200, Takashi Iwai wrote: > > I confirmed that the same behavior appears on AK4524. > > So, it makes much more sense to combine ADC and IPGA controls to a > > single control. > Great, this should simplify things considerably. > > > The patch below is the final version I have on my local tree. > > Please check whether it works for you. > It works nice. I now get > > Simple mixer control 'PCM',0 > Capabilities: pvolume cvolume cswitch cswitch-joined > Playback channels: Front Left - Front Right > Capture channels: Front Left - Front Right > Limits: Playback 0 - 127 Capture 0 - 151 > Front Left: Playback 127 [100%] Capture 0 [0%] [on] > Front Right: Playback 127 [100%] Capture 151 [100%] [on] > > One remaining problem: Unfortunatly left and right volume are > exchanged when recording. When I record with the setting above (using > arecord) and then replay the recording with aplay all the sound comes > from the left (!) speaker. > > I reactivated my register write spying patch and got > > reg4 <- 00 > reg5 <- 98 > > for the setting above. So the actual register writes seem to be ok. > It seems that register 5 corresponds to the left channel (and 4 to the > right channel) on the revolution 5.1 card. Hm, this is a bit weird. Could you double-check this? > Otherwise everything seems fine. OK, I committed the patch to ALSA HG tree now. > Minor nit: the code (from ak4xxx-adda.c) > > /* register 4 & 5 */ > if (ak->type == SND_AK5365) > knew.private_value = > AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | > AK_VOL_CVT | AK_IPGA; > else > knew.private_value = > AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | > AK_VOL_CVT | AK_IPGA; > > looks unnecessarily complicated. The AK5365 has just two channels, so > shouldn't it be just as follows? > > /* register 4 & 5 */ > if (ak->type == SND_AK5365) > knew.private_value = > AK_COMPOSE(0, idx + 4, 0, 151) | > AK_VOL_CVT | AK_IPGA; > else > knew.private_value = > AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | > AK_VOL_CVT | AK_IPGA; The code above is for the cases with multiple codecs, i.e. when two or more AK5365 codecs are connected to a single controller. > > > FYI, the second patch is for envy24control to make it work correctly > > after changing ADC ranges. > I only tried envy24control a long time ago. Then it didn't recognise my > card and I ignored it afterwards. Is it useful? Should I give this a try? Not really for VT1720/1724. Many functions of Envy24 were stripped, and thus many features envy24control provides are not supported by VT1720/1724 chips. thanks, Takashi ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 ^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC] Add dB scale information to AK4xxx codec 2006-09-08 10:32 ` Takashi Iwai @ 2006-09-10 22:38 ` Jochen Voss 0 siblings, 0 replies; 21+ messages in thread From: Jochen Voss @ 2006-09-10 22:38 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel [-- Attachment #1.1: Type: text/plain, Size: 1326 bytes --] Hi Takashi, On Fri, Sep 08, 2006 at 12:32:33PM +0200, Takashi Iwai wrote: > > One remaining problem: Unfortunatly left and right volume are > > exchanged when recording. When I record with the setting above (using > > arecord) and then replay the recording with aplay all the sound comes > > from the left (!) speaker. > > > > I reactivated my register write spying patch and got > > > > reg4 <- 00 > > reg5 <- 98 > > > > for the setting above. So the actual register writes seem to be ok. > > It seems that register 5 corresponds to the left channel (and 4 to the > > right channel) on the revolution 5.1 card. > > Hm, this is a bit weird. Could you double-check this? I did now and the result seems repeatable. Maybe we should try to find another REvolution 5.1 owner to double check (to make sure that it is not just a weird defect of my card or so). See my recent mail to the list for details. Any hints on what else I could try would be most welcome. > > Otherwise everything seems fine. > > OK, I committed the patch to ALSA HG tree now. Thank you. > > [ ... ] > > The code above is for the cases with multiple codecs, i.e. when two or > more AK5365 codecs are connected to a single controller. Ok, I see. All the best, Jochen -- http://seehuhn.de/ [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 373 bytes --] ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 [-- Attachment #3: Type: text/plain, Size: 161 bytes --] _______________________________________________ Alsa-devel mailing list Alsa-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/alsa-devel ^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2006-09-10 22:38 UTC | newest] Thread overview: 21+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-08-28 11:38 [RFC] Add dB scale information to AK4xxx codec Takashi Iwai 2006-08-28 14:52 ` Takashi Iwai 2006-09-03 15:53 ` Jochen Voss 2006-09-04 9:58 ` Takashi Iwai 2006-09-04 11:13 ` Jochen Voß 2006-09-04 11:35 ` Takashi Iwai 2006-09-04 12:12 ` Jochen Voß 2006-09-04 17:41 ` Jochen Voss 2006-09-04 18:28 ` Takashi Iwai 2006-09-04 19:27 ` Jochen Voss 2006-09-05 9:36 ` Takashi Iwai 2006-09-05 19:24 ` Jochen Voss 2006-09-07 10:09 ` Takashi Iwai 2006-09-07 10:29 ` Jochen Voss 2006-09-07 10:33 ` Takashi Iwai 2006-09-07 11:00 ` Jochen Voss 2006-09-07 12:49 ` Takashi Iwai 2006-09-07 14:52 ` Takashi Iwai 2006-09-07 22:18 ` Jochen Voss 2006-09-08 10:32 ` Takashi Iwai 2006-09-10 22:38 ` Jochen Voss
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.