diff options
Diffstat (limited to 'sound/pci/bt87x.c')
-rw-r--r-- | sound/pci/bt87x.c | 217 |
1 files changed, 130 insertions, 87 deletions
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 131952f55857..91f9e6a112ff 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -147,15 +147,56 @@ MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards"); | |||
147 | /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ | 147 | /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ |
148 | #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) | 148 | #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) |
149 | 149 | ||
150 | /* Cards with configuration information */ | ||
151 | enum snd_bt87x_boardid { | ||
152 | SND_BT87X_BOARD_UNKNOWN, | ||
153 | SND_BT87X_BOARD_GENERIC, /* both an & dig interfaces, 32kHz */ | ||
154 | SND_BT87X_BOARD_ANALOG, /* board with no external A/D */ | ||
155 | SND_BT87X_BOARD_OSPREY2x0, | ||
156 | SND_BT87X_BOARD_OSPREY440, | ||
157 | SND_BT87X_BOARD_AVPHONE98, | ||
158 | }; | ||
159 | |||
160 | /* Card configuration */ | ||
161 | struct snd_bt87x_board { | ||
162 | int dig_rate; /* Digital input sampling rate */ | ||
163 | u32 digital_fmt; /* Register settings for digital input */ | ||
164 | unsigned no_analog:1; /* No analog input */ | ||
165 | unsigned no_digital:1; /* No digital input */ | ||
166 | }; | ||
167 | |||
168 | static const __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = { | ||
169 | [SND_BT87X_BOARD_UNKNOWN] = { | ||
170 | .dig_rate = 32000, /* just a guess */ | ||
171 | }, | ||
172 | [SND_BT87X_BOARD_GENERIC] = { | ||
173 | .dig_rate = 32000, | ||
174 | }, | ||
175 | [SND_BT87X_BOARD_ANALOG] = { | ||
176 | .no_digital = 1, | ||
177 | }, | ||
178 | [SND_BT87X_BOARD_OSPREY2x0] = { | ||
179 | .dig_rate = 44100, | ||
180 | .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), | ||
181 | }, | ||
182 | [SND_BT87X_BOARD_OSPREY440] = { | ||
183 | .dig_rate = 32000, | ||
184 | .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), | ||
185 | .no_analog = 1, | ||
186 | }, | ||
187 | [SND_BT87X_BOARD_AVPHONE98] = { | ||
188 | .dig_rate = 48000, | ||
189 | }, | ||
190 | }; | ||
191 | |||
150 | struct snd_bt87x { | 192 | struct snd_bt87x { |
151 | struct snd_card *card; | 193 | struct snd_card *card; |
152 | struct pci_dev *pci; | 194 | struct pci_dev *pci; |
195 | struct snd_bt87x_board board; | ||
153 | 196 | ||
154 | void __iomem *mmio; | 197 | void __iomem *mmio; |
155 | int irq; | 198 | int irq; |
156 | 199 | ||
157 | int dig_rate; | ||
158 | |||
159 | spinlock_t reg_lock; | 200 | spinlock_t reg_lock; |
160 | unsigned long opened; | 201 | unsigned long opened; |
161 | struct snd_pcm_substream *substream; | 202 | struct snd_pcm_substream *substream; |
@@ -340,30 +381,11 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = { | |||
340 | 381 | ||
341 | static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) | 382 | static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) |
342 | { | 383 | { |
343 | static struct { | 384 | chip->reg_control |= CTL_DA_IOM_DA | CTL_A_PWRDN; |
344 | int rate; | ||
345 | unsigned int bit; | ||
346 | } ratebits[] = { | ||
347 | {8000, SNDRV_PCM_RATE_8000}, | ||
348 | {11025, SNDRV_PCM_RATE_11025}, | ||
349 | {16000, SNDRV_PCM_RATE_16000}, | ||
350 | {22050, SNDRV_PCM_RATE_22050}, | ||
351 | {32000, SNDRV_PCM_RATE_32000}, | ||
352 | {44100, SNDRV_PCM_RATE_44100}, | ||
353 | {48000, SNDRV_PCM_RATE_48000} | ||
354 | }; | ||
355 | int i; | ||
356 | |||
357 | chip->reg_control |= CTL_DA_IOM_DA; | ||
358 | runtime->hw = snd_bt87x_digital_hw; | 385 | runtime->hw = snd_bt87x_digital_hw; |
359 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | 386 | runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate); |
360 | for (i = 0; i < ARRAY_SIZE(ratebits); ++i) | 387 | runtime->hw.rate_min = chip->board.dig_rate; |
361 | if (chip->dig_rate == ratebits[i].rate) { | 388 | runtime->hw.rate_max = chip->board.dig_rate; |
362 | runtime->hw.rates = ratebits[i].bit; | ||
363 | break; | ||
364 | } | ||
365 | runtime->hw.rate_min = chip->dig_rate; | ||
366 | runtime->hw.rate_max = chip->dig_rate; | ||
367 | return 0; | 389 | return 0; |
368 | } | 390 | } |
369 | 391 | ||
@@ -380,7 +402,7 @@ static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtim | |||
380 | .rats = &analog_clock | 402 | .rats = &analog_clock |
381 | }; | 403 | }; |
382 | 404 | ||
383 | chip->reg_control &= ~CTL_DA_IOM_DA; | 405 | chip->reg_control &= ~(CTL_DA_IOM_DA | CTL_A_PWRDN); |
384 | runtime->hw = snd_bt87x_analog_hw; | 406 | runtime->hw = snd_bt87x_analog_hw; |
385 | return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 407 | return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
386 | &constraint_rates); | 408 | &constraint_rates); |
@@ -419,6 +441,11 @@ static int snd_bt87x_close(struct snd_pcm_substream *substream) | |||
419 | { | 441 | { |
420 | struct snd_bt87x *chip = snd_pcm_substream_chip(substream); | 442 | struct snd_bt87x *chip = snd_pcm_substream_chip(substream); |
421 | 443 | ||
444 | spin_lock_irq(&chip->reg_lock); | ||
445 | chip->reg_control |= CTL_A_PWRDN; | ||
446 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); | ||
447 | spin_unlock_irq(&chip->reg_lock); | ||
448 | |||
422 | chip->substream = NULL; | 449 | chip->substream = NULL; |
423 | clear_bit(0, &chip->opened); | 450 | clear_bit(0, &chip->opened); |
424 | smp_mb__after_clear_bit(); | 451 | smp_mb__after_clear_bit(); |
@@ -569,15 +596,7 @@ static struct snd_kcontrol_new snd_bt87x_capture_volume = { | |||
569 | .put = snd_bt87x_capture_volume_put, | 596 | .put = snd_bt87x_capture_volume_put, |
570 | }; | 597 | }; |
571 | 598 | ||
572 | static int snd_bt87x_capture_boost_info(struct snd_kcontrol *kcontrol, | 599 | #define snd_bt87x_capture_boost_info snd_ctl_boolean_mono_info |
573 | struct snd_ctl_elem_info *info) | ||
574 | { | ||
575 | info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
576 | info->count = 1; | ||
577 | info->value.integer.min = 0; | ||
578 | info->value.integer.max = 1; | ||
579 | return 0; | ||
580 | } | ||
581 | 600 | ||
582 | static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol, | 601 | static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol, |
583 | struct snd_ctl_elem_value *value) | 602 | struct snd_ctl_elem_value *value) |
@@ -736,61 +755,69 @@ static int __devinit snd_bt87x_create(struct snd_card *card, | |||
736 | chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), | 755 | chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), |
737 | pci_resource_len(pci, 0)); | 756 | pci_resource_len(pci, 0)); |
738 | if (!chip->mmio) { | 757 | if (!chip->mmio) { |
739 | snd_bt87x_free(chip); | ||
740 | snd_printk(KERN_ERR "cannot remap io memory\n"); | 758 | snd_printk(KERN_ERR "cannot remap io memory\n"); |
741 | return -ENOMEM; | 759 | err = -ENOMEM; |
760 | goto fail; | ||
742 | } | 761 | } |
743 | 762 | ||
744 | chip->reg_control = CTL_DA_ES2 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); | 763 | chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 | |
764 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); | ||
745 | chip->interrupt_mask = MY_INTERRUPTS; | 765 | chip->interrupt_mask = MY_INTERRUPTS; |
746 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); | 766 | snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); |
747 | snd_bt87x_writel(chip, REG_INT_MASK, 0); | 767 | snd_bt87x_writel(chip, REG_INT_MASK, 0); |
748 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); | 768 | snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); |
749 | 769 | ||
750 | if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, | 770 | err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, |
751 | "Bt87x audio", chip)) { | 771 | "Bt87x audio", chip); |
752 | snd_bt87x_free(chip); | 772 | if (err < 0) { |
753 | snd_printk(KERN_ERR "cannot grab irq\n"); | 773 | snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); |
754 | return -EBUSY; | 774 | goto fail; |
755 | } | 775 | } |
756 | chip->irq = pci->irq; | 776 | chip->irq = pci->irq; |
757 | pci_set_master(pci); | 777 | pci_set_master(pci); |
758 | synchronize_irq(chip->irq); | 778 | synchronize_irq(chip->irq); |
759 | 779 | ||
760 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | 780 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); |
761 | if (err < 0) { | 781 | if (err < 0) |
762 | snd_bt87x_free(chip); | 782 | goto fail; |
763 | return err; | 783 | |
764 | } | ||
765 | snd_card_set_dev(card, &pci->dev); | 784 | snd_card_set_dev(card, &pci->dev); |
766 | *rchip = chip; | 785 | *rchip = chip; |
767 | return 0; | 786 | return 0; |
787 | |||
788 | fail: | ||
789 | snd_bt87x_free(chip); | ||
790 | return err; | ||
768 | } | 791 | } |
769 | 792 | ||
770 | #define BT_DEVICE(chip, subvend, subdev, rate) \ | 793 | #define BT_DEVICE(chip, subvend, subdev, id) \ |
771 | { .vendor = PCI_VENDOR_ID_BROOKTREE, \ | 794 | { .vendor = PCI_VENDOR_ID_BROOKTREE, \ |
772 | .device = chip, \ | 795 | .device = chip, \ |
773 | .subvendor = subvend, .subdevice = subdev, \ | 796 | .subvendor = subvend, .subdevice = subdev, \ |
774 | .driver_data = rate } | 797 | .driver_data = SND_BT87X_BOARD_ ## id } |
798 | /* driver_data is the card id for that device */ | ||
775 | 799 | ||
776 | /* driver_data is the default digital_rate value for that device */ | ||
777 | static struct pci_device_id snd_bt87x_ids[] = { | 800 | static struct pci_device_id snd_bt87x_ids[] = { |
778 | /* Hauppauge WinTV series */ | 801 | /* Hauppauge WinTV series */ |
779 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000), | 802 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, GENERIC), |
780 | /* Hauppauge WinTV series */ | 803 | /* Hauppauge WinTV series */ |
781 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), | 804 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, GENERIC), |
782 | /* Viewcast Osprey 200 */ | 805 | /* Viewcast Osprey 200 */ |
783 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), | 806 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, OSPREY2x0), |
784 | /* Viewcast Osprey 440 (rate is configurable via gpio) */ | 807 | /* Viewcast Osprey 440 (rate is configurable via gpio) */ |
785 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, 32000), | 808 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, OSPREY440), |
786 | /* ATI TV-Wonder */ | 809 | /* ATI TV-Wonder */ |
787 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000), | 810 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, GENERIC), |
788 | /* Leadtek Winfast tv 2000xp delux */ | 811 | /* Leadtek Winfast tv 2000xp delux */ |
789 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), | 812 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, GENERIC), |
790 | /* Voodoo TV 200 */ | 813 | /* Voodoo TV 200 */ |
791 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000), | 814 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, GENERIC), |
792 | /* AVerMedia Studio No. 103, 203, ...? */ | 815 | /* AVerMedia Studio No. 103, 203, ...? */ |
793 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), | 816 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, AVPHONE98), |
817 | /* Prolink PixelView PV-M4900 */ | ||
818 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1554, 0x4011, GENERIC), | ||
819 | /* Pinnacle Studio PCTV rave */ | ||
820 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0xbd11, 0x1200, GENERIC), | ||
794 | { } | 821 | { } |
795 | }; | 822 | }; |
796 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); | 823 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); |
@@ -815,7 +842,7 @@ static struct { | |||
815 | 842 | ||
816 | static struct pci_driver driver; | 843 | static struct pci_driver driver; |
817 | 844 | ||
818 | /* return the rate of the card, or a negative value if it's blacklisted */ | 845 | /* return the id of the card, or a negative value if it's blacklisted */ |
819 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | 846 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) |
820 | { | 847 | { |
821 | int i; | 848 | int i; |
@@ -833,12 +860,12 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | |||
833 | return -EBUSY; | 860 | return -EBUSY; |
834 | } | 861 | } |
835 | 862 | ||
836 | snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x, using default rate 32000\n", | 863 | snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x\n", |
837 | pci->device, pci->subsystem_vendor, pci->subsystem_device); | 864 | pci->device, pci->subsystem_vendor, pci->subsystem_device); |
838 | snd_printk(KERN_DEBUG "please mail id, board name, and, " | 865 | snd_printk(KERN_DEBUG "please mail id, board name, and, " |
839 | "if it works, the correct digital_rate option to " | 866 | "if it works, the correct digital_rate option to " |
840 | "<alsa-devel@alsa-project.org>\n"); | 867 | "<alsa-devel@alsa-project.org>\n"); |
841 | return 32000; /* default rate */ | 868 | return SND_BT87X_BOARD_UNKNOWN; |
842 | } | 869 | } |
843 | 870 | ||
844 | static int __devinit snd_bt87x_probe(struct pci_dev *pci, | 871 | static int __devinit snd_bt87x_probe(struct pci_dev *pci, |
@@ -847,12 +874,16 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, | |||
847 | static int dev; | 874 | static int dev; |
848 | struct snd_card *card; | 875 | struct snd_card *card; |
849 | struct snd_bt87x *chip; | 876 | struct snd_bt87x *chip; |
850 | int err, rate; | 877 | int err; |
878 | enum snd_bt87x_boardid boardid; | ||
851 | 879 | ||
852 | rate = pci_id->driver_data; | 880 | if (!pci_id->driver_data) { |
853 | if (! rate) | 881 | err = snd_bt87x_detect_card(pci); |
854 | if ((rate = snd_bt87x_detect_card(pci)) <= 0) | 882 | if (err < 0) |
855 | return -ENODEV; | 883 | return -ENODEV; |
884 | boardid = err; | ||
885 | } else | ||
886 | boardid = pci_id->driver_data; | ||
856 | 887 | ||
857 | if (dev >= SNDRV_CARDS) | 888 | if (dev >= SNDRV_CARDS) |
858 | return -ENODEV; | 889 | return -ENODEV; |
@@ -869,27 +900,39 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, | |||
869 | if (err < 0) | 900 | if (err < 0) |
870 | goto _error; | 901 | goto _error; |
871 | 902 | ||
872 | if (digital_rate[dev] > 0) | 903 | memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board)); |
873 | chip->dig_rate = digital_rate[dev]; | ||
874 | else | ||
875 | chip->dig_rate = rate; | ||
876 | 904 | ||
877 | err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); | 905 | if (!chip->board.no_digital) { |
878 | if (err < 0) | 906 | if (digital_rate[dev] > 0) |
879 | goto _error; | 907 | chip->board.dig_rate = digital_rate[dev]; |
880 | err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); | ||
881 | if (err < 0) | ||
882 | goto _error; | ||
883 | 908 | ||
884 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_volume, chip)); | 909 | chip->reg_control |= chip->board.digital_fmt; |
885 | if (err < 0) | 910 | |
886 | goto _error; | 911 | err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); |
887 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_boost, chip)); | 912 | if (err < 0) |
888 | if (err < 0) | 913 | goto _error; |
889 | goto _error; | 914 | } |
890 | err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_source, chip)); | 915 | if (!chip->board.no_analog) { |
891 | if (err < 0) | 916 | err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); |
892 | goto _error; | 917 | if (err < 0) |
918 | goto _error; | ||
919 | err = snd_ctl_add(card, snd_ctl_new1( | ||
920 | &snd_bt87x_capture_volume, chip)); | ||
921 | if (err < 0) | ||
922 | goto _error; | ||
923 | err = snd_ctl_add(card, snd_ctl_new1( | ||
924 | &snd_bt87x_capture_boost, chip)); | ||
925 | if (err < 0) | ||
926 | goto _error; | ||
927 | err = snd_ctl_add(card, snd_ctl_new1( | ||
928 | &snd_bt87x_capture_source, chip)); | ||
929 | if (err < 0) | ||
930 | goto _error; | ||
931 | } | ||
932 | snd_printk(KERN_INFO "bt87x%d: Using board %d, %sanalog, %sdigital " | ||
933 | "(rate %d Hz)\n", dev, boardid, | ||
934 | chip->board.no_analog ? "no " : "", | ||
935 | chip->board.no_digital ? "no " : "", chip->board.dig_rate); | ||
893 | 936 | ||
894 | strcpy(card->driver, "Bt87x"); | 937 | strcpy(card->driver, "Bt87x"); |
895 | sprintf(card->shortname, "Brooktree Bt%x", pci->device); | 938 | sprintf(card->shortname, "Brooktree Bt%x", pci->device); |
@@ -920,8 +963,8 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) | |||
920 | /* default entries for all Bt87x cards - it's not exported */ | 963 | /* default entries for all Bt87x cards - it's not exported */ |
921 | /* driver_data is set to 0 to call detection */ | 964 | /* driver_data is set to 0 to call detection */ |
922 | static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { | 965 | static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { |
923 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0), | 966 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), |
924 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0), | 967 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, UNKNOWN), |
925 | { } | 968 | { } |
926 | }; | 969 | }; |
927 | 970 | ||