⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcxhr.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);	struct pcxhr_mgr *mgr = chip->mgr;	struct pcxhr_stream *stream = subs->runtime->private_data;	down(&mgr->setup_mutex);	snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number);	/* sample rate released */	if (--mgr->ref_count_rate == 0) {		mgr->sample_rate = 0;		/* the sample rate is no more locked */		pcxhr_hardware_timer(mgr, 0);	/* stop the DSP-timer */	}	stream->status    = PCXHR_STREAM_STATUS_FREE;	stream->substream = NULL;	up(&mgr->setup_mutex);	return 0;}static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs){	unsigned long flags;	u_int32_t timer_period_frag;	int timer_buf_periods;	struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);	struct snd_pcm_runtime *runtime = subs->runtime;	struct pcxhr_stream *stream  = runtime->private_data;	spin_lock_irqsave(&chip->mgr->lock, flags);	/* get the period fragment and the nb of periods in the buffer */	timer_period_frag = stream->timer_period_frag;	timer_buf_periods = stream->timer_buf_periods;	spin_unlock_irqrestore(&chip->mgr->lock, flags);	return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) +				   timer_period_frag);}static struct snd_pcm_ops pcxhr_ops = {	.open      = pcxhr_open,	.close     = pcxhr_close,	.ioctl     = snd_pcm_lib_ioctl,	.prepare   = pcxhr_prepare,	.hw_params = pcxhr_hw_params,	.hw_free   = pcxhr_hw_free,	.trigger   = pcxhr_trigger,	.pointer   = pcxhr_stream_pointer,};/* */int pcxhr_create_pcm(struct snd_pcxhr *chip){	int err;	struct snd_pcm *pcm;	char name[32];	sprintf(name, "pcxhr %d", chip->chip_idx);	if ((err = snd_pcm_new(chip->card, name, 0,			       chip->nb_streams_play,			       chip->nb_streams_capt, &pcm)) < 0) {		snd_printk(KERN_ERR "cannot create pcm %s\n", name);		return err;	}	pcm->private_data = chip;	if (chip->nb_streams_play)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcxhr_ops);	if (chip->nb_streams_capt)		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops);	pcm->info_flags = 0;	strcpy(pcm->name, name);	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->mgr->pci),					      32*1024, 32*1024);	chip->pcm = pcm;	return 0;}static int pcxhr_chip_free(struct snd_pcxhr *chip){	kfree(chip);	return 0;}static int pcxhr_chip_dev_free(struct snd_device *device){	struct snd_pcxhr *chip = device->device_data;	return pcxhr_chip_free(chip);}/* */static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, int idx){	int err;	struct snd_pcxhr *chip;	static struct snd_device_ops ops = {		.dev_free = pcxhr_chip_dev_free,	};	mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);	if (! chip) {		snd_printk(KERN_ERR "cannot allocate chip\n");		return -ENOMEM;	}	chip->card = card;	chip->chip_idx = idx;	chip->mgr = mgr;	if (idx < mgr->playback_chips)		/* stereo or mono streams */		chip->nb_streams_play = PCXHR_PLAYBACK_STREAMS;	if (idx < mgr->capture_chips) {		if (mgr->mono_capture)			chip->nb_streams_capt = 2;	/* 2 mono streams (left+right) */		else			chip->nb_streams_capt = 1;	/* or 1 stereo stream */	}	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {		pcxhr_chip_free(chip);		return err;	}	snd_card_set_dev(card, &mgr->pci->dev);	return 0;}/* proc interface */static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer){	struct snd_pcxhr *chip = entry->private_data;	struct pcxhr_mgr *mgr = chip->mgr;	snd_iprintf(buffer, "\n%s\n", mgr->longname);	/* stats available when embedded DSP is running */	if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {		struct pcxhr_rmh rmh;		short ver_maj = (mgr->dsp_version >> 16) & 0xff;		short ver_min = (mgr->dsp_version >> 8) & 0xff;		short ver_build = mgr->dsp_version & 0xff;		snd_iprintf(buffer, "module version %s\n", PCXHR_DRIVER_VERSION_STRING);		snd_iprintf(buffer, "dsp version %d.%d.%d\n", ver_maj, ver_min, ver_build);		if (mgr->board_has_analog)			snd_iprintf(buffer, "analog io available\n");		else			snd_iprintf(buffer, "digital only board\n");		/* calc cpu load of the dsp */		pcxhr_init_rmh(&rmh, CMD_GET_DSP_RESOURCES);		if( ! pcxhr_send_msg(mgr, &rmh) ) {			int cur = rmh.stat[0];			int ref = rmh.stat[1];			if (ref > 0) {				if (mgr->sample_rate_real != 0 &&				    mgr->sample_rate_real != 48000) {					ref = (ref * 48000) / mgr->sample_rate_real;					if (mgr->sample_rate_real >= PCXHR_IRQ_TIMER_FREQ)						ref *= 2;				}				cur = 100 - (100 * cur) / ref;				snd_iprintf(buffer, "cpu load    %d%%\n", cur);				snd_iprintf(buffer, "buffer pool %d/%d kWords\n",					    rmh.stat[2], rmh.stat[3]);			}		}		snd_iprintf(buffer, "dma granularity : %d\n", PCXHR_GRANULARITY);		snd_iprintf(buffer, "dsp time errors : %d\n", mgr->dsp_time_err);		snd_iprintf(buffer, "dsp async pipe xrun errors : %d\n",			    mgr->async_err_pipe_xrun);		snd_iprintf(buffer, "dsp async stream xrun errors : %d\n",			    mgr->async_err_stream_xrun);		snd_iprintf(buffer, "dsp async last other error : %x\n",			    mgr->async_err_other_last);		/* debug zone dsp */		rmh.cmd[0] = 0x4200 + PCXHR_SIZE_MAX_STATUS;		rmh.cmd_len = 1;		rmh.stat_len = PCXHR_SIZE_MAX_STATUS;		rmh.dsp_stat = 0;		rmh.cmd_idx = CMD_LAST_INDEX;		if( ! pcxhr_send_msg(mgr, &rmh) ) {			int i;			for (i = 0; i < rmh.stat_len; i++)				snd_iprintf(buffer, "debug[%02d] = %06x\n", i,  rmh.stat[i]);		}	} else		snd_iprintf(buffer, "no firmware loaded\n");	snd_iprintf(buffer, "\n");}static void pcxhr_proc_sync(struct snd_info_entry *entry, struct snd_info_buffer *buffer){	struct snd_pcxhr *chip = entry->private_data;	struct pcxhr_mgr *mgr = chip->mgr;	static char *texts[7] = {		"Internal", "Word", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"	};	snd_iprintf(buffer, "\n%s\n", mgr->longname);	snd_iprintf(buffer, "Current Sample Clock\t: %s\n", texts[mgr->cur_clock_type]);	snd_iprintf(buffer, "Current Sample Rate\t= %d\n", mgr->sample_rate_real);	/* commands available when embedded DSP is running */	if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {		int i, err, sample_rate;		for (i = PCXHR_CLOCK_TYPE_WORD_CLOCK; i< (3 + mgr->capture_chips); i++) {			err = pcxhr_get_external_clock(mgr, i, &sample_rate);			if (err)				break;			snd_iprintf(buffer, "%s Clock\t\t= %d\n", texts[i], sample_rate);		}	} else		snd_iprintf(buffer, "no firmware loaded\n");	snd_iprintf(buffer, "\n");}static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip){	struct snd_info_entry *entry;	if (! snd_card_proc_new(chip->card, "info", &entry))		snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_info);	if (! snd_card_proc_new(chip->card, "sync", &entry))		snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_sync);}/* end of proc interface *//* * release all the cards assigned to a manager instance */static int pcxhr_free(struct pcxhr_mgr *mgr){	unsigned int i;	for (i = 0; i < mgr->num_cards; i++) {		if (mgr->chip[i])			snd_card_free(mgr->chip[i]->card);	}	/* reset board if some firmware was loaded */	if(mgr->dsp_loaded) {		pcxhr_reset_board(mgr);		snd_printdd("reset pcxhr !\n");	}	/* release irq  */	if (mgr->irq >= 0)		free_irq(mgr->irq, mgr);	pci_release_regions(mgr->pci);	/* free hostport purgebuffer */	if (mgr->hostport.area) {		snd_dma_free_pages(&mgr->hostport);		mgr->hostport.area = NULL;	}	kfree(mgr->prmh);	pci_disable_device(mgr->pci);	kfree(mgr);	return 0;}/* *    probe function - creates the card manager */static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id *pci_id){	static int dev;	struct pcxhr_mgr *mgr;	unsigned int i;	int err;	size_t size;	char *card_name;	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, 0xffffffff) < 0) {		snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");		pci_disable_device(pci);		return -ENXIO;	}	/* alloc card manager */	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);	if (! mgr) {		pci_disable_device(pci);		return -ENOMEM;	}	snd_assert(pci_id->driver_data < PCI_ID_LAST, return -ENODEV);	card_name = pcxhr_board_params[pci_id->driver_data].board_name;	mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips;	mgr->capture_chips  = pcxhr_board_params[pci_id->driver_data].capture_chips;	mgr->firmware_num  = pcxhr_board_params[pci_id->driver_data].firmware_num;	mgr->mono_capture = mono[dev];	/* resource assignment */	if ((err = pci_request_regions(pci, card_name)) < 0) {		kfree(mgr);		pci_disable_device(pci);		return err;	}	for (i = 0; i < 3; i++)		mgr->port[i] = pci_resource_start(pci, i);	mgr->pci = pci;	mgr->irq = -1;	if (request_irq(pci->irq, pcxhr_interrupt, SA_INTERRUPT|SA_SHIRQ,			card_name, mgr)) {		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);		pcxhr_free(mgr);		return -EBUSY;	}	mgr->irq = pci->irq;	sprintf(mgr->shortname, "Digigram %s", card_name);	sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i", mgr->shortname,		mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);	/* ISR spinlock  */	spin_lock_init(&mgr->lock);	spin_lock_init(&mgr->msg_lock);	/* init setup mutex*/	init_MUTEX(&mgr->setup_mutex);	/* init taslket */	tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr);	tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet, (unsigned long) mgr);	mgr->prmh = kmalloc(sizeof(*mgr->prmh) + 			    sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - PCXHR_SIZE_MAX_STATUS),			    GFP_KERNEL);	if (! mgr->prmh) {		pcxhr_free(mgr);		return -ENOMEM;	}	for (i=0; i < PCXHR_MAX_CARDS; i++) {		struct snd_card *card;		char tmpid[16];		int idx;		if (i >= max(mgr->playback_chips, mgr->capture_chips))			break;		mgr->num_cards++;		if (index[dev] < 0)			idx = index[dev];		else			idx = index[dev] + i;		snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i);		card = snd_card_new(idx, tmpid, THIS_MODULE, 0);		if (! card) {			snd_printk(KERN_ERR "cannot allocate the card %d\n", i);			pcxhr_free(mgr);			return -ENOMEM;		}		strcpy(card->driver, DRIVER_NAME);		sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i);		sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);		if ((err = pcxhr_create(mgr, card, i)) < 0) {			pcxhr_free(mgr);			return err;		}		if (i == 0)			/* init proc interface only for chip0 */			pcxhr_proc_init(mgr->chip[i]);		if ((err = snd_card_register(card)) < 0) {			pcxhr_free(mgr);			return err;		}	}	/* create hostport purgebuffer */	size = PAGE_ALIGN(sizeof(struct pcxhr_hostport));	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),				size, &mgr->hostport) < 0) {		pcxhr_free(mgr);		return -ENOMEM;	}	/* init purgebuffer */	memset(mgr->hostport.area, 0, size);	/* create a DSP loader */	err = pcxhr_setup_firmware(mgr);	if (err < 0) {		pcxhr_free(mgr);		return err;	}	pci_set_drvdata(pci, mgr);	dev++;	return 0;}static void __devexit pcxhr_remove(struct pci_dev *pci){	pcxhr_free(pci_get_drvdata(pci));	pci_set_drvdata(pci, NULL);}static struct pci_driver driver = {	.name = "Digigram pcxhr",	.id_table = pcxhr_ids,	.probe = pcxhr_probe,	.remove = __devexit_p(pcxhr_remove),};static int __init pcxhr_module_init(void){	return pci_register_driver(&driver);}static void __exit pcxhr_module_exit(void){	pci_unregister_driver(&driver);}module_init(pcxhr_module_init)module_exit(pcxhr_module_exit)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -