? alsa-driver/alsa-kernel/pci/ca0106/.ca0106_mixer.c.swp
? alsa-driver/alsa-kernel/pci/emu10k1/private_value
Index: alsa-driver/alsa-kernel/core/control.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/control.c,v
retrieving revision 1.69
diff -u -r1.69 control.c
--- alsa-driver/alsa-kernel/core/control.c	20 Nov 2005 14:06:59 -0000	1.69
+++ alsa-driver/alsa-kernel/core/control.c	22 Dec 2005 22:28:04 -0000
@@ -237,6 +237,7 @@
 	kctl.info = ncontrol->info;
 	kctl.get = ncontrol->get;
 	kctl.put = ncontrol->put;
+	kctl.db_scale = ncontrol->db_scale;
 	kctl.private_value = ncontrol->private_value;
 	kctl.private_data = private_data;
 	return snd_ctl_new(&kctl, access);
@@ -547,6 +548,138 @@
 	return 0;
 }
 
+static int uint32_to_message(struct snd_ctl_misc *misc, unsigned int value)
+{
+	unsigned int pointer = misc->length;
+	/* If unsigned int is a 64bit value, we will just ignore the high 32bits. */
+	misc->message[pointer++] = value & 0xff;
+	misc->message[pointer++] = (value >> 8) & 0xff;
+	misc->message[pointer++] = (value >> 16) & 0xff;
+	misc->message[pointer++] = (value >> 24) & 0xff;
+	misc->length = pointer;
+	return 0;
+}
+
+static int message_to_uint32(struct snd_ctl_misc *misc, unsigned int *value)
+{
+	unsigned int pointer = misc->length;
+	unsigned int val;
+	val = misc->message[pointer++] ;
+	val |= ((misc->message[pointer++]) << 8);
+	val |= ((misc->message[pointer++]) << 16);
+	val |= ((misc->message[pointer++]) << 24);
+	misc->length = pointer;
+	*value = val;
+	return 0;
+}
+
+
+static int add_int32_tlv_to_container(struct snd_ctl_misc *misc, unsigned int type, unsigned int value)
+{
+	uint32_to_message(misc, type);
+	uint32_to_message(misc, 4);
+	uint32_to_message(misc, value);
+	/* FIXME: Check for overflows */
+	return 0;
+}
+
+
+static int container_open(struct snd_ctl_misc *misc, unsigned int type)
+{
+	uint32_to_message(misc, type);
+	uint32_to_message(misc, 0); /* This gets updated at container close */
+	return 0;
+}
+
+static int container_close(struct snd_ctl_misc *misc)
+{
+	unsigned int pointer = 4;
+	unsigned int value = misc->length;
+	misc->message[pointer++] = value & 0xff;
+	misc->message[pointer++] = (value >> 8) & 0xff;
+	misc->message[pointer++] = (value >> 16) & 0xff;
+	misc->message[pointer++] = (value >> 24) & 0xff;
+	return 0;
+}
+
+static int snd_ctl_misc_user(struct snd_ctl_file *ctl,
+				  struct snd_ctl_misc __user *_misc)
+{
+	struct snd_ctl_misc *misc;
+	struct snd_card *card = ctl->card;
+	struct snd_kcontrol *kctl;
+	int result=0;
+	int numid;
+	unsigned int received_length;
+	unsigned int tlv_type;
+	unsigned int tlv_length;
+	unsigned int tlv_value;
+	unsigned int container_type;
+	unsigned int container_length;
+	
+	misc = kmalloc(2048, GFP_KERNEL);
+	if (misc == NULL)
+		return -ENOMEM;	
+	if (copy_from_user(misc, _misc, 2048)) {
+		result = -EFAULT;
+		goto exit_free;
+	}
+	received_length = misc->length;
+	misc->length=0;
+	message_to_uint32(misc, &container_type);
+	switch (container_type) {
+		case SND_MISC_DB_SCALE:
+			message_to_uint32(misc, &container_length);
+			/* FIXME: Do more sanity checks here */
+			message_to_uint32(misc, &tlv_type);
+			switch (tlv_type) {
+				case SND_MISC_ELEM_NUMID:
+					message_to_uint32(misc, &tlv_length);
+					if (tlv_length != 4) {
+						result = -EINVAL;
+						goto exit_free;
+					}
+					message_to_uint32(misc, &tlv_value);
+					break;
+				default:
+					result = -EINVAL;
+					goto exit_free;
+					break;
+			}
+			break;
+		default:
+			result = -EINVAL;
+			goto exit_free;
+	}
+	numid=tlv_value;
+	//snd_printk("numid=%d\n", tlv_value);
+	down_read(&card->controls_rwsem);
+	kctl = snd_ctl_find_numid(card, numid);
+	if (kctl == NULL) {
+		result = -ENOENT;
+		snd_printk("exit_up1\n");
+		goto exit_up;
+	}
+	if (kctl->db_scale == 0) { /* Value defaults to zero when not implemented. */
+		result = -EINVAL;
+		goto exit_up;
+	}
+	misc->version=1;
+	misc->length=0;
+	container_open(misc, SND_MISC_DB_SCALE);
+	add_int32_tlv_to_container(misc, SND_MISC_ELEM_DB_SCALE, kctl->db_scale);
+	container_close(misc);
+	if (copy_to_user(_misc, misc, 2048))
+		result = -EFAULT;
+	
+exit_up:
+	up_read(&card->controls_rwsem);
+exit_free:
+	kfree(misc);
+exit:
+	return result;
+}
+
 static int snd_ctl_elem_list(struct snd_card *card,
 			     struct snd_ctl_elem_list __user *_list)
 {
@@ -1062,6 +1195,8 @@
 		return snd_ctl_elem_add_user(ctl, argp, 1);
 	case SNDRV_CTL_IOCTL_ELEM_REMOVE:
 		return snd_ctl_elem_remove(ctl, argp);
+	case SNDRV_CTL_IOCTL_MISC:
+		return snd_ctl_misc_user(ctl, argp);
 	case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
 		return snd_ctl_subscribe_events(ctl, ip);
 	case SNDRV_CTL_IOCTL_POWER:
Index: alsa-driver/alsa-kernel/include/asound.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/include/asound.h,v
retrieving revision 1.57
diff -u -r1.57 asound.h
--- alsa-driver/alsa-kernel/include/asound.h	17 Nov 2005 13:51:18 -0000	1.57
+++ alsa-driver/alsa-kernel/include/asound.h	22 Dec 2005 22:28:04 -0000
@@ -818,6 +818,18 @@
         unsigned char reserved[128-sizeof(struct timespec)];
 };
 
