/* * probe function - creates the card manager */ static int __devinit snd_mixart_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; struct mixart_mgr *mgr; unsigned int i; int err; size_t size; /* */ if (dev >= SNDRV_CARDS) return -ENODEV; if (! enable[dev]) { dev++; return -ENOENT; } /* enable PCI device */ if ((err = pci_enable_device(pci)) < 0) return err; pci_set_master(pci); /* check if we can restrict PCI DMA transfers to 32 bits */ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) { snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n"); pci_disable_device(pci); return -ENXIO; } /* */ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); if (! mgr) { pci_disable_device(pci); return -ENOMEM; } mgr->pci = pci; mgr->irq = -1; /* resource assignment */ if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { kfree(mgr); pci_disable_device(pci); return err; } for (i = 0; i < 2; i++) { mgr->mem[i].phys = pci_resource_start(pci, i); mgr->mem[i].virt = pci_ioremap_bar(pci, i); if (!mgr->mem[i].virt) { printk(KERN_ERR "unable to remap resource 0x%lx\n", mgr->mem[i].phys); snd_mixart_free(mgr); return -EBUSY; } } if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_SHARED, CARD_NAME, mgr)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_mixart_free(mgr); return -EBUSY; } mgr->irq = pci->irq; sprintf(mgr->shortname, "Digigram miXart"); sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq); /* ISR spinlock */ spin_lock_init(&mgr->lock); /* init mailbox */ mgr->msg_fifo_readptr = 0; mgr->msg_fifo_writeptr = 0; spin_lock_init(&mgr->msg_lock); mutex_init(&mgr->msg_mutex); init_waitqueue_head(&mgr->msg_sleep); atomic_set(&mgr->msg_processed, 0); /* init setup mutex*/ mutex_init(&mgr->setup_mutex); /* init message taslket */ tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr); /* card assignment */ mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */ for (i = 0; i < mgr->num_cards; i++) { struct snd_card *card; char tmpid[16]; int idx; if (index[dev] < 0) idx = index[dev]; else idx = index[dev] + i; snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i); card = snd_card_new(idx, tmpid, THIS_MODULE, 0); if (! card) { snd_printk(KERN_ERR "cannot allocate the card %d\n", i); snd_mixart_free(mgr); return -ENOMEM; } strcpy(card->driver, CARD_NAME); sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i); sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); if ((err = snd_mixart_create(mgr, card, i)) < 0) { snd_card_free(card); snd_mixart_free(mgr); return err; } if(i==0) { /* init proc interface only for chip0 */ snd_mixart_proc_init(mgr->chip[i]); } if ((err = snd_card_register(card)) < 0) { snd_mixart_free(mgr); return err; } } /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */ mgr->board_type = MIXART_DAUGHTER_TYPE_NONE; /* create array of streaminfo */ size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(struct mixart_flowinfo)) ); if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), size, &mgr->flowinfo) < 0) { snd_mixart_free(mgr); return -ENOMEM; } /* init streaminfo_array */ memset(mgr->flowinfo.area, 0, size); /* create array of bufferinfo */ size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(struct mixart_bufferinfo)) ); if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), size, &mgr->bufferinfo) < 0) { snd_mixart_free(mgr); return -ENOMEM; } /* init bufferinfo_array */ memset(mgr->bufferinfo.area, 0, size); /* set up firmware */ err = snd_mixart_setup_firmware(mgr); if (err < 0) { snd_mixart_free(mgr); return err; } pci_set_drvdata(pci, mgr); dev++; return 0; }
static int __devinit snd_vx222_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; struct snd_vx_hardware *hw; struct snd_vx222 *vx; int err; if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { dev++; return -ENOENT; } err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) return err; switch ((int)pci_id->driver_data) { case VX_PCI_VX222_OLD: hw = &vx222_old_hw; break; case VX_PCI_VX222_NEW: default: if (mic[dev]) hw = &vx222_mic_hw; else hw = &vx222_v2_hw; break; } if ((err = snd_vx222_create(card, pci, hw, &vx)) < 0) { snd_card_free(card); return err; } card->private_data = vx; vx->core.ibl.size = ibl[dev]; sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %i", card->shortname, vx->port[0], vx->port[1], vx->core.irq); snd_printdd("%s at 0x%lx & 0x%lx, irq %i\n", card->shortname, vx->port[0], vx->port[1], vx->core.irq); #ifdef SND_VX_FW_LOADER vx->core.dev = &pci->dev; #endif if ((err = snd_vx_setup_firmware(&vx->core)) < 0) { snd_card_free(card); return err; } if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } pci_set_drvdata(pci, card); dev++; return 0; }
static int snd_trident_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; struct snd_trident *trident; const char *str; int err, pcm_dev = 0; if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { dev++; return -ENOENT; } err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) return err; if ((err = snd_trident_create(card, pci, pcm_channels[dev], ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2, wavetable_size[dev], &trident)) < 0) { snd_card_free(card); return err; } card->private_data = trident; switch (trident->device) { case TRIDENT_DEVICE_ID_DX: str = "TRID4DWAVEDX"; break; case TRIDENT_DEVICE_ID_NX: str = "TRID4DWAVENX"; break; case TRIDENT_DEVICE_ID_SI7018: str = "SI7018"; break; default: str = "Unknown"; } strcpy(card->driver, str); if (trident->device == TRIDENT_DEVICE_ID_SI7018) { strcpy(card->shortname, "SiS "); } else { strcpy(card->shortname, "Trident "); } strcat(card->shortname, card->driver); sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d", card->shortname, trident->port, trident->irq); if ((err = snd_trident_pcm(trident, pcm_dev++, NULL)) < 0) { snd_card_free(card); return err; } switch (trident->device) { case TRIDENT_DEVICE_ID_DX: case TRIDENT_DEVICE_ID_NX: if ((err = snd_trident_foldback_pcm(trident, pcm_dev++, NULL)) < 0) { snd_card_free(card); return err; } break; } if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) { if ((err = snd_trident_spdif_pcm(trident, pcm_dev++, NULL)) < 0) { snd_card_free(card); return err; } } if (trident->device != TRIDENT_DEVICE_ID_SI7018 && (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, trident->midi_port, MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK, -1, &trident->rmidi)) < 0) { snd_card_free(card); return err; } snd_trident_create_gameport(trident); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } pci_set_drvdata(pci, card); dev++; return 0; }
static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; struct snd_cs46xx *chip; int err; 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; if ((err = snd_cs46xx_create(card, pci, external_amp[dev], thinkpad[dev], &chip)) < 0) { snd_card_free(card); return err; } card->private_data = chip; chip->accept_valid = mmap_valid[dev]; if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) { snd_card_free(card); return err; } #ifdef CONFIG_SND_CS46XX_NEW_DSP if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) { snd_card_free(card); return err; } if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) { snd_card_free(card); return err; } #endif if ((err = snd_cs46xx_mixer(chip, 2)) < 0) { snd_card_free(card); return err; } #ifdef CONFIG_SND_CS46XX_NEW_DSP if (chip->nr_ac97_codecs ==2) { if ((err = snd_cs46xx_pcm_center_lfe(chip,3,NULL)) < 0) { snd_card_free(card); return err; } } #endif if ((err = snd_cs46xx_midi(chip, 0, NULL)) < 0) { snd_card_free(card); return err; } if ((err = snd_cs46xx_start_dsp(chip)) < 0) { snd_card_free(card); return err; } snd_cs46xx_gameport(chip); strcpy(card->driver, "CS46xx"); strcpy(card->shortname, "Sound Fusion CS46xx"); sprintf(card->longname, "%s at 0x%lx/0x%lx, irq %i", card->shortname, chip->ba0_addr, chip->ba1_addr, chip->irq); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } pci_set_drvdata(pci, card); dev++; return 0; }
static int efw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { struct snd_card *card; struct snd_efw *efw; int card_index, err; mutex_lock(&devices_mutex); /* check registered cards */ for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { if (!test_bit(card_index, devices_used) && enable[card_index]) break; } if (card_index >= SNDRV_CARDS) { err = -ENOENT; goto end; } err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, sizeof(struct snd_efw), &card); if (err < 0) goto end; efw = card->private_data; efw->card_index = card_index; set_bit(card_index, devices_used); card->private_free = efw_card_free; efw->card = card; efw->unit = unit; mutex_init(&efw->mutex); spin_lock_init(&efw->lock); init_waitqueue_head(&efw->hwdep_wait); /* prepare response buffer */ snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, SND_EFW_RESPONSE_MAXIMUM_BYTES, 4096U); efw->resp_buf = kzalloc(snd_efw_resp_buf_size, GFP_KERNEL); if (efw->resp_buf == NULL) { err = -ENOMEM; goto error; } efw->pull_ptr = efw->push_ptr = efw->resp_buf; snd_efw_transaction_add_instance(efw); err = get_hardware_info(efw); if (err < 0) goto error; if (entry->model_id == MODEL_ECHO_AUDIOFIRE_9) efw->is_af9 = true; snd_efw_proc_init(efw); if (efw->midi_out_ports || efw->midi_in_ports) { err = snd_efw_create_midi_devices(efw); if (err < 0) goto error; } err = snd_efw_create_pcm_devices(efw); if (err < 0) goto error; err = snd_efw_create_hwdep_device(efw); if (err < 0) goto error; err = snd_efw_stream_init_duplex(efw); if (err < 0) goto error; err = snd_card_register(card); if (err < 0) { snd_efw_stream_destroy_duplex(efw); goto error; } dev_set_drvdata(&unit->device, efw); end: mutex_unlock(&devices_mutex); return err; error: snd_efw_transaction_remove_instance(efw); mutex_unlock(&devices_mutex); snd_card_free(card); return err; }
static int __devinit snd_msnd_attach(struct snd_card *card) { struct snd_msnd *chip = card->private_data; int err; static struct snd_device_ops ops = { .dev_free = snd_msnd_dev_free, }; err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname, chip); if (err < 0) { printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); return err; } if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) { free_irq(chip->irq, chip); return -EBUSY; } if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) { printk(KERN_ERR LOGNAME ": unable to grab memory region 0x%lx-0x%lx\n", chip->base, chip->base + BUFFSIZE - 1); release_region(chip->io, DSP_NUMIO); free_irq(chip->irq, chip); return -EBUSY; } chip->mappedbase = ioremap_nocache(chip->base, 0x8000); if (!chip->mappedbase) { printk(KERN_ERR LOGNAME ": unable to map memory region 0x%lx-0x%lx\n", chip->base, chip->base + BUFFSIZE - 1); err = -EIO; goto err_release_region; } err = snd_msnd_dsp_full_reset(card); if (err < 0) goto err_release_region; /* Register device */ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) goto err_release_region; err = snd_msnd_pcm(card, 0, NULL); if (err < 0) { printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); goto err_release_region; } err = snd_msndmix_new(card); if (err < 0) { printk(KERN_ERR LOGNAME ": error creating new Mixer device\n"); goto err_release_region; } if (mpu_io[0] != SNDRV_AUTO_PORT) { struct snd_mpu401 *mpu; err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpu_io[0], MPU401_MODE_INPUT | MPU401_MODE_OUTPUT, mpu_irq[0], IRQF_DISABLED, &chip->rmidi); if (err < 0) { printk(KERN_ERR LOGNAME ": error creating new Midi device\n"); goto err_release_region; } mpu = chip->rmidi->private_data; mpu->open_input = snd_msnd_mpu401_open; mpu->close_input = snd_msnd_mpu401_close; mpu->private_data = chip; } disable_irq(chip->irq); snd_msnd_calibrate_adc(chip, chip->play_sample_rate); snd_msndmix_force_recsrc(chip, 0); err = snd_card_register(card); if (err < 0) goto err_release_region; return 0; err_release_region: if (chip->mappedbase) iounmap(chip->mappedbase); release_mem_region(chip->base, BUFFSIZE); release_region(chip->io, DSP_NUMIO); free_irq(chip->irq, chip); return err; }
static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; snd_card_t *card; emu10k1_t *emu; #ifdef ENABLE_SYNTH snd_seq_device_t *wave = NULL; #endif int err; 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; if (max_buffer_size[dev] < 32) max_buffer_size[dev] = 32; else if (max_buffer_size[dev] > 1024) max_buffer_size[dev] = 1024; if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], (long)max_buffer_size[dev] * 1024 * 1024, enable_ir[dev], &emu)) < 0) { snd_card_free(card); return err; } if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) { snd_card_free(card); return err; } if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) { snd_card_free(card); return err; } if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) { snd_card_free(card); return err; } if ((err = snd_emu10k1_mixer(emu)) < 0) { snd_card_free(card); return err; } if ((err = snd_emu10k1_timer(emu, 0)) < 0) { snd_card_free(card); return err; } if (emu->audigy) { if ((err = snd_emu10k1_audigy_midi(emu)) < 0) { snd_card_free(card); return err; } } else { if ((err = snd_emu10k1_midi(emu)) < 0) { snd_card_free(card); return err; } } if ((err = snd_emu10k1_fx8010_new(emu, 0, NULL)) < 0) { snd_card_free(card); return err; } #ifdef ENABLE_SYNTH if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, sizeof(snd_emu10k1_synth_arg_t), &wave) < 0 || wave == NULL) { snd_printk("can't initialize Emu10k1 wavetable synth\n"); } else { snd_emu10k1_synth_arg_t *arg; arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); strcpy(wave->name, "Emu-10k1 Synth"); arg->hwptr = emu; arg->index = 1; arg->seq_ports = seq_ports[dev]; arg->max_voices = max_synth_voices[dev]; } #endif if (emu->audigy && (emu->serial == 0x10011102) ) { strcpy(card->driver, "Audigy2"); strcpy(card->shortname, "Sound Blaster Audigy2_Value"); } else if (emu->audigy && (emu->revision == 4) ) { strcpy(card->driver, "Audigy2"); strcpy(card->shortname, "Sound Blaster Audigy2"); } else if (emu->audigy) { strcpy(card->driver, "Audigy"); strcpy(card->shortname, "Sound Blaster Audigy"); } else if (emu->APS) { strcpy(card->driver, "E-mu APS"); strcpy(card->shortname, "E-mu APS"); } else { strcpy(card->driver, "EMU10K1"); strcpy(card->shortname, "Sound Blaster Live!"); } sprintf(card->longname, "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", card->shortname, emu->revision, emu->serial, emu->port, emu->irq); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } pci_set_drvdata(pci, card); dev++; return 0; }
static int __devinit snd_wavefront_probe (struct snd_card *card, int dev) { snd_wavefront_card_t *acard = card->private_data; struct snd_wss *chip; struct snd_hwdep *wavefront_synth; struct snd_rawmidi *ics2115_internal_rmidi = NULL; struct snd_rawmidi *ics2115_external_rmidi = NULL; struct snd_hwdep *fx_processor; int hw_dev = 0, midi_dev = 0, err; /* --------- PCM --------------- */ err = snd_wss_create(card, cs4232_pcm_port[dev], -1, cs4232_pcm_irq[dev], dma1[dev], dma2[dev], WSS_HW_DETECT, 0, &chip); if (err < 0) { snd_printk(KERN_ERR "can't allocate WSS device\n"); return err; } err = snd_wss_pcm(chip, 0, NULL); if (err < 0) return err; err = snd_wss_timer(chip, 0, NULL); if (err < 0) return err; /* ---------- OPL3 synth --------- */ if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { struct snd_opl3 *opl3; err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, OPL3_HW_OPL3_CS, 0, &opl3); if (err < 0) { snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n"); return err; } err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL); if (err < 0) return err; hw_dev++; } /* ------- ICS2115 Wavetable synth ------- */ acard->wavefront.res_base = request_region(ics2115_port[dev], 16, "ICS2115"); if (acard->wavefront.res_base == NULL) { snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", ics2115_port[dev], ics2115_port[dev] + 16 - 1); return -EBUSY; } if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, IRQF_DISABLED, "ICS2115", acard)) { snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); return -EBUSY; } acard->wavefront.irq = ics2115_irq[dev]; acard->wavefront.base = ics2115_port[dev]; wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard); if (wavefront_synth == NULL) { snd_printk (KERN_ERR "can't create WaveFront synth device\n"); return -ENOMEM; } strcpy (wavefront_synth->name, "ICS2115 Wavetable MIDI Synthesizer"); wavefront_synth->iface = SNDRV_HWDEP_IFACE_ICS2115; hw_dev++; /* --------- Mixer ------------ */ err = snd_wss_mixer(chip); if (err < 0) { snd_printk (KERN_ERR "can't allocate mixer device\n"); return err; } /* -------- CS4232 MPU-401 interface -------- */ if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, cs4232_mpu_port[dev], 0, cs4232_mpu_irq[dev], IRQF_DISABLED, NULL); if (err < 0) { snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); return err; } midi_dev++; } /* ------ ICS2115 internal MIDI ------------ */ if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) { ics2115_internal_rmidi = snd_wavefront_new_midi (card, midi_dev, acard, ics2115_port[dev], internal_mpu); if (ics2115_internal_rmidi == NULL) { snd_printk (KERN_ERR "can't setup ICS2115 internal MIDI device\n"); return -ENOMEM; } midi_dev++; } /* ------ ICS2115 external MIDI ------------ */ if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) { ics2115_external_rmidi = snd_wavefront_new_midi (card, midi_dev, acard, ics2115_port[dev], external_mpu); if (ics2115_external_rmidi == NULL) { snd_printk (KERN_ERR "can't setup ICS2115 external MIDI device\n"); return -ENOMEM; } midi_dev++; } /* FX processor for Tropez+ */ if (acard->wavefront.has_fx) { fx_processor = snd_wavefront_new_fx (card, hw_dev, acard, ics2115_port[dev]); if (fx_processor == NULL) { snd_printk (KERN_ERR "can't setup FX device\n"); return -ENOMEM; } hw_dev++; strcpy(card->driver, "Tropez+"); strcpy(card->shortname, "Turtle Beach Tropez+"); } else { /* Need a way to distinguish between Maui and Tropez */ strcpy(card->driver, "WaveFront"); strcpy(card->shortname, "Turtle Beach WaveFront"); } /* ----- Register the card --------- */ /* Not safe to include "Turtle Beach" in longname, due to length restrictions */ sprintf(card->longname, "%s PCM 0x%lx irq %d dma %d", card->driver, chip->port, cs4232_pcm_irq[dev], dma1[dev]); if (dma2[dev] >= 0 && dma2[dev] < 8) sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { sprintf (card->longname + strlen (card->longname), " MPU-401 0x%lx irq %d", cs4232_mpu_port[dev], cs4232_mpu_irq[dev]); } sprintf (card->longname + strlen (card->longname), " SYNTH 0x%lx irq %d", ics2115_port[dev], ics2115_irq[dev]); return snd_card_register(card); }
static void do_registration(struct work_struct *work) { struct snd_bebob *bebob = container_of(work, struct snd_bebob, dwork.work); unsigned int card_index; int err; if (bebob->registered) return; mutex_lock(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { if (!test_bit(card_index, devices_used) && enable[card_index]) break; } if (card_index >= SNDRV_CARDS) { mutex_unlock(&devices_mutex); return; } err = snd_card_new(&bebob->unit->device, index[card_index], id[card_index], THIS_MODULE, 0, &bebob->card); if (err < 0) { mutex_unlock(&devices_mutex); return; } err = name_device(bebob); if (err < 0) goto error; if (bebob->spec == &maudio_special_spec) { if (bebob->entry->model_id == MODEL_MAUDIO_FW1814) err = snd_bebob_maudio_special_discover(bebob, true); else err = snd_bebob_maudio_special_discover(bebob, false); } else { err = snd_bebob_stream_discover(bebob); } if (err < 0) goto error; err = snd_bebob_stream_init_duplex(bebob); if (err < 0) goto error; snd_bebob_proc_init(bebob); if (bebob->midi_input_ports > 0 || bebob->midi_output_ports > 0) { err = snd_bebob_create_midi_devices(bebob); if (err < 0) goto error; } err = snd_bebob_create_pcm_devices(bebob); if (err < 0) goto error; err = snd_bebob_create_hwdep_device(bebob); if (err < 0) goto error; err = snd_card_register(bebob->card); if (err < 0) goto error; set_bit(card_index, devices_used); mutex_unlock(&devices_mutex); /* * After registered, bebob instance can be released corresponding to * releasing the sound card instance. */ bebob->card->private_free = bebob_card_free; bebob->card->private_data = bebob; bebob->registered = true; return; error: mutex_unlock(&devices_mutex); snd_bebob_stream_destroy_duplex(bebob); snd_card_free(bebob->card); dev_info(&bebob->unit->device, "Sound card registration failed: %d\n", err); }
static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) { struct snd_card *card; struct snd_gus_card *gus; int error; card = snd_card_new(index[n], id[n], THIS_MODULE, 0); if (!card) return -EINVAL; if (pcm_channels[n] < 2) pcm_channels[n] = 2; error = snd_gusclassic_create(card, dev, n, &gus); if (error < 0) goto out; error = snd_gusclassic_detect(gus); if (error < 0) goto out; gus->joystick_dac = joystick_dac[n]; error = snd_gus_initialize(gus); if (error < 0) goto out; error = -ENODEV; if (gus->max_flag || gus->ess_flag) { dev_err(dev, "GUS Classic or ACE soundcard was " "not detected at 0x%lx\n", gus->gf1.port); goto out; } error = snd_gf1_new_mixer(gus); if (error < 0) goto out; error = snd_gf1_pcm_new(gus, 0, 0, NULL); if (error < 0) goto out; if (!gus->ace_flag) { error = snd_gf1_rawmidi_new(gus, 0, NULL); if (error < 0) goto out; } sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, gus->gf1.irq, gus->gf1.dma1); if (gus->gf1.dma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%d", gus->gf1.dma2); snd_card_set_dev(card, dev); error = snd_card_register(card); if (error < 0) goto out; dev_set_drvdata(dev, card); return 0; out: snd_card_free(card); return error; }
static int __init snd_sgalaxy_probe(int dev) { static int possible_irqs[] = {7, 9, 10, 11, -1}; static int possible_dmas[] = {1, 3, 0, -1}; int err, xirq, xdma1; snd_card_t *card; ad1848_t *chip; if (sbport[dev] == SNDRV_AUTO_PORT) { snd_printk("specify SB port\n"); return -EINVAL; } if (wssport[dev] == SNDRV_AUTO_PORT) { snd_printk("specify WSS port\n"); return -EINVAL; } card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; xirq = irq[dev]; if (xirq == SNDRV_AUTO_IRQ) { if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { snd_card_free(card); snd_printk("unable to find a free IRQ\n"); return -EBUSY; } } xdma1 = dma1[dev]; if (xdma1 == SNDRV_AUTO_DMA) { if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { snd_card_free(card); snd_printk("unable to find a free DMA\n"); return -EBUSY; } } if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0) { snd_card_free(card); return err; } if ((err = snd_ad1848_create(card, wssport[dev] + 4, xirq, xdma1, AD1848_HW_DETECT, &chip)) < 0) { snd_card_free(card); return err; } if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) { snd_printdd("sgalaxy - error creating new ad1848 PCM device\n"); snd_card_free(card); return err; } if ((err = snd_ad1848_mixer(chip)) < 0) { snd_printdd("sgalaxy - error creating new ad1848 mixer\n"); snd_card_free(card); return err; } if (snd_sgalaxy_mixer(chip) < 0) { snd_printdd("sgalaxy - the mixer rewrite failed\n"); snd_card_free(card); return err; } strcpy(card->driver, "Sound Galaxy"); strcpy(card->shortname, "Sound Galaxy"); sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d", wssport[dev], xirq, xdma1); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } snd_sgalaxy_cards[dev] = card; return 0; }
static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev) { int i, ret; u64 lpar_addr, lpar_size; BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND); the_card.ps3_dev = dev; ret = ps3_open_hv_device(dev); if (ret) return -ENXIO; /* setup MMIO */ ret = lv1_gpu_device_map(2, &lpar_addr, &lpar_size); if (ret) { pr_info("%s: device map 2 failed %d\n", __func__, ret); goto clean_open; } ps3_mmio_region_init(dev, dev->m_region, lpar_addr, lpar_size, PAGE_SHIFT); ret = snd_ps3_map_mmio(); if (ret) goto clean_dev_map; /* setup DMA area */ ps3_dma_region_init(dev, dev->d_region, PAGE_SHIFT, /* use system page size */ 0, /* dma type; not used */ NULL, _ALIGN_UP(SND_PS3_DMA_REGION_SIZE, PAGE_SIZE)); dev->d_region->ioid = PS3_AUDIO_IOID; ret = ps3_dma_region_create(dev->d_region); if (ret) { pr_info("%s: region_create\n", __func__); goto clean_mmio; } snd_ps3_audio_set_base_addr(dev->d_region->bus_addr); /* CONFIG_SND_PS3_DEFAULT_START_DELAY */ the_card.start_delay = snd_ps3_start_delay; /* irq */ if (snd_ps3_allocate_irq()) { ret = -ENXIO; goto clean_dma_region; } /* create card instance */ ret = snd_card_create(index, id, THIS_MODULE, 0, &the_card.card); if (ret < 0) goto clean_irq; strcpy(the_card.card->driver, "PS3"); strcpy(the_card.card->shortname, "PS3"); strcpy(the_card.card->longname, "PS3 sound"); /* create control elements */ for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) { ret = snd_ctl_add(the_card.card, snd_ctl_new1(&spdif_ctls[i], &the_card)); if (ret < 0) goto clean_card; } /* create PCM devices instance */ /* NOTE:this driver works assuming pcm:substream = 1:1 */ ret = snd_pcm_new(the_card.card, "SPDIF", 0, /* instance index, will be stored pcm.device*/ 1, /* output substream */ 0, /* input substream */ &(the_card.pcm)); if (ret) goto clean_card; the_card.pcm->private_data = &the_card; strcpy(the_card.pcm->name, "SPDIF"); /* set pcm ops */ snd_pcm_set_ops(the_card.pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ps3_pcm_spdif_ops); the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED; /* pre-alloc PCM DMA buffer*/ ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm, SNDRV_DMA_TYPE_DEV, &dev->core, SND_PS3_PCM_PREALLOC_SIZE, SND_PS3_PCM_PREALLOC_SIZE); if (ret < 0) { pr_info("%s: prealloc failed\n", __func__); goto clean_card; } /* * allocate null buffer * its size should be lager than PS3_AUDIO_FIFO_STAGE_SIZE * 2 * PAGE_SIZE is enogh */ the_card.null_buffer_start_vaddr = dma_alloc_coherent(&the_card.ps3_dev->core, PAGE_SIZE, &the_card.null_buffer_start_dma_addr, GFP_KERNEL); if (!the_card.null_buffer_start_vaddr) { pr_info("%s: nullbuffer alloc failed\n", __func__); goto clean_preallocate; } pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, the_card.null_buffer_start_vaddr, the_card.null_buffer_start_dma_addr); /* set default sample rate/word width */ snd_ps3_init_avsetting(&the_card); /* register the card */ snd_card_set_dev(the_card.card, &dev->core); ret = snd_card_register(the_card.card); if (ret < 0) goto clean_dma_map; pr_info("%s started. start_delay=%dms\n", the_card.card->longname, the_card.start_delay); return 0; clean_dma_map: dma_free_coherent(&the_card.ps3_dev->core, PAGE_SIZE, the_card.null_buffer_start_vaddr, the_card.null_buffer_start_dma_addr); clean_preallocate: snd_pcm_lib_preallocate_free_for_all(the_card.pcm); clean_card: snd_card_free(the_card.card); clean_irq: snd_ps3_free_irq(); clean_dma_region: ps3_dma_region_free(dev->d_region); clean_mmio: snd_ps3_unmap_mmio(); clean_dev_map: lv1_gpu_device_unmap(2); clean_open: ps3_close_hv_device(dev); /* * there is no destructor function to pcm. * midlayer automatically releases if the card removed */ return ret; }; /* snd_ps3_probe */
static int __init snd_gusextreme_probe(int dev) { static int possible_ess_irqs[] = {5, 9, 10, 7, -1}; static int possible_ess_dmas[] = {1, 3, 0, -1}; static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1}; int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma; snd_card_t *card; struct snd_gusextreme *acard; snd_gus_card_t *gus; es1688_t *es1688; opl3_t *opl3; int err; card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; acard = (struct snd_gusextreme *)card->private_data; xgf1_irq = gf1_irq[dev]; if (xgf1_irq == SNDRV_AUTO_IRQ) { if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) { snd_printk("unable to find a free IRQ for GF1\n"); err = -EBUSY; goto out; } } xess_irq = irq[dev]; if (xess_irq == SNDRV_AUTO_IRQ) { if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) { snd_printk("unable to find a free IRQ for ES1688\n"); err = -EBUSY; goto out; } } if (mpu_port[dev] == SNDRV_AUTO_PORT) mpu_port[dev] = 0; xmpu_irq = mpu_irq[dev]; if (xmpu_irq > 15) xmpu_irq = -1; xgf1_dma = dma1[dev]; if (xgf1_dma == SNDRV_AUTO_DMA) { if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) { snd_printk("unable to find a free DMA for GF1\n"); err = -EBUSY; goto out; } } xess_dma = dma8[dev]; if (xess_dma == SNDRV_AUTO_DMA) { if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) { snd_printk("unable to find a free DMA for ES1688\n"); err = -EBUSY; goto out; } } if ((err = snd_es1688_create(card, port[dev], mpu_port[dev], xess_irq, xmpu_irq, xess_dma, ES1688_HW_1688, &es1688)) < 0) goto out; if (gf1_port[dev] < 0) gf1_port[dev] = port[dev] + 0x20; if ((err = snd_gus_create(card, gf1_port[dev], xgf1_irq, xgf1_dma, -1, 0, channels[dev], pcm_channels[dev], 0, &gus)) < 0) goto out; if ((err = snd_gusextreme_detect(dev, card, gus, es1688)) < 0) goto out; snd_gusextreme_init(dev, gus); if ((err = snd_gus_initialize(gus)) < 0) goto out; if (!gus->ess_flag) { snd_printdd("GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port); err = -ENODEV; goto out; } if ((err = snd_es1688_pcm(es1688, 0, NULL)) < 0) goto out; if ((err = snd_es1688_mixer(es1688)) < 0) goto out; snd_component_add(card, "ES1688"); if (pcm_channels[dev] > 0) { if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) goto out; } if ((err = snd_gf1_new_mixer(gus)) < 0) goto out; if ((err = snd_gusextreme_mixer(es1688)) < 0) goto out; if (snd_opl3_create(card, es1688->port, es1688->port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) { printk(KERN_ERR "gusextreme: opl3 not detected at 0x%lx\n", es1688->port); } else { if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0) goto out; } if (es1688->mpu_port >= 0x300 && (err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, es1688->mpu_port, 0, xmpu_irq, SA_INTERRUPT, NULL)) < 0) goto out; sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i", es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma); if ((err = snd_card_register(card)) < 0) goto out; snd_gusextreme_cards[dev] = card; return 0; out: snd_card_free(card); return err; }
static int vaudio_snd_init_card (NkVaudio dev) { int err = 0; int i, j; /* * Wait until the backend is on. */ while (dev->vlink->c_state != dev->vlink->s_state) { msleep_interruptible(10); } for (i = 0; i < NK_VAUDIO_DEV_MAX; i++) { for (j = 0; j < NK_VAUDIO_STREAM_MAX; j++) { struct snd_pcm_hardware* pcm_hw; const NkVaudioHw* config = dev->s[i][j].hw_conf; if (j == SNDRV_PCM_STREAM_PLAYBACK) { pcm_hw = &vaudio_snd_playback[i][j]; } else { pcm_hw = &vaudio_snd_capture[i][j]; } pcm_hw->info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID); if (!(config->stream_cap & HW_CAP_PCM)) { err = -ENODEV; goto nodev; } pcm_hw->formats = config->pcm.formats; pcm_hw->rates = config->pcm.rates; pcm_hw->rate_min = config->pcm.rate_min; pcm_hw->rate_max = config->pcm.rate_max; pcm_hw->channels_min = config->pcm.channels_min; pcm_hw->channels_max = config->pcm.channels_max; pcm_hw->buffer_bytes_max = config->pcm.buffer_bytes_max; if (pcm_hw->buffer_bytes_max > NK_VAUDIO_MAX_RING_SIZE) { pcm_hw->buffer_bytes_max = NK_VAUDIO_MAX_RING_SIZE; } pcm_hw->period_bytes_min = config->pcm.period_bytes_min; pcm_hw->period_bytes_max = config->pcm.period_bytes_max; pcm_hw->periods_min = config->pcm.periods_min; if (pcm_hw->periods_min < 8) { pcm_hw->periods_min = 8; } pcm_hw->periods_max = config->pcm.periods_max; if (pcm_hw->periods_max > NK_VAUDIO_RING_DESC_NB) { pcm_hw->periods_max = NK_VAUDIO_RING_DESC_NB; } pcm_hw->fifo_size = config->pcm.fifo_size; if (config->stream_cap & HW_CAP_DMA) { dev->s[i][j].use_dma = 1; } else { dev->s[i][j].use_dma = 0; } } if ((err = vaudio_snd_card_pcm(dev, i)) < 0) { WTRACE("device %d initialization failed\n", i); } } if ((err = vaudio_snd_mixer(dev)) < 0) goto nodev; snprintf (dev->card->driver, sizeof dev->card->driver, "VAUDIO"); snprintf (dev->card->shortname, sizeof dev->card->shortname, "VIRTUAL AUDIO"); snprintf (dev->card->longname, sizeof dev->card->longname, "VIRTUAL AUDIO"); do { /* * Here ALSA sound core might not be setup yet. * We wait until the registering of vaudio card is successful. */ if ((err = snd_card_register(dev->card)) == 0) { TRACE("audio support initialized\n"); return 0; } msleep_interruptible(10); } while (err); nodev: ETRACE ("initialization failed\n"); return err; }
// constructor -- see "Constructor" sub-section static int __devinit snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; vortex_t *chip; int err; // (1) if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { dev++; return -ENOENT; } // (2) err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) return err; // (3) if ((err = snd_vortex_create(card, pci, &chip)) < 0) { snd_card_free(card); return err; } snd_vortex_workaround(pci, pcifix[dev]); // Card details needed in snd_vortex_midi strcpy(card->driver, CARD_NAME_SHORT); sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT); sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->io, chip->irq); // (4) Alloc components. err = snd_vortex_mixer(chip); if (err < 0) { snd_card_free(card); return err; } // ADB pcm. err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM); if (err < 0) { snd_card_free(card); return err; } #ifndef CHIP_AU8820 // ADB SPDIF if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) { snd_card_free(card); return err; } // A3D if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) { snd_card_free(card); return err; } #endif /* // ADB I2S if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) { snd_card_free(card); return err; } */ #ifndef CHIP_AU8810 // WT pcm. if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) { snd_card_free(card); return err; } #endif if ((err = snd_vortex_midi(chip)) < 0) { snd_card_free(card); return err; } vortex_gameport_register(chip); #if 0 if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH, sizeof(snd_vortex_synth_arg_t), &wave) < 0 || wave == NULL) { snd_printk(KERN_ERR "Can't initialize Aureal wavetable synth\n"); } else { snd_vortex_synth_arg_t *arg; arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); strcpy(wave->name, "Aureal Synth"); arg->hwptr = vortex; arg->index = 1; arg->seq_ports = seq_ports[dev]; arg->max_voices = max_synth_voices[dev]; } #endif // (5) if ((err = pci_read_config_word(pci, PCI_DEVICE_ID, &(chip->device))) < 0) { snd_card_free(card); return err; } if ((err = pci_read_config_word(pci, PCI_VENDOR_ID, &(chip->vendor))) < 0) { snd_card_free(card); return err; } chip->rev = pci->revision; #ifdef CHIP_AU8830 if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) { printk(KERN_ALERT "vortex: The revision (%x) of your card has not been seen before.\n", chip->rev); printk(KERN_ALERT "vortex: Please email the results of 'lspci -vv' to [email protected].\n"); snd_card_free(card); err = -ENODEV; return err; } #endif // (6) if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } // (7) pci_set_drvdata(pci, card); dev++; vortex_connect_default(chip, 1); vortex_enable_int(chip); return 0; }
/* * Alsa Constructor - Component probe */ int tm6000_audio_init(struct tm6000_core *dev) { struct snd_card *card; struct snd_tm6000_card *chip; int rc; static int devnr; char component[14]; struct snd_pcm *pcm; if (!dev) return 0; if (devnr >= SNDRV_CARDS) return -ENODEV; if (!enable[devnr]) return -ENOENT; rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card); if (rc < 0) { snd_printk(KERN_ERR "cannot create card instance %d\n", devnr); return rc; } strcpy(card->driver, "tm6000-alsa"); strcpy(card->shortname, "TM5600/60x0"); sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d", dev->udev->bus->busnum, dev->udev->devnum); sprintf(component, "USB%04x:%04x", le16_to_cpu(dev->udev->descriptor.idVendor), le16_to_cpu(dev->udev->descriptor.idProduct)); snd_component_add(card, component); snd_card_set_dev(card, &dev->udev->dev); chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL); if (!chip) { rc = -ENOMEM; goto error; } chip->core = dev; chip->card = card; dev->adev = chip; spin_lock_init(&chip->reg_lock); rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm); if (rc < 0) goto error_chip; pcm->info_flags = 0; pcm->private_data = chip; strcpy(pcm->name, "Trident TM5600/60x0"); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); INIT_WORK(&dev->wq_trigger, audio_trigger); rc = snd_card_register(card); if (rc < 0) goto error_chip; dprintk(1,"Registered audio driver for %s\n", card->longname); return 0; error_chip: kfree(chip); dev->adev = NULL; error: snd_card_free(card); return rc; }
static int __init snd_gusmax_probe(int dev) { static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; int xirq, xdma1, xdma2, err; snd_card_t *card; snd_gus_card_t *gus = NULL; cs4231_t *cs4231; struct snd_gusmax *maxcard; card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_gusmax)); if (card == NULL) return -ENOMEM; card->private_free = snd_gusmax_free; maxcard = (struct snd_gusmax *)card->private_data; maxcard->card = card; maxcard->irq = -1; xirq = irq[dev]; if (xirq == SNDRV_AUTO_IRQ) { if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { snd_card_free(card); snd_printk("unable to find a free IRQ\n"); return -EBUSY; } } xdma1 = dma1[dev]; if (xdma1 == SNDRV_AUTO_DMA) { if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { snd_card_free(card); snd_printk("unable to find a free DMA1\n"); return -EBUSY; } } xdma2 = dma2[dev]; if (xdma2 == SNDRV_AUTO_DMA) { if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) { snd_card_free(card); snd_printk("unable to find a free DMA2\n"); return -EBUSY; } } if ((err = snd_gus_create(card, port[dev], -xirq, xdma1, xdma2, 0, channels[dev], pcm_channels[dev], 0, &gus)) < 0) { snd_card_free(card); return err; } if ((err = snd_gusmax_detect(gus)) < 0) { snd_card_free(card); return err; } maxcard->gus_status_reg = gus->gf1.reg_irqstat; maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; snd_gusmax_init(dev, card, gus); if ((err = snd_gus_initialize(gus)) < 0) { snd_card_free(card); return err; } if (!gus->max_flag) { printk(KERN_ERR "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port); snd_card_free(card); return -ENODEV; } if (request_irq(xirq, snd_gusmax_interrupt, SA_INTERRUPT, "GUS MAX", (void *)maxcard)) { snd_card_free(card); printk(KERN_ERR "gusmax: unable to grab IRQ %d\n", xirq); return -EBUSY; } maxcard->irq = xirq; if ((err = snd_cs4231_create(card, gus->gf1.port + 0x10c, -1, xirq, xdma2 < 0 ? xdma1 : xdma2, xdma1, CS4231_HW_DETECT, CS4231_HWSHARE_IRQ | CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2, &cs4231)) < 0) { snd_card_free(card); return err; } if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0) { snd_card_free(card); return err; } if ((err = snd_cs4231_mixer(cs4231)) < 0) { snd_card_free(card); return err; } if ((err = snd_cs4231_timer(cs4231, 2, NULL)) < 0) { snd_card_free(card); return err; } if (pcm_channels[dev] > 0) { if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) { snd_card_free(card); return err; } } if ((err = snd_gusmax_mixer(cs4231)) < 0) { snd_card_free(card); return err; } if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) { snd_card_free(card); return err; } sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1); if (xdma2 >= 0) sprintf(card->longname + strlen(card->longname), "&%i", xdma2); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } maxcard->gus = gus; maxcard->cs4231 = cs4231; snd_gusmax_cards[dev] = card; return 0; }
static void __devinit setup_card(struct snd_usb_caiaqdev *dev) { int ret; char val[4]; /* device-specific startup specials */ switch (dev->chip.usb_id) { case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): /* RigKontrol2 - display centered dash ('-') */ val[0] = 0x00; val[1] = 0x00; val[2] = 0x01; snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 3); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): /* RigKontrol2 - display two centered dashes ('--') */ val[0] = 0x00; val[1] = 0x40; val[2] = 0x40; val[3] = 0x00; snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 4); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): /* Audio Kontrol 1 - make USB-LED stop blinking */ val[0] = 0x00; snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, val, 1); break; case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): /* Audio 8 DJ - trigger read of current settings */ dev->control_state[0] = 0xff; snd_usb_caiaq_set_auto_msg(dev, 1, 0, 0); snd_usb_caiaq_send_command(dev, EP1_CMD_READ_IO, NULL, 0); if (!wait_event_timeout(dev->ep1_wait_queue, dev->control_state[0] != 0xff, HZ)) return; /* fix up some defaults */ if ((dev->control_state[1] != 2) || (dev->control_state[2] != 3) || (dev->control_state[4] != 2)) { dev->control_state[1] = 2; dev->control_state[2] = 3; dev->control_state[4] = 2; snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO, dev->control_state, 6); } break; } if (dev->spec.num_analog_audio_out + dev->spec.num_analog_audio_in + dev->spec.num_digital_audio_out + dev->spec.num_digital_audio_in > 0) { ret = snd_usb_caiaq_audio_init(dev); if (ret < 0) log("Unable to set up audio system (ret=%d)\n", ret); } if (dev->spec.num_midi_in + dev->spec.num_midi_out > 0) { ret = snd_usb_caiaq_midi_init(dev); if (ret < 0) log("Unable to set up MIDI system (ret=%d)\n", ret); } #ifdef CONFIG_SND_USB_CAIAQ_INPUT ret = snd_usb_caiaq_input_init(dev); if (ret < 0) log("Unable to set up input system (ret=%d)\n", ret); #endif /* finally, register the card and all its sub-instances */ ret = snd_card_register(dev->chip.card); if (ret < 0) { log("snd_card_register() returned %d\n", ret); snd_card_free(dev->chip.card); } ret = snd_usb_caiaq_control_init(dev); if (ret < 0) log("Unable to set up control system (ret=%d)\n", ret); }
static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev) { struct snd_card *card; struct snd_opl3 *opl3; struct snd_cmi8328 *cmi; #ifdef SUPPORT_JOYSTICK struct resource *res; #endif int err, pos; static long mpu_ports[] = { 0x330, 0x300, 0x310, 0x320, 0x332, 0x334, 0x336, -1 }; static u8 mpu_port_bits[] = { 3, 0, 1, 2, 4, 5, 6 }; static int mpu_irqs[] = { 9, 7, 5, 3, -1 }; static u8 mpu_irq_bits[] = { 3, 2, 1, 0 }; static int irqs[] = { 9, 10, 11, 7, -1 }; static u8 irq_bits[] = { 2, 3, 4, 1 }; static int dma1s[] = { 3, 1, 0, -1 }; static u8 dma_bits[] = { 3, 2, 1 }; static int dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, {0, -1} }; u16 port = cmi8328_ports[ndev]; u8 val; /* 0xff is invalid configuration (but settable - hope it isn't set) */ if (snd_cmi8328_cfg_read(port, CFG1) == 0xff) return -ENODEV; /* the SB disable bit must NEVER EVER be cleared or the WSS dies */ snd_cmi8328_cfg_write(port, CFG1, CFG1_SB_DISABLE); if (snd_cmi8328_cfg_read(port, CFG1) != CFG1_SB_DISABLE) return -ENODEV; /* disable everything first */ snd_cmi8328_cfg_write(port, CFG2, 0); /* disable CDROM and MPU401 */ snd_cmi8328_cfg_write(port, CFG3, 0); /* disable CDROM IRQ and DMA */ if (irq[ndev] == SNDRV_AUTO_IRQ) { irq[ndev] = snd_legacy_find_free_irq(irqs); if (irq[ndev] < 0) { snd_printk(KERN_ERR "unable to find a free IRQ\n"); return -EBUSY; } } if (dma1[ndev] == SNDRV_AUTO_DMA) { dma1[ndev] = snd_legacy_find_free_dma(dma1s); if (dma1[ndev] < 0) { snd_printk(KERN_ERR "unable to find a free DMA1\n"); return -EBUSY; } } if (dma2[ndev] == SNDRV_AUTO_DMA) { dma2[ndev] = snd_legacy_find_free_dma(dma2s[dma1[ndev] % 4]); if (dma2[ndev] < 0) { snd_printk(KERN_WARNING "unable to find a free DMA2, full-duplex will not work\n"); dma2[ndev] = -1; } } /* configure WSS IRQ... */ pos = array_find(irqs, irq[ndev]); if (pos < 0) { snd_printk(KERN_ERR "invalid IRQ %d\n", irq[ndev]); return -EINVAL; } val = irq_bits[pos] << 3; /* ...and DMA... */ pos = array_find(dma1s, dma1[ndev]); if (pos < 0) { snd_printk(KERN_ERR "invalid DMA1 %d\n", dma1[ndev]); return -EINVAL; } val |= dma_bits[pos]; /* ...and DMA2 */ if (dma2[ndev] >= 0 && dma1[ndev] != dma2[ndev]) { pos = array_find(dma2s[dma1[ndev]], dma2[ndev]); if (pos < 0) { snd_printk(KERN_ERR "invalid DMA2 %d\n", dma2[ndev]); return -EINVAL; } val |= 0x04; /* enable separate capture DMA */ } outb(val, port); err = snd_card_create(index[ndev], id[ndev], THIS_MODULE, sizeof(struct snd_cmi8328), &card); if (err < 0) return err; cmi = card->private_data; cmi->card = card; cmi->port = port; cmi->wss_cfg = val; snd_card_set_dev(card, pdev); err = snd_wss_create(card, port + 4, -1, irq[ndev], dma1[ndev], dma2[ndev], WSS_HW_DETECT, 0, &cmi->wss); if (err < 0) goto error; err = snd_wss_pcm(cmi->wss, 0, NULL); if (err < 0) goto error; err = snd_wss_mixer(cmi->wss); if (err < 0) goto error; err = snd_cmi8328_mixer(cmi->wss); if (err < 0) goto error; if (snd_wss_timer(cmi->wss, 0, NULL) < 0) snd_printk(KERN_WARNING "error initializing WSS timer\n"); if (mpuport[ndev] == SNDRV_AUTO_PORT) { mpuport[ndev] = snd_legacy_find_free_ioport(mpu_ports, 2); if (mpuport[ndev] < 0) snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); } if (mpuirq[ndev] == SNDRV_AUTO_IRQ) { mpuirq[ndev] = snd_legacy_find_free_irq(mpu_irqs); if (mpuirq[ndev] < 0) snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); } /* enable and configure MPU401 */ if (mpuport[ndev] > 0 && mpuirq[ndev] > 0) { val = CFG2_MPU_ENABLE; pos = array_find_l(mpu_ports, mpuport[ndev]); if (pos < 0) snd_printk(KERN_WARNING "invalid MPU401 port 0x%lx\n", mpuport[ndev]); else { val |= mpu_port_bits[pos] << 5; pos = array_find(mpu_irqs, mpuirq[ndev]); if (pos < 0) snd_printk(KERN_WARNING "invalid MPU401 IRQ %d\n", mpuirq[ndev]); else { val |= mpu_irq_bits[pos] << 3; snd_cmi8328_cfg_write(port, CFG2, val); if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, mpuport[ndev], 0, mpuirq[ndev], NULL) < 0) snd_printk(KERN_ERR "error initializing MPU401\n"); } } } /* OPL3 is hardwired to 0x388 and cannot be disabled */ if (snd_opl3_create(card, 0x388, 0x38a, OPL3_HW_AUTO, 0, &opl3) < 0) snd_printk(KERN_ERR "error initializing OPL3\n"); else if (snd_opl3_hwdep_new(opl3, 0, 1, NULL) < 0) snd_printk(KERN_WARNING "error initializing OPL3 hwdep\n"); strcpy(card->driver, "CMI8328"); strcpy(card->shortname, "C-Media CMI8328"); sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d,%d", card->shortname, cmi->wss->port, irq[ndev], dma1[ndev], (dma2[ndev] >= 0) ? dma2[ndev] : dma1[ndev]); dev_set_drvdata(pdev, card); err = snd_card_register(card); if (err < 0) goto error; #ifdef SUPPORT_JOYSTICK if (!gameport[ndev]) return 0; /* gameport is hardwired to 0x200 */ res = request_region(0x200, 8, "CMI8328 gameport"); if (!res) snd_printk(KERN_WARNING "unable to allocate gameport I/O port\n"); else { struct gameport *gp = cmi->gameport = gameport_allocate_port(); if (!cmi->gameport) release_and_free_resource(res); else { gameport_set_name(gp, "CMI8328 Gameport"); gameport_set_phys(gp, "%s/gameport0", dev_name(pdev)); gameport_set_dev_parent(gp, pdev); gp->io = 0x200; gameport_set_port_data(gp, res); /* Enable gameport */ snd_cmi8328_cfg_write(port, CFG1, CFG1_SB_DISABLE | CFG1_GAMEPORT); gameport_register_port(gp); } } #endif return 0; error: snd_card_free(card); return err; }
/* * Create an ALSA soundcard entry for the SoundScape, using * the given list of port, IRQ and DMA resources. */ static int __devinit create_sscape(const struct params *params, snd_card_t **rcardp) { snd_card_t *card; register struct soundscape *sscape; register unsigned dma_cfg; unsigned irq_cfg; unsigned mpu_irq_cfg; struct resource *io_res; unsigned long flags; int err; /* * Check that the user didn't pass us garbage data ... */ irq_cfg = get_irq_config(params->irq); if (irq_cfg == INVALID_IRQ) { snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->irq); return -ENXIO; } mpu_irq_cfg = get_irq_config(params->mpu_irq); if (mpu_irq_cfg == INVALID_IRQ) { printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->mpu_irq); return -ENXIO; } /* * Grab IO ports that we will need to probe so that we * can detect and control this hardware ... */ if ((io_res = request_region(params->port, 8, "SoundScape")) == NULL) { snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", params->port); return -EBUSY; } /* * Grab both DMA channels (OK, only one for now) ... */ if ((err = request_dma(params->dma1, "SoundScape")) < 0) { snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", params->dma1); goto _release_region; } /* * Create a new ALSA sound card entry, in anticipation * of detecting our hardware ... */ if ((card = snd_card_new(params->index, params->id, THIS_MODULE, sizeof(struct soundscape))) == NULL) { err = -ENOMEM; goto _release_dma; } sscape = get_card_soundscape(card); spin_lock_init(&sscape->lock); spin_lock_init(&sscape->fwlock); sscape->io_res = io_res; sscape->io_base = params->port; if (!detect_sscape(sscape)) { printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); err = -ENODEV; goto _release_card; } printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", sscape->io_base, params->irq, params->dma1); /* * Now create the hardware-specific device so that we can * load the microcode into the on-board processor. * We cannot use the MPU-401 MIDI system until this firmware * has been loaded into the card. */ if ((err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw))) < 0) { printk(KERN_ERR "sscape: Failed to create firmware device\n"); goto _release_card; } strlcpy(sscape->hw->name, "SoundScape M68K", sizeof(sscape->hw->name)); sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0'; sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE; sscape->hw->ops.open = sscape_hw_open; sscape->hw->ops.release = sscape_hw_release; sscape->hw->ops.ioctl = sscape_hw_ioctl; sscape->hw->private_data = sscape; /* * Tell the on-board devices where their resources are (I think - * I can't be sure without a datasheet ... So many magic values!) */ spin_lock_irqsave(&sscape->lock, flags); activate_ad1845_unsafe(sscape->io_base); sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */ sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); /* * Enable and configure the DMA channels ... */ sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); dma_cfg = (sscape->ic_type == IC_ODIE ? 0x70 : 0x40); sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); sscape_write_unsafe(sscape->io_base, GA_CDCFG_REG, 0x09 | DMA_8BIT | (params->dma1 << 4) | (irq_cfg << 1)); spin_unlock_irqrestore(&sscape->lock, flags); /* * We have now enabled the codec chip, and so we should * detect the AD1845 device ... */ if ((err = create_ad1845(card, CODEC_IO(params->port), params->irq, params->dma1)) < 0) { printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n", CODEC_IO(params->port), params->irq); goto _release_card; } #define MIDI_DEVNUM 0 if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(params->port), params->mpu_irq)) < 0) { printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n", MPU401_IO(params->port)); goto _release_card; } /* * Enable the master IRQ ... */ sscape_write(sscape, GA_INTENA_REG, 0x80); if ((err = snd_card_register(card)) < 0) { printk(KERN_ERR "sscape: Failed to register sound card\n"); goto _release_card; } /* * Initialize mixer */ sscape->midi_vol = 0; host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100); host_write_ctrl_unsafe(sscape->io_base, 0, 100); host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100); /* * Now that we have successfully created this sound card, * it is safe to store the pointer. * NOTE: we only register the sound card's "destructor" * function now that our "constructor" has completed. */ card->private_free = soundscape_free; *rcardp = card; return 0; _release_card: snd_card_free(card); _release_dma: free_dma(params->dma1); _release_region: release_resource(io_res); kfree_nocheck(io_res); return err; }
static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, const struct pnp_card_device_id *pid) { static int idx = 0; struct pnp_dev *dev; struct snd_card *card; int ret; /* * Allow this function to fail *quietly* if all the ISA PnP * devices were configured using module parameters instead. */ if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS) return -ENOSPC; /* * We have found a candidate ISA PnP card. Now we * have to check that it has the devices that we * expect it to have. * * We will NOT try and autoconfigure all of the resources * needed and then activate the card as we are assuming that * has already been done at boot-time using /proc/isapnp. * We shall simply try to give each active card the resources * that it wants. This is a sensible strategy for a modular * system where unused modules are unloaded regularly. * * This strategy is utterly useless if we compile the driver * into the kernel, of course. */ // printk(KERN_INFO "sscape: %s\n", card->name); /* * Check that we still have room for another sound card ... */ dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); if (! dev) return -ENODEV; if (!pnp_is_active(dev)) { if (pnp_activate_dev(dev) < 0) { printk(KERN_INFO "sscape: device is inactive\n"); return -EBUSY; } } /* * Read the correct parameters off the ISA PnP bus ... */ port[idx] = pnp_port_start(dev, 0); irq[idx] = pnp_irq(dev, 0); mpu_irq[idx] = pnp_irq(dev, 1); dma[idx] = pnp_dma(dev, 0) & 0x03; ret = create_sscape(idx, &card); if (ret < 0) return ret; snd_card_set_dev(card, &pcard->card->dev); if ((ret = snd_card_register(card)) < 0) { printk(KERN_ERR "sscape: Failed to register sound card\n"); snd_card_free(card); return ret; } pnp_set_card_drvdata(pcard, card); ++idx; return ret; }
static int usX2Y_create_usbmidi(struct snd_card *card) { static struct snd_usb_midi_endpoint_info quirk_data_1 = { .out_ep = 0x06, .in_ep = 0x06, .out_cables = 0x001, .in_cables = 0x001 }; static struct snd_usb_audio_quirk quirk_1 = { .vendor_name = "TASCAM", .product_name = NAME_ALLCAPS, .ifnum = 0, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &quirk_data_1 }; static struct snd_usb_midi_endpoint_info quirk_data_2 = { .out_ep = 0x06, .in_ep = 0x06, .out_cables = 0x003, .in_cables = 0x003 }; static struct snd_usb_audio_quirk quirk_2 = { .vendor_name = "TASCAM", .product_name = "US428", .ifnum = 0, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &quirk_data_2 }; struct usb_device *dev = usX2Y(card)->chip.dev; struct usb_interface *iface = usb_ifnum_to_if(dev, 0); struct snd_usb_audio_quirk *quirk = le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? &quirk_2 : &quirk_1; snd_printdd("usX2Y_create_usbmidi \n"); return snd_usb_create_midi_interface(&usX2Y(card)->chip, iface, quirk); } static int usX2Y_create_alsa_devices(struct snd_card *card) { int err; do { if ((err = usX2Y_create_usbmidi(card)) < 0) { snd_printk(KERN_ERR "usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err); break; } if ((err = usX2Y_audio_create(card)) < 0) break; if ((err = usX2Y_hwdep_pcm_new(card)) < 0) break; if ((err = snd_card_register(card)) < 0) break; } while (0); return err; } static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, struct snd_hwdep_dsp_image *dsp) { struct usX2Ydev *priv = hw->private_data; int lret, err = -EINVAL; snd_printdd( "dsp_load %s\n", dsp->name); if (access_ok(VERIFY_READ, dsp->image, dsp->length)) { struct usb_device* dev = priv->chip.dev; char *buf; buf = memdup_user(dsp->image, dsp->length); if (IS_ERR(buf)) return PTR_ERR(buf); err = usb_set_interface(dev, 0, 1); if (err) snd_printk(KERN_ERR "usb_set_interface error \n"); else err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000); kfree(buf); } if (err) return err; if (dsp->index == 1) { msleep(250); // give the device some time err = usX2Y_AsyncSeq04_init(priv); if (err) { snd_printk(KERN_ERR "usX2Y_AsyncSeq04_init error \n"); return err; } err = usX2Y_In04_init(priv); if (err) { snd_printk(KERN_ERR "usX2Y_In04_init error \n"); return err; } err = usX2Y_create_alsa_devices(hw->card); if (err) { snd_printk(KERN_ERR "usX2Y_create_alsa_devices error %i \n", err); snd_card_free(hw->card); return err; } priv->chip_status |= USX2Y_STAT_CHIP_INIT; snd_printdd("%s: alsa all started\n", hw->name); } return err; } int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) { int err; struct snd_hwdep *hw; if ((err = snd_hwdep_new(card, SND_USX2Y_LOADER_ID, 0, &hw)) < 0) return err; hw->iface = SNDRV_HWDEP_IFACE_USX2Y; hw->private_data = usX2Y(card); hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; hw->ops.mmap = snd_us428ctls_mmap; hw->ops.poll = snd_us428ctls_poll; hw->exclusive = 1; sprintf(hw->name, "/proc/bus/usb/%03d/%03d", device->bus->busnum, device->devnum); return 0; }
static int __devinit snd_ad1889_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { int err; static int devno; struct snd_card *card; struct snd_ad1889 *chip; /* (1) */ if (devno >= SNDRV_CARDS) return -ENODEV; if (!enable[devno]) { devno++; return -ENOENT; } /* (2) */ card = snd_card_new(index[devno], id[devno], THIS_MODULE, 0); /* XXX REVISIT: we can probably allocate chip in this call */ if (card == NULL) return -ENOMEM; strcpy(card->driver, "AD1889"); strcpy(card->shortname, "Analog Devices AD1889"); /* (3) */ err = snd_ad1889_create(card, pci, &chip); if (err < 0) goto free_and_ret; /* (4) */ sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->bar, chip->irq); /* (5) */ /* register AC97 mixer */ err = snd_ad1889_ac97_init(chip, ac97_quirk[devno]); if (err < 0) goto free_and_ret; err = snd_ad1889_pcm_init(chip, 0, NULL); if (err < 0) goto free_and_ret; /* register proc interface */ snd_ad1889_proc_init(chip); /* (6) */ err = snd_card_register(card); if (err < 0) goto free_and_ret; /* (7) */ pci_set_drvdata(pci, card); devno++; return 0; free_and_ret: snd_card_free(card); return err; }
static int snd_card_emu10k1_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; struct snd_card *card; struct snd_emu10k1 *emu; #ifdef ENABLE_SYNTH struct snd_seq_device *wave = NULL; #endif int err; if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { dev++; return -ENOENT; } err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) return err; if (max_buffer_size[dev] < 32) max_buffer_size[dev] = 32; else if (max_buffer_size[dev] > 1024) max_buffer_size[dev] = 1024; if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], (long)max_buffer_size[dev] * 1024 * 1024, enable_ir[dev], subsystem[dev], &emu)) < 0) goto error; card->private_data = emu; emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; if ((err = snd_emu10k1_pcm(emu, 0)) < 0) goto error; if ((err = snd_emu10k1_pcm_mic(emu, 1)) < 0) goto error; if ((err = snd_emu10k1_pcm_efx(emu, 2)) < 0) goto error; /* This stores the periods table. */ if (emu->card_capabilities->ca0151_chip) { /* P16V */ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer)) < 0) goto error; } if ((err = snd_emu10k1_mixer(emu, 0, 3)) < 0) goto error; if ((err = snd_emu10k1_timer(emu, 0)) < 0) goto error; if ((err = snd_emu10k1_pcm_multi(emu, 3)) < 0) goto error; if (emu->card_capabilities->ca0151_chip) { /* P16V */ if ((err = snd_p16v_pcm(emu, 4)) < 0) goto error; } if (emu->audigy) { if ((err = snd_emu10k1_audigy_midi(emu)) < 0) goto error; } else { if ((err = snd_emu10k1_midi(emu)) < 0) goto error; } if ((err = snd_emu10k1_fx8010_new(emu, 0)) < 0) goto error; #ifdef ENABLE_SYNTH if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 || wave == NULL) { dev_warn(emu->card->dev, "can't initialize Emu10k1 wavetable synth\n"); } else { struct snd_emu10k1_synth_arg *arg; arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); strcpy(wave->name, "Emu-10k1 Synth"); arg->hwptr = emu; arg->index = 1; arg->seq_ports = seq_ports[dev]; arg->max_voices = max_synth_voices[dev]; } #endif strlcpy(card->driver, emu->card_capabilities->driver, sizeof(card->driver)); strlcpy(card->shortname, emu->card_capabilities->name, sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", card->shortname, emu->revision, emu->serial, emu->port, emu->irq); if ((err = snd_card_register(card)) < 0) goto error; pci_set_drvdata(pci, card); dev++; return 0; error: snd_card_free(card); return err; }
static int bcd2000_probe(struct usb_interface *interface, const struct usb_device_id *usb_id) { struct snd_card *card; struct bcd2000 *bcd2k; unsigned int card_index; char usb_path[32]; int err; mutex_lock(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) if (!test_bit(card_index, devices_used)) break; if (card_index >= SNDRV_CARDS) { mutex_unlock(&devices_mutex); return -ENOENT; } err = snd_card_new(&interface->dev, index[card_index], id[card_index], THIS_MODULE, sizeof(*bcd2k), &card); if (err < 0) { mutex_unlock(&devices_mutex); return err; } bcd2k = card->private_data; bcd2k->dev = interface_to_usbdev(interface); bcd2k->card = card; bcd2k->card_index = card_index; bcd2k->intf = interface; snd_card_set_dev(card, &interface->dev); strncpy(card->driver, "snd-bcd2000", sizeof(card->driver)); strncpy(card->shortname, "BCD2000", sizeof(card->shortname)); usb_make_path(bcd2k->dev, usb_path, sizeof(usb_path)); snprintf(bcd2k->card->longname, sizeof(bcd2k->card->longname), "Behringer BCD2000 at %s", usb_path); err = bcd2000_init_midi(bcd2k); if (err < 0) goto probe_error; err = snd_card_register(card); if (err < 0) goto probe_error; usb_set_intfdata(interface, bcd2k); set_bit(card_index, devices_used); mutex_unlock(&devices_mutex); return 0; probe_error: dev_info(&bcd2k->dev->dev, PREFIX "error during probing"); bcd2000_free_usb_related_resources(bcd2k, interface); snd_card_free(card); mutex_unlock(&devices_mutex); return err; }
static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) { struct snd_sb *chip; struct snd_card *card; struct snd_sb8 *acard; struct snd_opl3 *opl3; int err; err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_sb8), &card); if (err < 0) return err; acard = card->private_data; card->private_free = snd_sb8_free; /* block the 0x388 port to avoid PnP conflicts */ acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); if (port[dev] != SNDRV_AUTO_PORT) { if ((err = snd_sbdsp_create(card, port[dev], irq[dev], snd_sb8_interrupt, dma8[dev], -1, SB_HW_AUTO, &chip)) < 0) goto _err; } else { /* auto-probe legacy ports */ static unsigned long possible_ports[] = { 0x220, 0x240, 0x260, }; int i; for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { err = snd_sbdsp_create(card, possible_ports[i], irq[dev], snd_sb8_interrupt, dma8[dev], -1, SB_HW_AUTO, &chip); if (err >= 0) { port[dev] = possible_ports[i]; break; } } if (i >= ARRAY_SIZE(possible_ports)) { err = -EINVAL; goto _err; } } acard->chip = chip; if (chip->hardware >= SB_HW_16) { if (chip->hardware == SB_HW_ALS100) snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n", port[dev]); else snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n", port[dev]); err = -ENODEV; goto _err; } if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) goto _err; if ((err = snd_sbmixer_new(chip)) < 0) goto _err; if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) { if ((err = snd_opl3_create(card, chip->port + 8, 0, OPL3_HW_AUTO, 1, &opl3)) < 0) { snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8); } } else { if ((err = snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_AUTO, 1, &opl3)) < 0) { snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n", chip->port, chip->port + 2); } } if (err >= 0) { if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) goto _err; } if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) goto _err; strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8"); strcpy(card->shortname, chip->name); sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", chip->name, chip->port, irq[dev], dma8[dev]); snd_card_set_dev(card, pdev); if ((err = snd_card_register(card)) < 0) goto _err; dev_set_drvdata(pdev, card); return 0; _err: snd_card_free(card); return err; }
static int __init snd_es1688_probe(struct platform_device *pdev) { int dev = pdev->id; static int possible_irqs[] = {5, 9, 10, 7, -1}; static int possible_dmas[] = {1, 3, 0, -1}; int xirq, xdma, xmpu_irq; struct snd_card *card; struct snd_es1688 *chip; struct snd_opl3 *opl3; struct snd_pcm *pcm; int err; card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; xirq = irq[dev]; if (xirq == SNDRV_AUTO_IRQ) { if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); err = -EBUSY; goto _err; } } xmpu_irq = mpu_irq[dev]; xdma = dma8[dev]; if (xdma == SNDRV_AUTO_DMA) { if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) { snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); err = -EBUSY; goto _err; } } if (port[dev] != SNDRV_AUTO_PORT) { if ((err = snd_es1688_create(card, port[dev], mpu_port[dev], xirq, xmpu_irq, xdma, ES1688_HW_AUTO, &chip)) < 0) goto _err; } else { /* auto-probe legacy ports */ static unsigned long possible_ports[] = { 0x220, 0x240, 0x260, }; int i; for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { err = snd_es1688_create(card, possible_ports[i], mpu_port[dev], xirq, xmpu_irq, xdma, ES1688_HW_AUTO, &chip); if (err >= 0) { port[dev] = possible_ports[i]; break; } } if (i >= ARRAY_SIZE(possible_ports)) goto _err; } if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0) goto _err; if ((err = snd_es1688_mixer(chip)) < 0) goto _err; strcpy(card->driver, "ES1688"); strcpy(card->shortname, pcm->name); sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma); if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) { printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->port); } else { if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) goto _err; } if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, chip->mpu_port, 0, xmpu_irq, SA_INTERRUPT, NULL)) < 0) goto _err; } snd_card_set_dev(card, &pdev->dev); if ((err = snd_card_register(card)) < 0) goto _err; platform_set_drvdata(pdev, card); return 0; _err: snd_card_free(card); return err; }
static int mixart_enum_connectors(struct mixart_mgr *mgr) { u32 k; int err; struct mixart_msg request; struct mixart_enum_connector_resp *connector; struct mixart_audio_info_req *audio_info_req; struct mixart_audio_info_resp *audio_info; connector = kmalloc(sizeof(*connector), GFP_KERNEL); audio_info_req = kmalloc(sizeof(*audio_info_req), GFP_KERNEL); audio_info = kmalloc(sizeof(*audio_info), GFP_KERNEL); if (! connector || ! audio_info_req || ! audio_info) { err = -ENOMEM; goto __error; } audio_info_req->line_max_level = MIXART_FLOAT_P_22_0_TO_HEX; audio_info_req->micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX; audio_info_req->cd_max_level = MIXART_FLOAT____0_0_TO_HEX; request.message_id = MSG_SYSTEM_ENUM_PLAY_CONNECTOR; request.uid = (struct mixart_uid){0,0}; /* board num = 0 */ request.data = NULL; request.size = 0; err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n"); err = -EINVAL; goto __error; } for(k=0; k < connector->uid_count; k++) { struct mixart_pipe *pipe; if(k < MIXART_FIRST_DIG_AUDIO_ID) { pipe = &mgr->chip[k/2]->pipe_out_ana; } else { pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_out_dig; } if(k & 1) { pipe->uid_right_connector = connector->uid[k]; /* odd */ } else { pipe->uid_left_connector = connector->uid[k]; /* even */ } /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; request.uid = connector->uid[k]; request.data = audio_info_req; request.size = sizeof(*audio_info_req); err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); if( err < 0 ) { snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); goto __error; } /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ } request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR; request.uid = (struct mixart_uid){0,0}; /* board num = 0 */ request.data = NULL; request.size = 0; err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector); if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) { snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n"); err = -EINVAL; goto __error; } for(k=0; k < connector->uid_count; k++) { struct mixart_pipe *pipe; if(k < MIXART_FIRST_DIG_AUDIO_ID) { pipe = &mgr->chip[k/2]->pipe_in_ana; } else { pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_in_dig; } if(k & 1) { pipe->uid_right_connector = connector->uid[k]; /* odd */ } else { pipe->uid_left_connector = connector->uid[k]; /* even */ } /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */ /* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */ request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO; request.uid = connector->uid[k]; request.data = audio_info_req; request.size = sizeof(*audio_info_req); err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info); if( err < 0 ) { snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n"); goto __error; } /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/ } err = 0; __error: kfree(connector); kfree(audio_info_req); kfree(audio_info); return err; } static int mixart_enum_physio(struct mixart_mgr *mgr) { u32 k; int err; struct mixart_msg request; struct mixart_uid get_console_mgr; struct mixart_return_uid console_mgr; struct mixart_uid_enumeration phys_io; /* get the uid for the console manager */ get_console_mgr.object_id = 0; get_console_mgr.desc = MSG_CONSOLE_MANAGER | 0; /* cardindex = 0 */ request.message_id = MSG_CONSOLE_GET_CLOCK_UID; request.uid = get_console_mgr; request.data = &get_console_mgr; request.size = sizeof(get_console_mgr); err = snd_mixart_send_msg(mgr, &request, sizeof(console_mgr), &console_mgr); if( (err < 0) || (console_mgr.error_code != 0) ) { snd_printk(KERN_DEBUG "error MSG_CONSOLE_GET_CLOCK_UID : err=%x\n", console_mgr.error_code); return -EINVAL; } /* used later for clock issues ! */ mgr->uid_console_manager = console_mgr.uid; request.message_id = MSG_SYSTEM_ENUM_PHYSICAL_IO; request.uid = (struct mixart_uid){0,0}; request.data = &console_mgr.uid; request.size = sizeof(console_mgr.uid); err = snd_mixart_send_msg(mgr, &request, sizeof(phys_io), &phys_io); if( (err < 0) || ( phys_io.error_code != 0 ) ) { snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PHYSICAL_IO err(%x) error_code(%x)\n", err, phys_io.error_code ); return -EINVAL; } /* min 2 phys io per card (analog in + analog out) */ if (phys_io.nb_uid < MIXART_MAX_CARDS * 2) return -EINVAL; for(k=0; k<mgr->num_cards; k++) { mgr->chip[k]->uid_in_analog_physio = phys_io.uid[k]; mgr->chip[k]->uid_out_analog_physio = phys_io.uid[phys_io.nb_uid/2 + k]; } return 0; } static int mixart_first_init(struct mixart_mgr *mgr) { u32 k; int err; struct mixart_msg request; if((err = mixart_enum_connectors(mgr)) < 0) return err; if((err = mixart_enum_physio(mgr)) < 0) return err; /* send a synchro command to card (necessary to do this before first MSG_STREAM_START_STREAM_GRP_PACKET) */ /* though why not here */ request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD; request.uid = (struct mixart_uid){0,0}; request.data = NULL; request.size = 0; /* this command has no data. response is a 32 bit status */ err = snd_mixart_send_msg(mgr, &request, sizeof(k), &k); if( (err < 0) || (k != 0) ) { snd_printk(KERN_ERR "error MSG_SYSTEM_SEND_SYNCHRO_CMD\n"); return err == 0 ? -EINVAL : err; } return 0; } /* firmware base addresses (when hard coded) */ #define MIXART_MOTHERBOARD_XLX_BASE_ADDRESS 0x00600000 static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmware *dsp) { int err, card_index; u32 status_xilinx, status_elf, status_daught; u32 val; /* read motherboard xilinx status */ status_xilinx = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); /* read elf status */ status_elf = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); /* read daughterboard xilinx status */ status_daught = readl_be( MIXART_MEM( mgr,MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); /* motherboard xilinx status 5 will say that the board is performing a reset */ if (status_xilinx == 5) { snd_printk(KERN_ERR "miXart is resetting !\n"); return -EAGAIN; /* try again later */ } switch (index) { case MIXART_MOTHERBOARD_XLX_INDEX: /* xilinx already loaded ? */ if (status_xilinx == 4) { snd_printk(KERN_DEBUG "xilinx is already loaded !\n"); return 0; } /* the status should be 0 == "idle" */ if (status_xilinx != 0) { snd_printk(KERN_ERR "xilinx load error ! status = %d\n", status_xilinx); return -EIO; /* modprob -r may help ? */ } /* check xilinx validity */ if (((u32*)(dsp->data))[0] == 0xffffffff) return -EINVAL; if (dsp->size % 4) return -EINVAL; /* set xilinx status to copying */ writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); /* setup xilinx base address */ writel_be( MIXART_MOTHERBOARD_XLX_BASE_ADDRESS, MIXART_MEM( mgr,MIXART_PSEUDOREG_MXLX_BASE_ADDR_OFFSET )); /* setup code size for xilinx file */ writel_be( dsp->size, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_SIZE_OFFSET )); /* copy xilinx code */ memcpy_toio( MIXART_MEM( mgr, MIXART_MOTHERBOARD_XLX_BASE_ADDRESS), dsp->data, dsp->size); /* set xilinx status to copy finished */ writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET )); /* return, because no further processing needed */ return 0; case MIXART_MOTHERBOARD_ELF_INDEX: if (status_elf == 4) { snd_printk(KERN_DEBUG "elf file already loaded !\n"); return 0; } /* the status should be 0 == "idle" */ if (status_elf != 0) { snd_printk(KERN_ERR "elf load error ! status = %d\n", status_elf); return -EIO; /* modprob -r may help ? */ } /* wait for xilinx status == 4 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_MXLX_STATUS_OFFSET, 1, 4, 500); /* 5sec */ if (err < 0) { snd_printk(KERN_ERR "xilinx was not loaded or " "could not be started\n"); return err; } /* init some data on the card */ writel_be( 0, MIXART_MEM( mgr, MIXART_PSEUDOREG_BOARDNUMBER ) ); /* set miXart boardnumber to 0 */ writel_be( 0, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) ); /* reset pointer to flow table on miXart */ /* set elf status to copying */ writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); /* process the copying of the elf packets */ err = mixart_load_elf( mgr, dsp ); if (err < 0) return err; /* set elf status to copy finished */ writel_be( 2, MIXART_MEM( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET )); /* wait for elf status == 4 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_ELF_STATUS_OFFSET, 1, 4, 300); /* 3sec */ if (err < 0) { snd_printk(KERN_ERR "elf could not be started\n"); return err; } /* miXart waits at this point on the pointer to the flow table */ writel_be( (u32)mgr->flowinfo.addr, MIXART_MEM( mgr, MIXART_FLOWTABLE_PTR ) ); /* give pointer of flow table to miXart */ return 0; /* return, another xilinx file has to be loaded before */ case MIXART_AESEBUBOARD_XLX_INDEX: default: /* elf and xilinx should be loaded */ if (status_elf != 4 || status_xilinx != 4) { printk(KERN_ERR "xilinx or elf not " "successfully loaded\n"); return -EIO; /* modprob -r may help ? */ } /* wait for daughter detection != 0 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DBRD_PRESENCE_OFFSET, 0, 0, 30); /* 300msec */ if (err < 0) { snd_printk(KERN_ERR "error starting elf file\n"); return err; } /* the board type can now be retrieved */ mgr->board_type = (DAUGHTER_TYPE_MASK & readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DBRD_TYPE_OFFSET))); if (mgr->board_type == MIXART_DAUGHTER_TYPE_NONE) break; /* no daughter board; the file does not have to be loaded, continue after the switch */ /* only if aesebu daughter board presence (elf code must run) */ if (mgr->board_type != MIXART_DAUGHTER_TYPE_AES ) return -EINVAL; /* daughter should be idle */ if (status_daught != 0) { printk(KERN_ERR "daughter load error ! status = %d\n", status_daught); return -EIO; /* modprob -r may help ? */ } /* check daughterboard xilinx validity */ if (((u32*)(dsp->data))[0] == 0xffffffff) return -EINVAL; if (dsp->size % 4) return -EINVAL; /* inform mixart about the size of the file */ writel_be( dsp->size, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_SIZE_OFFSET )); /* set daughterboard status to 1 */ writel_be( 1, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); /* wait for status == 2 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 2, 30); /* 300msec */ if (err < 0) { snd_printk(KERN_ERR "daughter board load error\n"); return err; } /* get the address where to write the file */ val = readl_be( MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_BASE_ADDR_OFFSET )); if (!val) return -EINVAL; /* copy daughterboard xilinx code */ memcpy_toio( MIXART_MEM( mgr, val), dsp->data, dsp->size); /* set daughterboard status to 4 */ writel_be( 4, MIXART_MEM( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET )); /* continue with init */ break; } /* end of switch file index*/ /* wait for daughter status == 3 */ err = mixart_wait_nice_for_register_value( mgr, MIXART_PSEUDOREG_DXLX_STATUS_OFFSET, 1, 3, 300); /* 3sec */ if (err < 0) { snd_printk(KERN_ERR "daughter board could not be initialised\n"); return err; } /* init mailbox (communication with embedded) */ snd_mixart_init_mailbox(mgr); /* first communication with embedded */ err = mixart_first_init(mgr); if (err < 0) { snd_printk(KERN_ERR "miXart could not be set up\n"); return err; } /* create devices and mixer in accordance with HW options*/ for (card_index = 0; card_index < mgr->num_cards; card_index++) { struct snd_mixart *chip = mgr->chip[card_index]; if ((err = snd_mixart_create_pcm(chip)) < 0) return err; if (card_index == 0) { if ((err = snd_mixart_create_mixer(chip->mgr)) < 0) return err; } if ((err = snd_card_register(chip->card)) < 0) return err; }; snd_printdd("miXart firmware downloaded and successfully set up\n"); return 0; } #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) #if !defined(CONFIG_USE_MIXARTLOADER) && !defined(CONFIG_SND_MIXART) /* built-in kernel */ #define SND_MIXART_FW_LOADER /* use the standard firmware loader */ #endif #endif #ifdef SND_MIXART_FW_LOADER int snd_mixart_setup_firmware(struct mixart_mgr *mgr) { static char *fw_files[3] = { "miXart8.xlx", "miXart8.elf", "miXart8AES.xlx" }; char path[32]; const struct firmware *fw_entry; int i, err; for (i = 0; i < 3; i++) { sprintf(path, "mixart/%s", fw_files[i]); if (request_firmware(&fw_entry, path, &mgr->pci->dev)) return -ENOENT; /* fake hwdep dsp record */ err = mixart_dsp_load(mgr, i, fw_entry); release_firmware(fw_entry); if (err < 0) return err; mgr->dsp_loaded |= 1 << i; } return 0; } MODULE_FIRMWARE("mixart/miXart8.xlx"); MODULE_FIRMWARE("mixart/miXart8.elf"); MODULE_FIRMWARE("mixart/miXart8AES.xlx"); #else /* old style firmware loading */ /* miXart hwdep interface id string */ #define SND_MIXART_HWDEP_ID "miXart Loader" static int mixart_hwdep_dsp_status(struct snd_hwdep *hw, struct snd_hwdep_dsp_status *info) { struct mixart_mgr *mgr = hw->private_data; strcpy(info->id, "miXart"); info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX; if (mgr->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX)) info->chip_ready = 1; info->version = MIXART_DRIVER_VERSION; return 0; } static int mixart_hwdep_dsp_load(struct snd_hwdep *hw, struct snd_hwdep_dsp_image *dsp) { struct mixart_mgr* mgr = hw->private_data; struct firmware fw; int err; fw.size = dsp->length; fw.data = vmalloc(dsp->length); if (! fw.data) { snd_printk(KERN_ERR "miXart: cannot allocate image size %d\n", (int)dsp->length); return -ENOMEM; } if (copy_from_user((void *) fw.data, dsp->image, dsp->length)) { vfree(fw.data); return -EFAULT; } err = mixart_dsp_load(mgr, dsp->index, &fw); vfree(fw.data); if (err < 0) return err; mgr->dsp_loaded |= 1 << dsp->index; return err; } int snd_mixart_setup_firmware(struct mixart_mgr *mgr) { int err; struct snd_hwdep *hw; /* only create hwdep interface for first cardX (see "index" module parameter)*/ if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0) return err; hw->iface = SNDRV_HWDEP_IFACE_MIXART; hw->private_data = mgr; hw->ops.dsp_status = mixart_hwdep_dsp_status; hw->ops.dsp_load = mixart_hwdep_dsp_load; hw->exclusive = 1; sprintf(hw->name, SND_MIXART_HWDEP_ID); mgr->dsp_loaded = 0; return snd_card_register(mgr->chip[0]->card); }
/* * Ubicom audio driver probe() method. Args change depending on whether we use * platform_device or i2c_device. */ static int snd_ubi32_generic_probe(struct platform_device *dev) { struct snd_card *card; struct ubi32_snd_priv *ubi32_priv; int err; struct ubi32_generic_platform_data *pdata; /* * dev is audio device */ if (!dev) { snd_printk(KERN_WARNING "generic platform_data null!\n"); return -ENODEV; } /* * setup mclk if pdata exists */ pdata = audio_device_priv(dev); if (pdata) { if (snd_ubi32_generic_setup_mclk(pdata)) { snd_printk(KERN_WARNING "can not setup mclk!\n"); return -EINVAL; } } /* * Create a snd_card structure */ card = snd_card_new(index, "Ubi32-Generic", THIS_MODULE, sizeof(struct ubi32_snd_priv)); if (card == NULL) { return -ENOMEM; } card->private_free = snd_ubi32_generic_free; /* Not sure if correct */ ubi32_priv = card->private_data; /* * Initialize the snd_card's private data structure */ ubi32_priv->card = card; /* * Create the new PCM instance */ err = snd_ubi32_pcm_probe(ubi32_priv, dev); if (err < 0) { snd_card_free(card); return err; } strcpy(card->driver, "Ubi32-Generic"); strcpy(card->shortname, "Ubi32-Generic"); snprintf(card->longname, sizeof(card->longname), "%s at sendirq=%d.%d recvirq=%d.%d regs=%p", card->shortname, ubi32_priv->tx_irq, ubi32_priv->irq_idx, ubi32_priv->rx_irq, ubi32_priv->irq_idx, ubi32_priv->adr); snd_card_set_dev(card, &dev->dev); /* * Register the sound card */ if ((err = snd_card_register(card)) != 0) { snd_printk(KERN_INFO "snd_card_register error\n"); } /* * Store card for access from other methods */ platform_set_drvdata(dev, card); return 0; }
static int __devinit snd_nm256_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { struct snd_card *card; struct nm256 *chip; int err; const struct snd_pci_quirk *q; q = snd_pci_quirk_lookup(pci, nm256_quirks); if (q) { snd_printdd(KERN_INFO "nm256: Enabled quirk for %s.\n", q->name); switch (q->value) { case NM_BLACKLISTED: printk(KERN_INFO "nm256: The device is blacklisted. " "Loading stopped\n"); return -ENODEV; case NM_RESET_WORKAROUND_2: reset_workaround_2 = 1; /* Fall-through */ case NM_RESET_WORKAROUND: reset_workaround = 1; break; } } err = snd_card_create(index, id, THIS_MODULE, 0, &card); if (err < 0) return err; switch (pci->device) { case PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO: strcpy(card->driver, "NM256AV"); break; case PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO: strcpy(card->driver, "NM256ZX"); break; case PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO: strcpy(card->driver, "NM256XL+"); break; default: snd_printk(KERN_ERR "invalid device id 0x%x\n", pci->device); snd_card_free(card); return -EINVAL; } if (vaio_hack) buffer_top = 0x25a800; /* this avoids conflicts with XFree86 server */ if (playback_bufsize < 4) playback_bufsize = 4; if (playback_bufsize > 128) playback_bufsize = 128; if (capture_bufsize < 4) capture_bufsize = 4; if (capture_bufsize > 128) capture_bufsize = 128; if ((err = snd_nm256_create(card, pci, &chip)) < 0) { snd_card_free(card); return err; } card->private_data = chip; if (reset_workaround) { snd_printdd(KERN_INFO "nm256: reset_workaround activated\n"); chip->reset_workaround = 1; } if (reset_workaround_2) { snd_printdd(KERN_INFO "nm256: reset_workaround_2 activated\n"); chip->reset_workaround_2 = 1; } if ((err = snd_nm256_pcm(chip, 0)) < 0 || (err = snd_nm256_mixer(chip)) < 0) { snd_card_free(card); return err; } sprintf(card->shortname, "NeoMagic %s", card->driver); sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d", card->shortname, chip->buffer_addr, chip->cport_addr, chip->irq); if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } pci_set_drvdata(pci, card); return 0; }