Skip to content

Commit

Permalink
[ALSA] Stereo controls for M-Audio Revolution cards
Browse files Browse the repository at this point in the history
This patch adds stereo controls to revo cards by making the ak4xxx
driver mixers configurable from the card driver.

Signed-off-by: Jani Alinikula <janialinikula@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
  • Loading branch information
Jani Alinikula authored and Jaroslav Kysela committed Jun 28, 2006
1 parent be7ee27 commit c83c0c4
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 9 deletions.
2 changes: 2 additions & 0 deletions include/sound/ak4xxx-adda.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ struct snd_akm4xxx {
SND_AK4524, SND_AK4528, SND_AK4529,
SND_AK4355, SND_AK4358, SND_AK4381
} type;
unsigned int *num_stereo; /* array of combined counts for the mixer */
char **channel_names; /* array of mixer channel names */
struct snd_ak4xxx_ops ops;
};

Expand Down
89 changes: 83 additions & 6 deletions sound/i2c/other/ak4xxx-adda.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,64 @@ static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
return change;
}

static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
unsigned int mask = AK_GET_MASK(kcontrol->private_value);

uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask;
return 0;
}

static int snd_akm4xxx_stereo_volume_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);
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);

ucontrol->value.integer.value[0] = invert ? mask - val : val;

val = snd_akm4xxx_get(ak, chip, addr+1);
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 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;
change0 = snd_akm4xxx_get(ak, chip, addr) != nval;
if (change0)
snd_akm4xxx_write(ak, chip, addr, nval);

nval = ucontrol->value.integer.value[1] % (mask+1);
if (invert)
nval = mask - nval;
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)
{
Expand Down Expand Up @@ -377,20 +435,35 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
unsigned int idx, num_emphs;
struct snd_kcontrol *ctl;
int err;
int mixer_ch = 0;
int num_stereo;

ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
if (! ctl)
return -ENOMEM;

for (idx = 0; idx < ak->num_dacs; ++idx) {
for (idx = 0; idx < ak->num_dacs; ) {
memset(ctl, 0, sizeof(*ctl));
strcpy(ctl->id.name, "DAC Volume");
ctl->id.index = idx + ak->idx_offset * 2;
if (ak->channel_names == NULL) {
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];
ctl->id.index = 0; //mixer_ch + ak->idx_offset * 2;
}
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;
}
switch (ak->type) {
case SND_AK4524:
ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
Expand Down Expand Up @@ -419,9 +492,13 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
err = -EINVAL;
goto __error;
}

ctl->private_data = ak;
if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
goto __error;

idx += num_stereo;
mixer_ch++;
}
for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) {
memset(ctl, 0, sizeof(*ctl));
Expand Down
23 changes: 20 additions & 3 deletions sound/pci/ice1712/revo.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,25 @@ static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
* 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 struct snd_akm4xxx akm_revo_front __devinitdata = {
.type = SND_AK4381,
.num_dacs = 2,
.ops = {
.set_rate_val = revo_set_rate_val
}
},
.num_stereo = revo71_num_stereo_front,
.channel_names = revo71_channel_names_front
};

static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
Expand All @@ -113,7 +126,9 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = {
.num_dacs = 6,
.ops = {
.set_rate_val = revo_set_rate_val
}
},
.num_stereo = revo71_num_stereo_surround,
.channel_names = revo71_channel_names_surround
};

static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
Expand All @@ -133,7 +148,9 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = {
.num_dacs = 6,
.ops = {
.set_rate_val = revo_set_rate_val
}
},
.num_stereo = revo51_num_stereo,
.channel_names = revo51_channel_names
};

static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
Expand Down

0 comments on commit c83c0c4

Please sign in to comment.