[alsa-devel] CMI8788/AV200/Oxygen Volume Controls in alsamixer (oxygen_mixer.c:dac_volume_get())

John L. Utz III jutz at dmx.com
Fri Jan 23 00:36:52 CET 2009


Hi Clemens and all;

( To those following along at home, kindly open
alsa-driver-1.0.18a/alsa-kernel/pci/oxygen/oxygen_mixer.c and look at 
dac_volume_get() and dac_volume_put() )


It appears to me that these functions are attempting to work on all of 
the channels at once instead of just choosing Master, Front, Rear, 
Surround, or what have you:

static int dac_volume_get(struct snd_kcontrol *ctl,
			  struct snd_ctl_elem_value *value)
{
	struct oxygen *chip = ctl->private_data;
	unsigned int i;

	mutex_lock(&chip->mutex);
	for (i = 0; i < chip->model.dac_channels; ++i)
		value->value.integer.value[i] = chip->dac_volume[i];
	mutex_unlock(&chip->mutex);
	return 0;
}


This is then surfaced to userland thusly in the controls array:

static const struct snd_kcontrol_new controls[] = {
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Master Playback Volume",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = dac_volume_info,
		.get = dac_volume_get,
		.put = dac_volume_put,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Master Playback Switch",
		.info = snd_ctl_boolean_mono_info,
		.get = dac_mute_get,
		.put = dac_mute_put,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Stereo Upmixing",
		.info = upmix_info,
		.get = upmix_get,
		.put = upmix_put,
	},
         { blah },
	{ blah },
         { blah }
};


this leads to a rather awkward result in alsamixer where there are 5 
volume controls called "Master":


< Master >  Master    Master    Master    Master


IMHO, it would be more desirable for them to say:


< Master >  Front     C/LFE     Surround  Rear Surr


Our app would certainly be much happier :-)

So, i *think* that i can fix this thusly:

static const struct snd_kcontrol_new controls[] = {
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Master Playback Volume",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = dac_volume_info,
		.get = dac_volume_get,
		.put = dac_volume_put,
		.private_value = 0
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Master Playback Switch",
		.info = snd_ctl_boolean_mono_info,
		.get = dac_mute_get,
		.put = dac_mute_put,
		.private_value = 0
	},
         {
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Front Playback Volume",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = dac_volume_info,
		.get = dac_volume_get,
		.put = dac_volume_put,
		.private_value = 1
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Front Playback Switch",
		.info = snd_ctl_boolean_mono_info,
		.get = dac_mute_get,
		.put = dac_mute_put,
		.private_value = 1
	},


and alter dac_volume_*() to not use a for() loop and just work off the 
private_value.

anybody have any opinions?

i'll probably have tried this already before anybody responds but it 
seemed reasonable to surface the idea.

tnx!

johnu














More information about the Alsa-devel mailing list