Lines Matching +full:has +full:- +full:chip +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * bt87x.c - Brooktree Bt878/Bt879 driver for ALSA
29 static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
30 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ variable
37 module_param_array(id, charp, NULL, 0444);
38 MODULE_PARM_DESC(id, "ID string for Bt87x soundcard");
72 #define CTL_PKTP_4 (0 << 2) /* packet mode FIFO trigger point - 4 DWORDs */
95 #define CTL_A_PWRDN (1 << 26) /* analog audio power-down */
133 #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8)
203 static inline u32 snd_bt87x_readl(struct snd_bt87x *chip, u32 reg) in snd_bt87x_readl() argument
205 return readl(chip->mmio + reg); in snd_bt87x_readl()
208 static inline void snd_bt87x_writel(struct snd_bt87x *chip, u32 reg, u32 value) in snd_bt87x_writel() argument
210 writel(value, chip->mmio + reg); in snd_bt87x_writel()
213 static int snd_bt87x_create_risc(struct snd_bt87x *chip, struct snd_pcm_substream *substream, in snd_bt87x_create_risc() argument
219 if (chip->dma_risc.area == NULL) { in snd_bt87x_create_risc()
220 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev, in snd_bt87x_create_risc()
221 PAGE_ALIGN(MAX_RISC_SIZE), &chip->dma_risc) < 0) in snd_bt87x_create_risc()
222 return -ENOMEM; in snd_bt87x_create_risc()
224 risc = (__le32 *)chip->dma_risc.area; in snd_bt87x_create_risc()
236 len = PAGE_SIZE - (offset % PAGE_SIZE); in snd_bt87x_create_risc()
252 rest -= len; in snd_bt87x_create_risc()
258 *risc++ = cpu_to_le32(chip->dma_risc.addr); in snd_bt87x_create_risc()
259 chip->line_bytes = period_bytes; in snd_bt87x_create_risc()
260 chip->lines = periods; in snd_bt87x_create_risc()
264 static void snd_bt87x_free_risc(struct snd_bt87x *chip) in snd_bt87x_free_risc() argument
266 if (chip->dma_risc.area) { in snd_bt87x_free_risc()
267 snd_dma_free_pages(&chip->dma_risc); in snd_bt87x_free_risc()
268 chip->dma_risc.area = NULL; in snd_bt87x_free_risc()
272 static void snd_bt87x_pci_error(struct snd_bt87x *chip, unsigned int status) in snd_bt87x_pci_error() argument
274 int pci_status = pci_status_get_and_clear_errors(chip->pci); in snd_bt87x_pci_error()
277 dev_err(chip->card->dev, in snd_bt87x_pci_error()
278 "Aieee - PCI error! status %#08x, PCI status %#04x\n", in snd_bt87x_pci_error()
281 dev_err(chip->card->dev, in snd_bt87x_pci_error()
282 "Aieee - PCI parity error detected!\n"); in snd_bt87x_pci_error()
284 chip->pci_parity_errors++; in snd_bt87x_pci_error()
285 if (chip->pci_parity_errors > 20) { in snd_bt87x_pci_error()
286 dev_err(chip->card->dev, in snd_bt87x_pci_error()
288 dev_err(chip->card->dev, in snd_bt87x_pci_error()
290 dev_err(chip->card->dev, in snd_bt87x_pci_error()
292 dev_err(chip->card->dev, in snd_bt87x_pci_error()
293 "PCI parity error checking has been disabled.\n"); in snd_bt87x_pci_error()
294 chip->interrupt_mask &= ~(INT_PPERR | INT_RIPERR); in snd_bt87x_pci_error()
295 snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); in snd_bt87x_pci_error()
302 struct snd_bt87x *chip = dev_id; in snd_bt87x_interrupt() local
305 status = snd_bt87x_readl(chip, REG_INT_STAT); in snd_bt87x_interrupt()
306 irq_status = status & chip->interrupt_mask; in snd_bt87x_interrupt()
309 snd_bt87x_writel(chip, REG_INT_STAT, irq_status); in snd_bt87x_interrupt()
313 dev_warn(chip->card->dev, in snd_bt87x_interrupt()
316 dev_err(chip->card->dev, in snd_bt87x_interrupt()
319 snd_bt87x_pci_error(chip, irq_status); in snd_bt87x_interrupt()
321 if ((irq_status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) { in snd_bt87x_interrupt()
324 /* assume that exactly one line has been recorded */ in snd_bt87x_interrupt()
325 chip->current_line = (chip->current_line + 1) % chip->lines; in snd_bt87x_interrupt()
327 current_block = chip->current_line * 16 / chip->lines; in snd_bt87x_interrupt()
330 chip->current_line = (irq_block * chip->lines + 15) / 16; in snd_bt87x_interrupt()
332 snd_pcm_period_elapsed(chip->substream); in snd_bt87x_interrupt()
373 static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) in snd_bt87x_set_digital_hw() argument
375 chip->reg_control |= CTL_DA_IOM_DA | CTL_A_PWRDN; in snd_bt87x_set_digital_hw()
376 runtime->hw = snd_bt87x_digital_hw; in snd_bt87x_set_digital_hw()
377 runtime->hw.rates = snd_pcm_rate_to_rate_bit(chip->board.dig_rate); in snd_bt87x_set_digital_hw()
378 runtime->hw.rate_min = chip->board.dig_rate; in snd_bt87x_set_digital_hw()
379 runtime->hw.rate_max = chip->board.dig_rate; in snd_bt87x_set_digital_hw()
383 static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) in snd_bt87x_set_analog_hw() argument
396 chip->reg_control &= ~(CTL_DA_IOM_DA | CTL_A_PWRDN); in snd_bt87x_set_analog_hw()
397 runtime->hw = snd_bt87x_analog_hw; in snd_bt87x_set_analog_hw()
404 struct snd_bt87x *chip = snd_pcm_substream_chip(substream); in snd_bt87x_pcm_open() local
405 struct snd_pcm_runtime *runtime = substream->runtime; in snd_bt87x_pcm_open()
408 if (test_and_set_bit(0, &chip->opened)) in snd_bt87x_pcm_open()
409 return -EBUSY; in snd_bt87x_pcm_open()
411 if (substream->pcm->device == DEVICE_DIGITAL) in snd_bt87x_pcm_open()
412 err = snd_bt87x_set_digital_hw(chip, runtime); in snd_bt87x_pcm_open()
414 err = snd_bt87x_set_analog_hw(chip, runtime); in snd_bt87x_pcm_open()
422 chip->substream = substream; in snd_bt87x_pcm_open()
426 clear_bit(0, &chip->opened); in snd_bt87x_pcm_open()
433 struct snd_bt87x *chip = snd_pcm_substream_chip(substream); in snd_bt87x_close() local
435 spin_lock_irq(&chip->reg_lock); in snd_bt87x_close()
436 chip->reg_control |= CTL_A_PWRDN; in snd_bt87x_close()
437 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_close()
438 spin_unlock_irq(&chip->reg_lock); in snd_bt87x_close()
440 chip->substream = NULL; in snd_bt87x_close()
441 clear_bit(0, &chip->opened); in snd_bt87x_close()
449 struct snd_bt87x *chip = snd_pcm_substream_chip(substream); in snd_bt87x_hw_params() local
451 return snd_bt87x_create_risc(chip, substream, in snd_bt87x_hw_params()
458 struct snd_bt87x *chip = snd_pcm_substream_chip(substream); in snd_bt87x_hw_free() local
460 snd_bt87x_free_risc(chip); in snd_bt87x_hw_free()
466 struct snd_bt87x *chip = snd_pcm_substream_chip(substream); in snd_bt87x_prepare() local
467 struct snd_pcm_runtime *runtime = substream->runtime; in snd_bt87x_prepare()
470 spin_lock_irq(&chip->reg_lock); in snd_bt87x_prepare()
471 chip->reg_control &= ~(CTL_DA_SDR_MASK | CTL_DA_SBR); in snd_bt87x_prepare()
472 decimation = (ANALOG_CLOCK + runtime->rate / 4) / runtime->rate; in snd_bt87x_prepare()
473 chip->reg_control |= decimation << CTL_DA_SDR_SHIFT; in snd_bt87x_prepare()
474 if (runtime->format == SNDRV_PCM_FORMAT_S8) in snd_bt87x_prepare()
475 chip->reg_control |= CTL_DA_SBR; in snd_bt87x_prepare()
476 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_prepare()
477 spin_unlock_irq(&chip->reg_lock); in snd_bt87x_prepare()
481 static int snd_bt87x_start(struct snd_bt87x *chip) in snd_bt87x_start() argument
483 spin_lock(&chip->reg_lock); in snd_bt87x_start()
484 chip->current_line = 0; in snd_bt87x_start()
485 chip->reg_control |= CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN; in snd_bt87x_start()
486 snd_bt87x_writel(chip, REG_RISC_STRT_ADD, chip->dma_risc.addr); in snd_bt87x_start()
487 snd_bt87x_writel(chip, REG_PACKET_LEN, in snd_bt87x_start()
488 chip->line_bytes | (chip->lines << 16)); in snd_bt87x_start()
489 snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); in snd_bt87x_start()
490 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_start()
491 spin_unlock(&chip->reg_lock); in snd_bt87x_start()
495 static int snd_bt87x_stop(struct snd_bt87x *chip) in snd_bt87x_stop() argument
497 spin_lock(&chip->reg_lock); in snd_bt87x_stop()
498 chip->reg_control &= ~(CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN); in snd_bt87x_stop()
499 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_stop()
500 snd_bt87x_writel(chip, REG_INT_MASK, 0); in snd_bt87x_stop()
501 snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); in snd_bt87x_stop()
502 spin_unlock(&chip->reg_lock); in snd_bt87x_stop()
508 struct snd_bt87x *chip = snd_pcm_substream_chip(substream); in snd_bt87x_trigger() local
512 return snd_bt87x_start(chip); in snd_bt87x_trigger()
514 return snd_bt87x_stop(chip); in snd_bt87x_trigger()
516 return -EINVAL; in snd_bt87x_trigger()
522 struct snd_bt87x *chip = snd_pcm_substream_chip(substream); in snd_bt87x_pointer() local
523 struct snd_pcm_runtime *runtime = substream->runtime; in snd_bt87x_pointer()
525 return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes); in snd_bt87x_pointer()
541 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_bt87x_capture_volume_info()
542 info->count = 1; in snd_bt87x_capture_volume_info()
543 info->value.integer.min = 0; in snd_bt87x_capture_volume_info()
544 info->value.integer.max = 15; in snd_bt87x_capture_volume_info()
551 struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); in snd_bt87x_capture_volume_get() local
553 value->value.integer.value[0] = (chip->reg_control & CTL_A_GAIN_MASK) >> CTL_A_GAIN_SHIFT; in snd_bt87x_capture_volume_get()
560 struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); in snd_bt87x_capture_volume_put() local
564 spin_lock_irq(&chip->reg_lock); in snd_bt87x_capture_volume_put()
565 old_control = chip->reg_control; in snd_bt87x_capture_volume_put()
566 chip->reg_control = (chip->reg_control & ~CTL_A_GAIN_MASK) in snd_bt87x_capture_volume_put()
567 | (value->value.integer.value[0] << CTL_A_GAIN_SHIFT); in snd_bt87x_capture_volume_put()
568 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_capture_volume_put()
569 changed = old_control != chip->reg_control; in snd_bt87x_capture_volume_put()
570 spin_unlock_irq(&chip->reg_lock); in snd_bt87x_capture_volume_put()
587 struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); in snd_bt87x_capture_boost_get() local
589 value->value.integer.value[0] = !! (chip->reg_control & CTL_A_G2X); in snd_bt87x_capture_boost_get()
596 struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); in snd_bt87x_capture_boost_put() local
600 spin_lock_irq(&chip->reg_lock); in snd_bt87x_capture_boost_put()
601 old_control = chip->reg_control; in snd_bt87x_capture_boost_put()
602 chip->reg_control = (chip->reg_control & ~CTL_A_G2X) in snd_bt87x_capture_boost_put()
603 | (value->value.integer.value[0] ? CTL_A_G2X : 0); in snd_bt87x_capture_boost_put()
604 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_capture_boost_put()
605 changed = chip->reg_control != old_control; in snd_bt87x_capture_boost_put()
606 spin_unlock_irq(&chip->reg_lock); in snd_bt87x_capture_boost_put()
629 struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); in snd_bt87x_capture_source_get() local
631 value->value.enumerated.item[0] = (chip->reg_control & CTL_A_SEL_MASK) >> CTL_A_SEL_SHIFT; in snd_bt87x_capture_source_get()
638 struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol); in snd_bt87x_capture_source_put() local
642 spin_lock_irq(&chip->reg_lock); in snd_bt87x_capture_source_put()
643 old_control = chip->reg_control; in snd_bt87x_capture_source_put()
644 chip->reg_control = (chip->reg_control & ~CTL_A_SEL_MASK) in snd_bt87x_capture_source_put()
645 | (value->value.enumerated.item[0] << CTL_A_SEL_SHIFT); in snd_bt87x_capture_source_put()
646 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_capture_source_put()
647 changed = chip->reg_control != old_control; in snd_bt87x_capture_source_put()
648 spin_unlock_irq(&chip->reg_lock); in snd_bt87x_capture_source_put()
660 static int snd_bt87x_free(struct snd_bt87x *chip) in snd_bt87x_free() argument
662 if (chip->mmio) in snd_bt87x_free()
663 snd_bt87x_stop(chip); in snd_bt87x_free()
664 if (chip->irq >= 0) in snd_bt87x_free()
665 free_irq(chip->irq, chip); in snd_bt87x_free()
666 iounmap(chip->mmio); in snd_bt87x_free()
667 pci_release_regions(chip->pci); in snd_bt87x_free()
668 pci_disable_device(chip->pci); in snd_bt87x_free()
669 kfree(chip); in snd_bt87x_free()
675 struct snd_bt87x *chip = device->device_data; in snd_bt87x_dev_free() local
676 return snd_bt87x_free(chip); in snd_bt87x_dev_free()
679 static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name) in snd_bt87x_pcm() argument
684 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); in snd_bt87x_pcm()
687 pcm->private_data = chip; in snd_bt87x_pcm()
688 strcpy(pcm->name, name); in snd_bt87x_pcm()
691 &chip->pci->dev, in snd_bt87x_pcm()
701 struct snd_bt87x *chip; in snd_bt87x_create() local
713 chip = kzalloc(sizeof(*chip), GFP_KERNEL); in snd_bt87x_create()
714 if (!chip) { in snd_bt87x_create()
716 return -ENOMEM; in snd_bt87x_create()
718 chip->card = card; in snd_bt87x_create()
719 chip->pci = pci; in snd_bt87x_create()
720 chip->irq = -1; in snd_bt87x_create()
721 spin_lock_init(&chip->reg_lock); in snd_bt87x_create()
724 kfree(chip); in snd_bt87x_create()
728 chip->mmio = pci_ioremap_bar(pci, 0); in snd_bt87x_create()
729 if (!chip->mmio) { in snd_bt87x_create()
730 dev_err(card->dev, "cannot remap io memory\n"); in snd_bt87x_create()
731 err = -ENOMEM; in snd_bt87x_create()
735 chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 | in snd_bt87x_create()
737 chip->interrupt_mask = MY_INTERRUPTS; in snd_bt87x_create()
738 snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); in snd_bt87x_create()
739 snd_bt87x_writel(chip, REG_INT_MASK, 0); in snd_bt87x_create()
740 snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); in snd_bt87x_create()
742 err = request_irq(pci->irq, snd_bt87x_interrupt, IRQF_SHARED, in snd_bt87x_create()
743 KBUILD_MODNAME, chip); in snd_bt87x_create()
745 dev_err(card->dev, "cannot grab irq %d\n", pci->irq); in snd_bt87x_create()
748 chip->irq = pci->irq; in snd_bt87x_create()
749 card->sync_irq = chip->irq; in snd_bt87x_create()
752 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); in snd_bt87x_create()
756 *rchip = chip; in snd_bt87x_create()
760 snd_bt87x_free(chip); in snd_bt87x_create()
764 #define BT_DEVICE(chip, subvend, subdev, id) \ argument
766 .device = chip, \
768 .driver_data = SND_BT87X_BOARD_ ## id }
769 /* driver_data is the card id for that device */
780 /* ATI TV-Wonder */
792 /* Prolink PixelView PV-M4900 */
808 {0x1461, 0x0761}, /* AVermedia AverTV DVB-T */
809 {0x1461, 0x0771}, /* AVermedia DVB-T 771 */
810 {0x1822, 0x0001}, /* Twinhan VisionPlus DVB-T */
812 {0x18ac, 0xdb10}, /* DVICO FusionHDTV DVB-T Lite */
813 {0x18ac, 0xdb11}, /* Ultraview DVB-T Lite */
814 {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */
815 {0x7063, 0x2000}, /* pcHDTV HD-2000 TV */
820 /* return the id of the card, or a negative value if it's on the denylist */
827 if (supported && supported->driver_data > 0) in snd_bt87x_detect_card()
828 return supported->driver_data; in snd_bt87x_detect_card()
831 if (denylist[i].subvendor == pci->subsystem_vendor && in snd_bt87x_detect_card()
832 denylist[i].subdevice == pci->subsystem_device) { in snd_bt87x_detect_card()
833 dev_dbg(&pci->dev, in snd_bt87x_detect_card()
834 "card %#04x-%#04x:%#04x has no audio\n", in snd_bt87x_detect_card()
835 pci->device, pci->subsystem_vendor, pci->subsystem_device); in snd_bt87x_detect_card()
836 return -EBUSY; in snd_bt87x_detect_card()
839 dev_info(&pci->dev, "unknown card %#04x-%#04x:%#04x\n", in snd_bt87x_detect_card()
840 pci->device, pci->subsystem_vendor, pci->subsystem_device); in snd_bt87x_detect_card()
841 dev_info(&pci->dev, "please mail id, board name, and, " in snd_bt87x_detect_card()
843 "<alsa-devel@alsa-project.org>\n"); in snd_bt87x_detect_card()
852 struct snd_bt87x *chip; in snd_bt87x_probe() local
856 if (!pci_id->driver_data) { in snd_bt87x_probe()
859 return -ENODEV; in snd_bt87x_probe()
862 boardid = pci_id->driver_data; in snd_bt87x_probe()
865 return -ENODEV; in snd_bt87x_probe()
868 return -ENOENT; in snd_bt87x_probe()
871 err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, in snd_bt87x_probe()
876 err = snd_bt87x_create(card, pci, &chip); in snd_bt87x_probe()
880 memcpy(&chip->board, &snd_bt87x_boards[boardid], sizeof(chip->board)); in snd_bt87x_probe()
882 if (!chip->board.no_digital) { in snd_bt87x_probe()
884 chip->board.dig_rate = digital_rate[dev]; in snd_bt87x_probe()
886 chip->reg_control |= chip->board.digital_fmt; in snd_bt87x_probe()
888 err = snd_bt87x_pcm(chip, DEVICE_DIGITAL, "Bt87x Digital"); in snd_bt87x_probe()
892 if (!chip->board.no_analog) { in snd_bt87x_probe()
893 err = snd_bt87x_pcm(chip, DEVICE_ANALOG, "Bt87x Analog"); in snd_bt87x_probe()
897 &snd_bt87x_capture_volume, chip)); in snd_bt87x_probe()
901 &snd_bt87x_capture_boost, chip)); in snd_bt87x_probe()
905 &snd_bt87x_capture_source, chip)); in snd_bt87x_probe()
909 dev_info(card->dev, "bt87x%d: Using board %d, %sanalog, %sdigital " in snd_bt87x_probe()
911 chip->board.no_analog ? "no " : "", in snd_bt87x_probe()
912 chip->board.no_digital ? "no " : "", chip->board.dig_rate); in snd_bt87x_probe()
914 strcpy(card->driver, "Bt87x"); in snd_bt87x_probe()
915 sprintf(card->shortname, "Brooktree Bt%x", pci->device); in snd_bt87x_probe()
916 sprintf(card->longname, "%s at %#llx, irq %i", in snd_bt87x_probe()
917 card->shortname, (unsigned long long)pci_resource_start(pci, 0), in snd_bt87x_probe()
918 chip->irq); in snd_bt87x_probe()
919 strcpy(card->mixername, "Bt87x"); in snd_bt87x_probe()
939 /* default entries for all Bt87x cards - it's not exported */