+struct snd_ctl_misc {
+	u32 version;
+	u32 length;
+	unsigned char message[];
+};
+
+#define SND_MISC_DB_SCALE 2
+/* Request */
+#define SND_MISC_ELEM_NUMID 2
+/* Response */
+#define SND_MISC_ELEM_DB_SCALE 2
+
 enum {
 	SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
 	SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
@@ -833,6 +845,7 @@
 	SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
 	SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
 	SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
+	SNDRV_CTL_IOCTL_MISC = _IOR('U', 0x22, struct snd_ctl_misc),
 	SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
 	SNDRV_CTL_IOCTL_PCM_INFO = _IOWR('U', 0x31, struct snd_pcm_info),
 	SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE = _IOW('U', 0x32, int),
Index: alsa-driver/alsa-kernel/include/control.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/include/control.h,v
retrieving revision 1.14
diff -u -r1.14 control.h
--- alsa-driver/alsa-kernel/include/control.h	17 Nov 2005 13:53:23 -0000	1.14
+++ alsa-driver/alsa-kernel/include/control.h	22 Dec 2005 22:28:04 -0000
@@ -42,6 +42,7 @@
 	snd_kcontrol_info_t *info;
 	snd_kcontrol_get_t *get;
 	snd_kcontrol_put_t *put;
+	unsigned int db_scale;
 	unsigned long private_value;
 };
 
@@ -58,6 +59,7 @@
 	snd_kcontrol_info_t *info;
 	snd_kcontrol_get_t *get;
 	snd_kcontrol_put_t *put;
+	unsigned int db_scale;
 	unsigned long private_value;
 	void *private_data;
 	void (*private_free)(struct snd_kcontrol *kcontrol);
Index: alsa-driver/alsa-kernel/include/emu10k1.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/include/emu10k1.h,v
retrieving revision 1.78
diff -u -r1.78 emu10k1.h
--- alsa-driver/alsa-kernel/include/emu10k1.h	21 Dec 2005 15:06:08 -0000	1.78
+++ alsa-driver/alsa-kernel/include/emu10k1.h	22 Dec 2005 22:28:05 -0000
@@ -1522,6 +1522,7 @@
 	unsigned int value[32];		/* initial values */
 	unsigned int min;		/* minimum range */
 	unsigned int max;		/* maximum range */
+	unsigned int db_scale;		/* dB scale */
 	unsigned int translation;	/* translation type (EMU10K1_GPR_TRANSLATION*) */
 };
 
Index: alsa-driver/alsa-kernel/pci/ca0106/ca0106_mixer.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ca0106/ca0106_mixer.c,v
retrieving revision 1.10
diff -u -r1.10 ca0106_mixer.c
--- alsa-driver/alsa-kernel/pci/ca0106/ca0106_mixer.c	16 Dec 2005 21:59:59 -0000	1.10
+++ alsa-driver/alsa-kernel/pci/ca0106/ca0106_mixer.c	22 Dec 2005 22:28:05 -0000
@@ -329,37 +329,38 @@
 	return 1;
 }
 
