📄 azt3328.c
字号:
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &snd_azf3328_hw_constraints_rates); snd_azf3328_dbgcallleave(); return 0;}static int snd_azf3328_capture_open(snd_pcm_substream_t * substream){ azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; snd_azf3328_dbgcallenter(); chip->capture_substream = substream; runtime->hw = snd_azf3328_capture; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &snd_azf3328_hw_constraints_rates); snd_azf3328_dbgcallleave(); return 0;}static int snd_azf3328_playback_close(snd_pcm_substream_t * substream){ azf3328_t *chip = snd_pcm_substream_chip(substream); snd_azf3328_dbgcallenter(); chip->playback_substream = NULL; snd_azf3328_dbgcallleave(); return 0;}static int snd_azf3328_capture_close(snd_pcm_substream_t * substream){ azf3328_t *chip = snd_pcm_substream_chip(substream); snd_azf3328_dbgcallenter(); chip->capture_substream = NULL; snd_azf3328_dbgcallleave(); return 0;}/******************************************************************/static snd_pcm_ops_t snd_azf3328_playback_ops = { .open = snd_azf3328_playback_open, .close = snd_azf3328_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_azf3328_hw_params, .hw_free = snd_azf3328_hw_free, .prepare = snd_azf3328_playback_prepare, .trigger = snd_azf3328_playback_trigger, .pointer = snd_azf3328_playback_pointer};static snd_pcm_ops_t snd_azf3328_capture_ops = { .open = snd_azf3328_capture_open, .close = snd_azf3328_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_azf3328_hw_params, .hw_free = snd_azf3328_hw_free, .prepare = snd_azf3328_capture_prepare, .trigger = snd_azf3328_capture_trigger, .pointer = snd_azf3328_capture_pointer};static void snd_azf3328_pcm_free(snd_pcm_t *pcm){ azf3328_t *chip = pcm->private_data; chip->pcm = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}static int __devinit snd_azf3328_pcm(azf3328_t *chip, int device){ snd_pcm_t *pcm; int err; snd_azf3328_dbgcallenter(); if ((err = snd_pcm_new(chip->card, "AZF3328 DSP", device, 1, 1, &pcm)) < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_azf3328_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_azf3328_capture_ops); pcm->private_data = chip; pcm->private_free = snd_azf3328_pcm_free; pcm->info_flags = 0; strcpy(pcm->name, chip->card->shortname); chip->pcm = pcm; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), 64*1024, 64*1024); snd_azf3328_dbgcallleave(); return 0;}/******************************************************************/static int snd_azf3328_free(azf3328_t *chip){ if (chip->irq < 0) goto __end_hw; /* reset (close) mixer */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); /* first mute master volume */ snd_azf3328_mixer_write(chip, IDX_MIXER_RESET, 0x0, WORD_VALUE); /* interrupt setup - mask everything */ /* FIXME */ synchronize_irq(chip->irq); __end_hw:#ifdef SUPPORT_JOYSTICK if (chip->res_joystick) { gameport_unregister_port(&chip->gameport); /* disable gameport */ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR, snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY); release_resource(chip->res_joystick); kfree_nocheck(chip->res_joystick); }#endif if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); pci_release_regions(chip->pci); kfree(chip); return 0;}static int snd_azf3328_dev_free(snd_device_t *device){ azf3328_t *chip = device->device_data; return snd_azf3328_free(chip);}#if 0/* check whether a bit can be modified */static void snd_azf3328_test_bit(unsigned int reg, int bit){ unsigned char val, valoff, valon; val = inb(reg); outb(val & ~(1 << bit), reg); valoff = inb(reg); outb(val|(1 << bit), reg); valon = inb(reg); outb(val, reg); printk(KERN_ERR "reg %04x bit %d: %02x %02x %02x\n", reg, bit, val, valoff, valon);}#endifstatic int __devinit snd_azf3328_create(snd_card_t * card, struct pci_dev *pci, unsigned long device_type, azf3328_t ** rchip){ azf3328_t *chip; int err; static snd_device_ops_t ops = { .dev_free = snd_azf3328_dev_free, }; u16 tmp; *rchip = NULL; if ((err = pci_enable_device(pci)) < 0) return err; chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; spin_lock_init(&chip->reg_lock); chip->card = card; chip->pci = pci; chip->irq = -1; /* check if we can restrict PCI DMA transfers to 24 bits */ if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { snd_printk("architecture does not support 24bit PCI busmaster DMA\n"); return -ENXIO; } if ((err = pci_request_regions(pci, "Aztech AZF3328")) < 0) { kfree(chip); return err; } chip->codec_port = pci_resource_start(pci, 0); chip->io2_port = pci_resource_start(pci, 1); chip->mpu_port = pci_resource_start(pci, 2); chip->synth_port = pci_resource_start(pci, 3); chip->mixer_port = pci_resource_start(pci, 4); if (request_irq(pci->irq, snd_azf3328_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { snd_printk("unable to grab IRQ %d\n", pci->irq); snd_azf3328_free(chip); return -EBUSY; } chip->irq = pci->irq; pci_set_master(pci); synchronize_irq(chip->irq); snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq); snd_azf3328_dbgmisc("io2 %02x %02x %02x %02x %02x %02x\n", snd_azf3328_io2_read(chip, 0), snd_azf3328_io2_read(chip, 1), snd_azf3328_io2_read(chip, 2), snd_azf3328_io2_read(chip, 3), snd_azf3328_io2_read(chip, 4), snd_azf3328_io2_read(chip, 5)); for (tmp=0; tmp <= 0x01; tmp += 1) snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp)); /* create mixer interface & switches */ if ((err = snd_azf3328_mixer_new(chip)) < 0) return err; if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_azf3328_free(chip); return err; }#if 0 /* set very low bitrate to reduce noise and power consumption? */ snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, 5512, 8, 1);#endif /* standard chip init stuff */ spin_lock_irq(&chip->reg_lock); outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_PLAY_FLAGS); outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_SOMETHING_FLAGS); outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_REC_FLAGS); outb(0x0, chip->codec_port + IDX_IO_IRQ63H); spin_unlock_irq(&chip->reg_lock); snd_card_set_dev(card, &pci->dev); *rchip = chip; return 0;}#ifdef SUPPORT_JOYSTICKstatic void __devinit snd_azf3328_config_joystick(azf3328_t *chip, int joystick){ unsigned char val; if (joystick == 1) { if ((chip->res_joystick = request_region(0x200, 8, "AZF3328 gameport")) != NULL) chip->gameport.io = 0x200; } val = inb(chip->io2_port + IDX_IO2_LEGACY_ADDR); if (chip->res_joystick) val |= LEGACY_JOY; else val &= ~LEGACY_JOY; outb(val, chip->io2_port + IDX_IO2_LEGACY_ADDR); if (chip->res_joystick) gameport_register_port(&chip->gameport);}#endifstatic int __devinit snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id){ static int dev; snd_card_t *card; azf3328_t *chip; opl3_t *opl3; int err; snd_azf3328_dbgcallenter(); if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { dev++; return -ENOENT; } card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0 ); if (card == NULL) return -ENOMEM; strcpy(card->driver, "AZF3328"); strcpy(card->shortname, "Aztech AZF3328 (PCI168)"); if ((err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip)) < 0) { snd_card_free(card); return err; } if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, chip->mpu_port, 1, pci->irq, 0, &chip->rmidi)) < 0) { snd_printk("azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); snd_card_free(card); return err; } if ((err = snd_azf3328_pcm(chip, 0)) < 0) { snd_card_free(card); return err; } if (snd_opl3_create(card, chip->synth_port, chip->synth_port+2, OPL3_HW_AUTO, 1, &opl3) < 0) { snd_printk("azf3328: no OPL3 device at 0x%lx-0x%lx?\n", chip->synth_port, chip->synth_port+2 ); } else { if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { snd_card_free(card); return err; } } snd_azf3328_dbgio(chip, "create"); sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, chip->codec_port, chip->irq); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; }#ifdef MODULE printk("azt3328: Experimental driver for Aztech AZF3328-based soundcards such as PCI168.\n""azt3328: ZERO support from Aztech: you might think hard about future purchase.\n""azt3328: Feel free to contact hw7oshyuv3001@sneakemail.com for bug reports etc.!\n");#endif#ifdef SUPPORT_JOYSTICK snd_azf3328_config_joystick(chip, joystick[dev]);#endif pci_set_drvdata(pci, card); dev++; snd_azf3328_dbgcallleave(); return 0;}static void __devexit snd_azf3328_remove(struct pci_dev *pci){ snd_azf3328_dbgcallenter(); snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); snd_azf3328_dbgcallleave();}static struct pci_driver driver = { .name = "AZF3328", .id_table = snd_azf3328_ids, .probe = snd_azf3328_probe, .remove = __devexit_p(snd_azf3328_remove),};static int __init alsa_card_azf3328_init(void){ int err; snd_azf3328_dbgcallenter(); err = pci_module_init(&driver); snd_azf3328_dbgcallleave(); return err;}static void __exit alsa_card_azf3328_exit(void){ snd_azf3328_dbgcallenter(); pci_unregister_driver(&driver); snd_azf3328_dbgcallleave();}module_init(alsa_card_azf3328_init)module_exit(alsa_card_azf3328_exit)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -