diff options
Diffstat (limited to 'sound/pci/bt87x.c')
-rw-r--r-- | sound/pci/bt87x.c | 172 |
1 files changed, 114 insertions, 58 deletions
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index d87d6a3..10c8af1 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -147,15 +147,52 @@ MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards"); /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */ #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8) +/* Cards with configuration information */ +enum snd_bt87x_boardid { + SND_BT87X_BOARD_GENERIC, /* both an & dig interfaces, 32kHz */ + SND_BT87X_BOARD_ANALOG, /* board with no external A/D */ + SND_BT87X_BOARD_OSPREY2x0, + SND_BT87X_BOARD_OSPREY440, + SND_BT87X_BOARD_AVPHONE98, +}; + +/* Card configuration */ +struct snd_bt87x_board { + int dig_rate; /* Digital input sampling rate */ + u32 digital_fmt; /* Register settings for digital input */ + unsigned no_analog:1; /* No analog input */ + unsigned no_digital:1; /* No digital input */ +}; + +static const __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = { + [SND_BT87X_BOARD_GENERIC] = { + .dig_rate = 32000, + }, + [SND_BT87X_BOARD_ANALOG] = { + .no_digital = 1, + }, + [SND_BT87X_BOARD_OSPREY2x0] = { + .dig_rate = 44100, + .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), + }, + [SND_BT87X_BOARD_OSPREY440] = { + .dig_rate = 32000, + .digital_fmt = CTL_DA_LRI | (1 << CTL_DA_LRD_SHIFT), + .no_analog = 1, + }, + [SND_BT87X_BOARD_AVPHONE98] = { + .dig_rate = 48000, + }, +}; + struct snd_bt87x { struct snd_card *card; struct pci_dev *pci; + struct snd_bt87x_board board; void __iomem *mmio; int irq; - int dig_rate; - spinlock_t reg_lock; unsigned long opened; struct snd_pcm_substream *substream; @@ -342,9 +379,9 @@ static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runti { chip->reg_control |= CTL_DA_IOM_DA; runtime->hw = snd_bt87x_digital_hw; - runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->dig_rate); - runtime->hw.rate_min = chip->dig_rate; - runtime->hw.rate_max = chip->dig_rate; + runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate); + runtime->hw.rate_min = chip->board.dig_rate; + runtime->hw.rate_max = chip->board.dig_rate; return 0; } @@ -709,9 +746,9 @@ static int __devinit snd_bt87x_create(struct snd_card *card, chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), pci_resource_len(pci, 0)); if (!chip->mmio) { - snd_bt87x_free(chip); snd_printk(KERN_ERR "cannot remap io memory\n"); - return -ENOMEM; + err = -ENOMEM; + goto fail; } chip->reg_control = CTL_DA_ES2 | CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT); @@ -720,54 +757,57 @@ static int __devinit snd_bt87x_create(struct snd_card *card, snd_bt87x_writel(chip, REG_INT_MASK, 0); snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); - if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, - "Bt87x audio", chip)) { - snd_bt87x_free(chip); - snd_printk(KERN_ERR "cannot grab irq\n"); - return -EBUSY; + err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, + "Bt87x audio", chip); + if (err < 0) { + snd_printk(KERN_ERR "cannot grab irq %d\n", pci->irq); + goto fail; } chip->irq = pci->irq; pci_set_master(pci); synchronize_irq(chip->irq); err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_bt87x_free(chip); - return err; - } + if (err < 0) + goto fail; + snd_card_set_dev(card, &pci->dev); *rchip = chip; return 0; + +fail: + snd_bt87x_free(chip); + return err; } -#define BT_DEVICE(chip, subvend, subdev, rate) \ +#define BT_DEVICE(chip, subvend, subdev, id) \ { .vendor = PCI_VENDOR_ID_BROOKTREE, \ .device = chip, \ .subvendor = subvend, .subdevice = subdev, \ - .driver_data = rate } + .driver_data = SND_BT87X_BOARD_ ## id } +/* driver_data is the card id for that device */ -/* driver_data is the default digital_rate value for that device */ static struct pci_device_id snd_bt87x_ids[] = { /* Hauppauge WinTV series */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, GENERIC), /* Hauppauge WinTV series */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, GENERIC), /* Viewcast Osprey 200 */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, OSPREY2x0), /* Viewcast Osprey 440 (rate is configurable via gpio) */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, OSPREY440), /* ATI TV-Wonder */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, GENERIC), /* Leadtek Winfast tv 2000xp delux */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, GENERIC), /* Voodoo TV 200 */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, GENERIC), /* AVerMedia Studio No. 103, 203, ...? */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, AVPHONE98), /* Prolink PixelView PV-M4900 */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1554, 0x4011, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1554, 0x4011, GENERIC), /* Pinnacle Studio PCTV rave */ - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0xbd11, 0x1200, 32000), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0xbd11, 0x1200, GENERIC), { } }; MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); @@ -792,7 +832,7 @@ static struct { static struct pci_driver driver; -/* return the rate of the card, or a negative value if it's blacklisted */ +/* return the id of the card, or a negative value if it's blacklisted */ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) { int i; @@ -810,12 +850,12 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) return -EBUSY; } - snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x, using default rate 32000\n", - pci->device, pci->subsystem_vendor, pci->subsystem_device); + snd_printk(KERN_INFO "unknown card %#04x-%#04x:%#04x\n", + pci->device, pci->subsystem_vendor, pci->subsystem_device); snd_printk(KERN_DEBUG "please mail id, board name, and, " "if it works, the correct digital_rate option to " "<alsa-devel@alsa-project.org>\n"); - return 32000; /* default rate */ + return SND_BT87X_BOARD_GENERIC; } static int __devinit snd_bt87x_probe(struct pci_dev *pci, @@ -824,12 +864,16 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, static int dev; struct snd_card *card; struct snd_bt87x *chip; - int err, rate; + int err; + enum snd_bt87x_boardid boardid; - rate = pci_id->driver_data; - if (! rate) - if ((rate = snd_bt87x_detect_card(pci)) <= 0) + if (!pci_id->driver_data) { + err = snd_bt87x_detect_card(pci); + if (err < 0) return -ENODEV; + boardid = err; + } else + boardid = pci_id->driver_data; if (dev >= SNDRV_CARDS) return -ENODEV; @@ -846,27 +890,39 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, if (err < 0) goto _error; - if (digital_rate[dev] > 0) - chip->dig_rate = digital_rate[dev]; - else - chip->dig_rate = rate; + memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board)); - err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); - if (err < 0) - goto _error; - err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); - if (err < 0) - goto _error; + if (!chip->board.no_digital) { + if (digital_rate[dev] > 0) + chip->board.dig_rate = digital_rate[dev]; - err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_volume, chip)); - if (err < 0) - goto _error; - err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_boost, chip)); - if (err < 0) - goto _error; - err = snd_ctl_add(card, snd_ctl_new1(&snd_bt87x_capture_source, chip)); - if (err < 0) - goto _error; + chip->reg_control |= chip->board.digital_fmt; + + err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); + if (err < 0) + goto _error; + } + if (!chip->board.no_analog) { + err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); + if (err < 0) + goto _error; + err = snd_ctl_add(card, snd_ctl_new1( + &snd_bt87x_capture_volume, chip)); + if (err < 0) + goto _error; + err = snd_ctl_add(card, snd_ctl_new1( + &snd_bt87x_capture_boost, chip)); + if (err < 0) + goto _error; + err = snd_ctl_add(card, snd_ctl_new1( + &snd_bt87x_capture_source, chip)); + if (err < 0) + goto _error; + } + snd_printk(KERN_INFO "bt87x%d: Using board %d, %sanalog, %sdigital " + "(rate %d Hz)\n", dev, boardid, + chip->board.no_analog ? "no " : "", + chip->board.no_digital ? "no " : "", chip->board.dig_rate); strcpy(card->driver, "Bt87x"); sprintf(card->shortname, "Brooktree Bt%x", pci->device); @@ -897,8 +953,8 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci) /* default entries for all Bt87x cards - it's not exported */ /* driver_data is set to 0 to call detection */ static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = { - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0), - BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, GENERIC), + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, GENERIC), { } }; |