-#define CA_VOLUME(xname,chid,reg) \
+#define CA_VOLUME(xname,chid,reg,db) \
 {								\
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
 	.info = snd_ca0106_volume_info,				\
 	.get =          snd_ca0106_volume_get,			\
 	.put =          snd_ca0106_volume_put,			\
-	.private_value = ((chid) << 8) | (reg)			\
+	.private_value = ((chid) << 8) | (reg),			\
+	.db_scale = db						\
 }
 
 
 static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
 	CA_VOLUME("Analog Front Playback Volume",
-		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
-        CA_VOLUME("Analog Rear Playback Volume",
-		  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
+		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2, 1),
+	CA_VOLUME("Analog Rear Playback Volume",
+		  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2, 1),
 	CA_VOLUME("Analog Center/LFE Playback Volume",
-		  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
-        CA_VOLUME("Analog Side Playback Volume",
-		  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
+		  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2, 1),
+	CA_VOLUME("Analog Side Playback Volume",
+		  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2, 1),
 
-        CA_VOLUME("IEC958 Front Playback Volume",
-		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
+	CA_VOLUME("IEC958 Front Playback Volume",
+		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1, 1),
 	CA_VOLUME("IEC958 Rear Playback Volume",
-		  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
+		  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1, 1),
 	CA_VOLUME("IEC958 Center/LFE Playback Volume",
-		  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
+		  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1, 1),
 	CA_VOLUME("IEC958 Unknown Playback Volume",
-		  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
+		  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1, 1),
 
-        CA_VOLUME("CAPTURE feedback Playback Volume",
-		  1, CAPTURE_CONTROL),
+	CA_VOLUME("CAPTURE feedback Playback Volume",
+		  1, CAPTURE_CONTROL, 1),
 
 	{
 		.access =	SNDRV_CTL_ELEM_ACCESS_READ,
Index: alsa-driver/alsa-kernel/pci/emu10k1/emufx.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/emu10k1/emufx.c,v
retrieving revision 1.84
diff -u -r1.84 emufx.c
--- alsa-driver/alsa-kernel/pci/emu10k1/emufx.c	5 Dec 2005 15:12:20 -0000	1.84
+++ alsa-driver/alsa-kernel/pci/emu10k1/emufx.c	22 Dec 2005 22:28:06 -0000
@@ -752,6 +752,7 @@
 		knew.device = gctl->id.device;
 		knew.subdevice = gctl->id.subdevice;
 		knew.info = snd_emu10k1_gpr_ctl_info;
+		knew.db_scale = gctl->db_scale;
 		knew.get = snd_emu10k1_gpr_ctl_get;
 		knew.put = snd_emu10k1_gpr_ctl_put;
 		memset(nctl, 0, sizeof(*nctl));
@@ -1010,6 +1011,7 @@
 	ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
 	ctl->min = 0;
 	ctl->max = 100;
+	ctl->db_scale = 2;
 	ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;	
 }
 
@@ -1024,6 +1026,7 @@
 	ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
 	ctl->min = 0;
 	ctl->max = 100;
+	ctl->db_scale = 2;
 	ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
 }
 
Index: alsa-driver/alsa-kernel/pci/emu10k1/p16v.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/emu10k1/p16v.c,v
retrieving revision 1.16
diff -u -r1.16 p16v.c
--- alsa-driver/alsa-kernel/pci/emu10k1/p16v.c	22 Dec 2005 17:01:20 -0000	1.16
+++ alsa-driver/alsa-kernel/pci/emu10k1/p16v.c	22 Dec 2005 22:28:06 -0000
@@ -785,23 +785,24 @@
         return change;
 }
 
-#define P16V_VOL(xname,xreg,xhl) { \
+#define P16V_VOL(xname,xreg,xhl,scale) { \
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_p16v_volume_info, \
 	.get = snd_p16v_volume_get, \
 	.put = snd_p16v_volume_put, \
-	.private_value = ((xreg) | ((xhl) << 8)) \
+	.private_value = ((xreg) | ((xhl) << 8)), \
+	.db_scale = scale \
 }
 
 static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
-	P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
-	P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
-	P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
-	P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0),
-	P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0),
-	P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1),
-	P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1),
-	P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0),
+	P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0, 1),
+	P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1, 1),
+	P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1, 1),
+	P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0, 1),
+	P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0, 1),
+	P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1, 1),
+	P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1, 1),
+	P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0, 1),
 	{
 		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name =		"HD source Capture",

