Skip to content

Commit

Permalink
V4L/DVB (6184): cx88-alsa: Make volume control stereo
Browse files Browse the repository at this point in the history
Use the balance control to make the mono volume control stereo.

Note that full range isn't supported.  The balance control attenuates one
channel by 0 to -63 dB, and the volume control provides additional attenuation
to both channels by another 0 to -63 dB.

So the channel with the most attenuation has a range of 0 to -126 dB, while
the other channel only has a range of 0 to -63 dB.  ALSA volume controls don't
appear to support this concept.  I just limited the range to 0 to -63 total.
Once you get to -63 dB, you're already at silence, so additional attenuation
is pretty much pointless anyway.

Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
  • Loading branch information
Trent Piepho authored and Mauro Carvalho Chehab committed Oct 10, 2007
1 parent 6fcecce commit 82896f2
Showing 1 changed file with 37 additions and 24 deletions.
61 changes: 37 additions & 24 deletions drivers/media/video/cx88/cx88-alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *info)
{
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
info->count = 1;
info->count = 2;
info->value.integer.min = 0;
info->value.integer.max = 0x3f;

Expand All @@ -565,8 +565,12 @@ static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol,
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core=chip->core;
int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f),
bal = cx_read(AUD_BAL_CTL);

value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol;
vol -= (bal & 0x3f);
value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol;

return 0;
}
Expand All @@ -577,19 +581,31 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol,
{
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core=chip->core;
int v;
u32 old_control;

int v, b;
int changed = 0;
u32 old;

b = value->value.integer.value[1] - value->value.integer.value[0];
if (b < 0) {
v = 0x3f - value->value.integer.value[0];
b = (-b) | 0x40;
} else {
v = 0x3f - value->value.integer.value[1];
}
/* Do we really know this will always be called with IRQs on? */
spin_lock_irq(&chip->reg_lock);

old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
v = 0x3f - (value->value.integer.value[0] & 0x3f);
cx_andor(AUD_VOL_CTL, 0x3f, v);

old = cx_read(AUD_VOL_CTL);
if (v != (old & 0x3f)) {
cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
changed = 1;
}
if (cx_read(AUD_BAL_CTL) != b) {
cx_write(AUD_BAL_CTL, b);
changed = 1;
}
spin_unlock_irq(&chip->reg_lock);

return v != old_control;
return changed;
}

static struct snd_kcontrol_new snd_cx88_capture_volume = {
Expand Down Expand Up @@ -746,17 +762,12 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
return (err);

err = snd_cx88_pcm(chip, 0, "CX88 Digital");

if (err < 0) {
snd_card_free(card);
return (err);
}
if (err < 0)
goto error;

err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
if (err < 0) {
snd_card_free(card);
return (err);
}
if (err < 0)
goto error;

strcpy (card->driver, "CX88x");
sprintf(card->shortname, "Conexant CX%x", pci->device);
Expand All @@ -768,14 +779,16 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
card->driver,devno);

err = snd_card_register(card);
if (err < 0) {
snd_card_free(card);
return (err);
}
if (err < 0)
goto error;
pci_set_drvdata(pci,card);

devno++;
return 0;

error:
snd_card_free(card);
return err;
}
/*
* ALSA destructor
Expand Down

0 comments on commit 82896f2

Please sign in to comment.