aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2007-09-06 22:02:23 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-10-09 21:08:31 -0400
commit82896f29d47d945e331873c7295da9e3a47d709d (patch)
tree7c237b70408049f5cf8ae0073ce1a33a5adb1e7f /drivers
parent6fcecce7e1a5223be450031fa446323b08d1ec41 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c61
1 files changed, 37 insertions, 24 deletions
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 85d632224f3a..25de25fb8052 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -552,7 +552,7 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol,
552 struct snd_ctl_elem_info *info) 552 struct snd_ctl_elem_info *info)
553{ 553{
554 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 554 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
555 info->count = 1; 555 info->count = 2;
556 info->value.integer.min = 0; 556 info->value.integer.min = 0;
557 info->value.integer.max = 0x3f; 557 info->value.integer.max = 0x3f;
558 558
@@ -565,8 +565,12 @@ static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol,
565{ 565{
566 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 566 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
567 struct cx88_core *core=chip->core; 567 struct cx88_core *core=chip->core;
568 int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f),
569 bal = cx_read(AUD_BAL_CTL);
568 570
569 value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); 571 value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol;
572 vol -= (bal & 0x3f);
573 value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol;
570 574
571 return 0; 575 return 0;
572} 576}
@@ -577,19 +581,31 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol,
577{ 581{
578 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 582 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
579 struct cx88_core *core=chip->core; 583 struct cx88_core *core=chip->core;
580 int v; 584 int v, b;
581 u32 old_control; 585 int changed = 0;
582 586 u32 old;
587
588 b = value->value.integer.value[1] - value->value.integer.value[0];
589 if (b < 0) {
590 v = 0x3f - value->value.integer.value[0];
591 b = (-b) | 0x40;
592 } else {
593 v = 0x3f - value->value.integer.value[1];
594 }
583 /* Do we really know this will always be called with IRQs on? */ 595 /* Do we really know this will always be called with IRQs on? */
584 spin_lock_irq(&chip->reg_lock); 596 spin_lock_irq(&chip->reg_lock);
585 597 old = cx_read(AUD_VOL_CTL);
586 old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); 598 if (v != (old & 0x3f)) {
587 v = 0x3f - (value->value.integer.value[0] & 0x3f); 599 cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
588 cx_andor(AUD_VOL_CTL, 0x3f, v); 600 changed = 1;
589 601 }
602 if (cx_read(AUD_BAL_CTL) != b) {
603 cx_write(AUD_BAL_CTL, b);
604 changed = 1;
605 }
590 spin_unlock_irq(&chip->reg_lock); 606 spin_unlock_irq(&chip->reg_lock);
591 607
592 return v != old_control; 608 return changed;
593} 609}
594 610
595static struct snd_kcontrol_new snd_cx88_capture_volume = { 611static struct snd_kcontrol_new snd_cx88_capture_volume = {
@@ -746,17 +762,12 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
746 return (err); 762 return (err);
747 763
748 err = snd_cx88_pcm(chip, 0, "CX88 Digital"); 764 err = snd_cx88_pcm(chip, 0, "CX88 Digital");
749 765 if (err < 0)
750 if (err < 0) { 766 goto error;
751 snd_card_free(card);
752 return (err);
753 }
754 767
755 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip)); 768 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
756 if (err < 0) { 769 if (err < 0)
757 snd_card_free(card); 770 goto error;
758 return (err);
759 }
760 771
761 strcpy (card->driver, "CX88x"); 772 strcpy (card->driver, "CX88x");
762 sprintf(card->shortname, "Conexant CX%x", pci->device); 773 sprintf(card->shortname, "Conexant CX%x", pci->device);
@@ -768,14 +779,16 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
768 card->driver,devno); 779 card->driver,devno);
769 780
770 err = snd_card_register(card); 781 err = snd_card_register(card);
771 if (err < 0) { 782 if (err < 0)
772 snd_card_free(card); 783 goto error;
773 return (err);
774 }
775 pci_set_drvdata(pci,card); 784 pci_set_drvdata(pci,card);
776 785
777 devno++; 786 devno++;
778 return 0; 787 return 0;
788
789error:
790 snd_card_free(card);
791 return err;
779} 792}
780/* 793/*
781 * ALSA destructor 794 * ALSA destructor