static int __devinit snd_card_saudio_pcm(struct snd_saudio *saudio, int device, int substreams) { struct snd_pcm *pcm; int err; ADEBUG(); err = snd_pcm_new(saudio->card, "SAUDIO PCM", device, substreams, substreams, &pcm); if (err < 0) return err; pcm->private_data = saudio; saudio->pcm[device] = pcm; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_saudio_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saudio_capture_ops); pcm->private_data = saudio; pcm->info_flags = 0; strcpy(pcm->name, "SAUDIO PCM"); pcm->private_free = saudio_pcm_lib_preallocate_free_for_all; saudio_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); return 0; }
/* * SSP Platform functions */ static int ssp_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime) { int retval = 0; struct snd_soc_dai *dai; struct snd_pcm *pcm; pr_debug("SSP DAI: FCT %s enters\n", __func__); /* * Do pre-allocation to all substreams of the given pcm for the * specified DMA type. * */ dai = soc_runtime->cpu_dai; pcm = soc_runtime->pcm; if (dai->driver->playback.channels_min || dai->driver->capture.channels_min) { retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), SSP_MIN_BUFFER, SSP_MAX_BUFFER); if (retval) { pr_err("DMA buffer allocation fail\n"); return retval; } } return retval; } /* ssp_platform_pcm_new */
int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip) { struct snd_pcm *pcm; int err; audio_info(" .. IN\n"); if (mutex_lock_interruptible(&chip->audio_mutex)) { audio_error("Interrupted whilst waiting for lock\n"); return -EINTR; } err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm); if (err < 0) goto out; pcm->private_data = chip; strcpy(pcm->name, "bcm2835 IEC958/HDMI"); chip->pcm_spdif = pcm; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_bcm2835_playback_spdif_ops); /* pre-allocation of buffers */ /* NOTE: this may fail */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max); out: mutex_unlock(&chip->audio_mutex); audio_info(" .. OUT\n"); return 0; }
/* create a pcm device */ int __devinit snd_bcm2835_new_pcm(bcm2835_chip_t * chip) { struct snd_pcm *pcm; int err; audio_info(" .. IN\n"); err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm); if (err < 0) return err; pcm->private_data = chip; strcpy(pcm->name, "bcm2835 ALSA"); chip->pcm = pcm; chip->dest = AUDIO_DEST_AUTO; chip->volume = 100; /* set operators */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_bcm2835_playback_ops); /* pre-allocation of buffers */ /* NOTE: this may fail */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), 64 * 1024, 64 * 1024); audio_info(" .. OUT\n"); return 0; }
static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int substreams) { struct snd_pcm *pcm; struct snd_pcm_ops *ops; int err; err = snd_pcm_new(dummy->card, "Dummy PCM", device, substreams, substreams, &pcm); if (err < 0) return err; dummy->pcm = pcm; if (fake_buffer) ops = &dummy_pcm_ops_no_buf; else ops = &dummy_pcm_ops; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, ops); pcm->private_data = dummy; pcm->info_flags = 0; strcpy(pcm->name, "Dummy PCM"); if (!fake_buffer) { snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 0, 64*1024); } return 0; }
/* TO DO: set up to handle more than one pcm instance */ static int __init snd_aicapcmchip(struct snd_card_aica *dreamcastcard, int pcm_index) { struct snd_pcm *pcm; int err; /* AICA has no capture ability */ err = snd_pcm_new(dreamcastcard->card, "AICA PCM", pcm_index, 1, 0, &pcm); if (unlikely(err < 0)) return err; pcm->private_data = dreamcastcard; strcpy(pcm->name, "AICA PCM"); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_aicapcm_playback_ops); /* Allocate the DMA buffers */ err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), AICA_BUFFER_SIZE, AICA_BUFFER_SIZE); return err; }
static int __devinit snd_card_capture_allocate(pcm_hw_t *snd_card, int device,char* name) { int err; snd_pcm_t *pcm; err = snd_pcm_new(snd_card->card,name,device, 0, 1, &pcm); if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_capture_ops_pcm); pcm->private_data = snd_card; pcm->private_free = snd_card_pcm_free; pcm->info_flags = 0; snd_card->pcm = pcm; strcpy(pcm->name, name); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), PCM_PREALLOC_SIZE, PCM_PREALLOC_MAX); return 0; }
/* create a PCM device */ static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm) { struct snd_pcm *pcm; int err; err = snd_pcm_new(line6pcm->line6->card, (char *)line6pcm->line6->properties->name, 0, 1, 1, &pcm); if (err < 0) return err; pcm->private_data = line6pcm; pcm->private_free = line6_cleanup_pcm; line6pcm->pcm = pcm; strcpy(pcm->name, line6pcm->line6->properties->name); /* set operators */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_line6_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops); /* pre-allocation of buffers */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), 64 * 1024, 128 * 1024); return 0; }
static int dw_pcm_new(struct snd_soc_pcm_runtime *rtd) { size_t size = dw_pcm_hardware.buffer_bytes_max; return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), size, size); }
/* * intel_alsa_create_pcm_device : to setup pcm for the card * * Input parameters * @card : pointer to the sound card structure * @p_alsa_ssp_snd_card : pointer to internal context * * Output parameters * @ret_val : status, 0 ==> OK * */ static int intel_alsa_create_pcm_device(struct snd_card *card, struct intel_alsa_ssp_card_info *p_alsa_ssp_snd_card) { struct snd_pcm *pl_pcm; int i, ret_val = 0; WARN(!card, "ALSA_SSP: ERROR NULL card\n"); if (!card) return -EINVAL; WARN(!p_alsa_ssp_snd_card, "ALSA_SSP: ERROR NULL p_alsa_ssp_snd_card\n"); if (!p_alsa_ssp_snd_card) return -EINVAL; /* * The alsa_ssp driver handles provide 2 PCM devices : * device 0 ==> BT with 1 capture sub-stream + 1 play sub-stream * device 1 ==> FM with 1 capture sub-stream + 0 play sub-stream * These 2 devices are exclusive */ for (i = 0; i < INTEL_ALSA_SSP_SND_CARD_MAX_DEVICES; i++) { ret_val = snd_pcm_new(card, s_dev_info[i].dev_name, i, s_dev_info[i].nb_play_stream, s_dev_info[i].nb_capt_stream, &pl_pcm); if (ret_val) return ret_val; /* setup the ops for playback and capture streams */ snd_pcm_set_ops(pl_pcm, SNDRV_PCM_STREAM_PLAYBACK, &s_alsa_ssp_playback_ops); snd_pcm_set_ops(pl_pcm, SNDRV_PCM_STREAM_CAPTURE, &s_alsa_ssp_capture_ops); /* setup private data which can be retrieved when required */ pl_pcm->private_data = p_alsa_ssp_snd_card; pl_pcm->info_flags = 0; strncpy(pl_pcm->name, card->shortname, strlen(card->shortname)); /* * allocate DMA pages for ALSA stream operations pre-allocation * to all substreams of the given pcm for the specified DMA type */ snd_pcm_lib_preallocate_pages_for_all(pl_pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), s_dev_info[i].stream_hw_param->buffer_bytes_max, s_dev_info[i].stream_hw_param->buffer_bytes_max); } return ret_val; }
static int __init vaudio_snd_card_pcm (NkVaudio vaudio, int device) { struct snd_pcm* pcm; int err; ADEBUG(); if ((err = snd_pcm_new(vaudio->card, "VAUDIO PCM", device, 1, 1, &pcm)) < 0) return err; pcm->private_data = vaudio; /* Set up initial buffer with continuous allocation */ #ifdef VAUDIO_CONFIG_NK_PMEM pcm->private_free = vaudio_pcm_lib_preallocate_free_for_all; vaudio_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), NK_VAUDIO_MAX_RING_SIZE, NK_VAUDIO_MAX_RING_SIZE); #else snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), NK_VAUDIO_MAX_RING_SIZE, NK_VAUDIO_MAX_RING_SIZE); #endif snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vaudio_snd_card_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vaudio_snd_card_capture_ops); pcm->info_flags = 0; snprintf (pcm->name, sizeof pcm->name, "virtual audio pcm"); vaudio->pcm[device] = pcm; return 0; }
int usbtv_audio_init(struct usbtv *usbtv) { int rv; struct snd_card *card; struct snd_pcm *pcm; INIT_WORK(&usbtv->snd_trigger, snd_usbtv_trigger); atomic_set(&usbtv->snd_stream, 0); rv = snd_card_new(&usbtv->udev->dev, SNDRV_DEFAULT_IDX1, "usbtv", THIS_MODULE, 0, &card); if (rv < 0) return rv; strlcpy(card->driver, usbtv->dev->driver->name, sizeof(card->driver)); strlcpy(card->shortname, "usbtv", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "USBTV Audio at bus %d device %d", usbtv->udev->bus->busnum, usbtv->udev->devnum); snd_card_set_dev(card, usbtv->dev); usbtv->snd = card; rv = snd_pcm_new(card, "USBTV Audio", 0, 0, 1, &pcm); if (rv < 0) goto err; strlcpy(pcm->name, "USBTV Audio Input", sizeof(pcm->name)); pcm->info_flags = 0; pcm->private_data = usbtv; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usbtv_pcm_ops); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), USBTV_AUDIO_BUFFER, USBTV_AUDIO_BUFFER); rv = snd_card_register(card); if (rv) goto err; return 0; err: usbtv->snd = NULL; snd_card_free(card); return rv; }
/** * snd_intelmad_pcm_new - to setup pcm for the card * * @card: pointer to the sound card structure * @intelmaddata: pointer to internal context * @pb: playback count for this card * @cap: capture count for this card * @index: device index * * This function is called from probe function to set up pcm params * and functions */ static int __devinit snd_intelmad_pcm_new(struct snd_card *card, struct snd_intelmad *intelmaddata, unsigned int pb, unsigned int cap, unsigned int index) { int ret_val = 0; struct snd_pcm *pcm; char name[32] = INTEL_MAD; struct snd_pcm_ops *pb_ops = NULL, *cap_ops = NULL; pr_debug("called for pb %d, cp %d, idx %d\n", pb, cap, index); ret_val = snd_pcm_new(card, name, index, pb, cap, &pcm); if (ret_val) return ret_val; /* setup the ops for playback and capture streams */ switch (index) { case 0: pb_ops = &snd_intelmad_headset_ops; cap_ops = &snd_intelmad_capture_ops; break; case 1: pb_ops = &snd_intelmad_ihf_ops; cap_ops = &snd_intelmad_capture_ops; break; case 2: pb_ops = &snd_intelmad_vibra_ops; cap_ops = &snd_intelmad_capture_ops; break; case 3: pb_ops = &snd_intelmad_haptic_ops; cap_ops = &snd_intelmad_capture_ops; break; } if (pb) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, pb_ops); if (cap) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, cap_ops); /* setup private data which can be retrieved when required */ pcm->private_data = intelmaddata; pcm->private_free = snd_intelmad_page_free; pcm->info_flags = 0; strncpy(pcm->name, card->shortname, strlen(card->shortname)); /* allocate dma pages for ALSA stream operations */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), MIN_BUFFER, MAX_BUFFER); return ret_val; }
static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int substreams) { struct snd_pcm *pcm; int err; err = snd_pcm_new(dummy->card, "Dummy PCM", device, substreams, substreams, &pcm); if (err < 0) return err; dummy->pcm = pcm; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops); pcm->private_data = dummy; pcm->info_flags = 0; strcpy(pcm->name, "Dummy PCM"); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 128 * 1024, 1024 * 1024); return 0; }
static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai = rtd->cpu_dai; struct snd_pcm *pcm = rtd->pcm; int retval = 0; if (dai->driver->playback.channels_min || dai->driver->capture.channels_min) { retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_DMA), SST_MIN_BUFFER, SST_MAX_BUFFER); if (retval) { dev_err(rtd->dev, "dma buffer allocationf fail\n"); return retval; } } return retval; }
static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_pcm *pcm = rtd->pcm; int retval = 0; pr_debug("sst_pcm_new called\n"); if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream || pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), SST_MIN_BUFFER, SST_MAX_BUFFER); if (retval) { pr_err("dma buffer allocationf fail\n"); return retval; } } return retval; }
int sst_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { int retval = 0; pr_debug("sst_pcm_new called\n"); if (dai->driver->playback.channels_min || dai->driver->capture.channels_min) { retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), SST_MIN_BUFFER, SST_MAX_BUFFER); if (retval) { pr_err("dma buffer allocationf fail\n"); return retval; } } return retval; }
static int __init snd_card_lf1000_pcm(struct snd_lf1000 *lf1000, int device, int substreams) { struct snd_pcm *pcm; int err; printk(KERN_INFO "audio: _init _pcm\n"); /*XXX*/ if ((err = snd_pcm_new(lf1000->card, "LF1000 PCM", device, substreams, substreams, &pcm)) < 0) return err; lf1000->pcm = pcm; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_lf1000_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_lf1000_capture_ops); pcm->private_data = lf1000; pcm->info_flags = 0; strcpy(pcm->name, "LF1000 PCM"); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 0, 64*1024); return 0; }
static int __devinit snd_sh_dac_pcm(struct snd_sh_dac *chip, int device) { int err; struct snd_pcm *pcm; err = snd_pcm_new(chip->card, "SH_DAC PCM", device, 1, 0, &pcm); if (err < 0) return err; pcm->private_data = chip; strcpy(pcm->name, "SH_DAC PCM"); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 48 * 1024, 48 * 1024); return 0; }
/* create a pcm device */ int snd_bcm2835_new_pcm(struct bcm2835_chip *chip) { struct snd_pcm *pcm; int err; audio_info(" .. IN\n"); mutex_init(&chip->audio_mutex); if (mutex_lock_interruptible(&chip->audio_mutex)) { audio_error("Interrupted whilst waiting for lock\n"); return -EINTR; } err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm); if (err < 0) goto out; pcm->private_data = chip; strcpy(pcm->name, "bcm2835 ALSA"); chip->pcm = pcm; chip->dest = AUDIO_DEST_AUTO; chip->volume = alsa2chip(0); chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */ /* set operators */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_bcm2835_playback_ops); /* pre-allocation of buffers */ /* NOTE: this may fail */ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), snd_bcm2835_playback_hw.buffer_bytes_max, snd_bcm2835_playback_hw.buffer_bytes_max); out: mutex_unlock(&chip->audio_mutex); audio_info(" .. OUT\n"); return 0; }
int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip) { int err; err = snd_pcm_new(chip->card, "pcspeaker", 0, 1, 0, &chip->pcm); if (err < 0) return err; snd_pcm_set_ops(chip->pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_pcsp_playback_ops); chip->pcm->private_data = chip; chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; strcpy(chip->pcm->name, "pcsp"); snd_pcm_lib_preallocate_pages_for_all(chip->pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data (GFP_KERNEL), PCSP_BUFFER_SIZE, PCSP_BUFFER_SIZE); return 0; }
static int __devinit loopback_pcm_new(struct loopback *loopback, int device, int substreams) { struct snd_pcm *pcm; int err; err = snd_pcm_new(loopback->card, "Loopback PCM", device, substreams, substreams, &pcm); if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops); pcm->private_data = loopback; pcm->info_flags = 0; strcpy(pcm->name, "Loopback PCM"); loopback->pcm[device] = pcm; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), 0, 2 * 1024 * 1024); return 0; }
/* * * Probe/remove functions * */ static int __devinit minivosc_probe(struct platform_device *devptr) { struct snd_card *card; struct minivosc_device *mydev; int ret; int nr_subdevs; // how many capture substreams we want struct snd_pcm *pcm; int dev = devptr->id; // from aloop-kernel.c dbg("%s: probe", __func__); // no need to kzalloc minivosc_device separately, if the sizeof is included here ret = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(struct minivosc_device), &card); if (ret < 0) goto __nodev; mydev = card->private_data; mydev->card = card; // MUST have mutex_init here - else crash on mutex_lock!! mutex_init(&mydev->cable_lock); dbg2("-- mydev %p", mydev); sprintf(card->driver, "my_driver-%s", SND_MINIVOSC_DRIVER); sprintf(card->shortname, "MySoundCard Audio %s", SND_MINIVOSC_DRIVER); sprintf(card->longname, "%s", card->shortname); snd_card_set_dev(card, &devptr->dev); // present in dummy, not in aloop though ret = snd_device_new(card, SNDRV_DEV_LOWLEVEL, mydev, &dev_ops); if (ret < 0) goto __nodev; nr_subdevs = 1; // how many capture substreams we want // * we want 0 playback, and 1 capture substreams (4th and 5th arg) .. ret = snd_pcm_new(card, card->driver, 0, 0, nr_subdevs, &pcm); if (ret < 0) goto __nodev; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &minivosc_pcm_ops); // in both aloop-kernel.c and dummy.c, after snd_pcm_new... pcm->private_data = mydev; //here it should be dev/card struct (the one containing struct snd_card *card) - this DOES NOT end up in substream->private_data pcm->info_flags = 0; strcpy(pcm->name, card->shortname); /* trid to add this - but it crashes here: //mydev->substream->private_data = mydev; Well, first time real substream comes in, is in _open - so that has to be handled there.. That is: at this point, mydev->substream is null, and we first have a chance to set it ... in _open! */ ret = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), MAX_BUFFER, MAX_BUFFER); // in both aloop-kernel.c and dummy.c, after snd_pcm_set_ops... if (ret < 0) goto __nodev; // * will use the snd_card_register form from aloop-kernel.c/dummy.c here.. ret = snd_card_register(card); if (ret == 0) // or... (!ret) { platform_set_drvdata(devptr, card); return 0; // success } __nodev: // as in aloop/dummy... dbg("__nodev reached!!"); snd_card_free(card); // this will autocall .dev_free (= minivosc_pcm_dev_free) return ret; }
int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) { int i, ret; dev->n_audio_in = max(dev->spec.num_analog_audio_in, dev->spec.num_digital_audio_in) / CHANNELS_PER_STREAM; dev->n_audio_out = max(dev->spec.num_analog_audio_out, dev->spec.num_digital_audio_out) / CHANNELS_PER_STREAM; dev->n_streams = max(dev->n_audio_in, dev->n_audio_out); debug("dev->n_audio_in = %d\n", dev->n_audio_in); debug("dev->n_audio_out = %d\n", dev->n_audio_out); debug("dev->n_streams = %d\n", dev->n_streams); if (dev->n_streams > MAX_STREAMS) { log("unable to initialize device, too many streams.\n"); return -EINVAL; } ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, dev->n_audio_out, dev->n_audio_in, &dev->pcm); if (ret < 0) { log("snd_pcm_new() returned %d\n", ret); return ret; } dev->pcm->private_data = dev; strcpy(dev->pcm->name, dev->product_name); memset(dev->sub_playback, 0, sizeof(dev->sub_playback)); memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware, sizeof(snd_usb_caiaq_pcm_hardware)); /* setup samplerates */ dev->samplerates = dev->pcm_info.rates; switch (dev->chip.usb_id) { case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE): dev->samplerates |= SNDRV_PCM_RATE_192000; /* fall thru */ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): dev->samplerates |= SNDRV_PCM_RATE_88200; break; } snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usb_caiaq_ops); snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usb_caiaq_ops); snd_pcm_lib_preallocate_pages_for_all(dev->pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), MAX_BUFFER_SIZE, MAX_BUFFER_SIZE); dev->data_cb_info = kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, GFP_KERNEL); if (!dev->data_cb_info) return -ENOMEM; for (i = 0; i < N_URBS; i++) { dev->data_cb_info[i].dev = dev; dev->data_cb_info[i].index = i; } dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret); if (ret < 0) { kfree(dev->data_cb_info); free_urbs(dev->data_urbs_in); return ret; } dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret); if (ret < 0) { kfree(dev->data_cb_info); free_urbs(dev->data_urbs_in); free_urbs(dev->data_urbs_out); return ret; } return 0; }