V4L/DVB (6184): cx88-alsa: Make volume control stereo
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>
This commit is contained in:
parent
6fcecce7e1
commit
82896f29d4
|
@ -552,7 +552,7 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *info)
|
struct snd_ctl_elem_info *info)
|
||||||
{
|
{
|
||||||
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||||
info->count = 1;
|
info->count = 2;
|
||||||
info->value.integer.min = 0;
|
info->value.integer.min = 0;
|
||||||
info->value.integer.max = 0x3f;
|
info->value.integer.max = 0x3f;
|
||||||
|
|
||||||
|
@ -565,8 +565,12 @@ static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct cx88_core *core=chip->core;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -577,19 +581,31 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct cx88_core *core=chip->core;
|
struct cx88_core *core=chip->core;
|
||||||
int v;
|
int v, b;
|
||||||
u32 old_control;
|
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? */
|
/* Do we really know this will always be called with IRQs on? */
|
||||||
spin_lock_irq(&chip->reg_lock);
|
spin_lock_irq(&chip->reg_lock);
|
||||||
|
old = cx_read(AUD_VOL_CTL);
|
||||||
old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
|
if (v != (old & 0x3f)) {
|
||||||
v = 0x3f - (value->value.integer.value[0] & 0x3f);
|
cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
|
||||||
cx_andor(AUD_VOL_CTL, 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);
|
spin_unlock_irq(&chip->reg_lock);
|
||||||
|
|
||||||
return v != old_control;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_kcontrol_new snd_cx88_capture_volume = {
|
static struct snd_kcontrol_new snd_cx88_capture_volume = {
|
||||||
|
@ -746,17 +762,12 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
|
||||||
return (err);
|
return (err);
|
||||||
|
|
||||||
err = snd_cx88_pcm(chip, 0, "CX88 Digital");
|
err = snd_cx88_pcm(chip, 0, "CX88 Digital");
|
||||||
|
if (err < 0)
|
||||||
if (err < 0) {
|
goto error;
|
||||||
snd_card_free(card);
|
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
|
err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
snd_card_free(card);
|
goto error;
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy (card->driver, "CX88x");
|
strcpy (card->driver, "CX88x");
|
||||||
sprintf(card->shortname, "Conexant CX%x", pci->device);
|
sprintf(card->shortname, "Conexant CX%x", pci->device);
|
||||||
|
@ -768,14 +779,16 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
|
||||||
card->driver,devno);
|
card->driver,devno);
|
||||||
|
|
||||||
err = snd_card_register(card);
|
err = snd_card_register(card);
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
snd_card_free(card);
|
goto error;
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
pci_set_drvdata(pci,card);
|
pci_set_drvdata(pci,card);
|
||||||
|
|
||||||
devno++;
|
devno++;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
snd_card_free(card);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* ALSA destructor
|
* ALSA destructor
|
||||||
|
|
Loading…
Reference in New Issue