提交 82896f29 编写于 作者: T Trent Piepho 提交者: Mauro Carvalho Chehab

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: NTrent Piepho <xyzzy@speakeasy.org>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 6fcecce7
...@@ -552,7 +552,7 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册