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

📄 mixart.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
			       MIXART_PLAYBACK_STREAMS,			       MIXART_CAPTURE_STREAMS, &pcm)) < 0) {		snd_printk(KERN_ERR "cannot create the digital pcm %d\n", chip->chip_idx);		return err;	}	pcm->private_data = chip;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);	pcm->info_flags = 0;	strcpy(pcm->name, name);	preallocate_buffers(chip, pcm);	chip->pcm_dig = pcm;	return 0;}static int snd_mixart_chip_free(mixart_t *chip){	kfree(chip);	return 0;}static int snd_mixart_chip_dev_free(snd_device_t *device){	mixart_t *chip = device->device_data;	return snd_mixart_chip_free(chip);}/* */static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int idx){	int err;	mixart_t *chip;	static snd_device_ops_t ops = {		.dev_free = snd_mixart_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 ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {		snd_mixart_chip_free(chip);		return err;	}	snd_card_set_dev(card, &mgr->pci->dev);	return 0;}int snd_mixart_create_pcm(mixart_t* chip){	int err;	err = snd_mixart_pcm_analog(chip);	if (err < 0)		return err;	if(chip->mgr->board_type == MIXART_DAUGHTER_TYPE_AES) {		err = snd_mixart_pcm_digital(chip);		if (err < 0)			return err;	}	return err;}/* * release all the cards assigned to a manager instance */static int snd_mixart_free(mixart_mgr_t *mgr){	unsigned int i;	for (i = 0; i < mgr->num_cards; i++) {		if (mgr->chip[i])			snd_card_free(mgr->chip[i]->card);	}	/* stop mailbox */	snd_mixart_exit_mailbox(mgr);	/* release irq  */	if (mgr->irq >= 0)		free_irq(mgr->irq, (void *)mgr);	/* reset board if some firmware was loaded */	if(mgr->dsp_loaded) {		snd_mixart_reset_board(mgr);		snd_printdd("reset miXart !\n");	}	/* release the i/o ports */	for (i = 0; i < 2; i++) {		if (mgr->mem[i].virt)			iounmap(mgr->mem[i].virt);	}	pci_release_regions(mgr->pci);	/* free flowarray */	if(mgr->flowinfo.area) {		snd_dma_free_pages(&mgr->flowinfo);		mgr->flowinfo.area = NULL;	}	/* free bufferarray */	if(mgr->bufferinfo.area) {		snd_dma_free_pages(&mgr->bufferinfo);		mgr->bufferinfo.area = NULL;	}	pci_disable_device(mgr->pci);	kfree(mgr);	return 0;}/* * proc interface */static long long snd_mixart_BA0_llseek(snd_info_entry_t *entry,				       void *private_file_data,				       struct file *file,				       long long offset,				       int orig){	offset = offset & ~3; /* 4 bytes aligned */	switch(orig) {	case 0:  /* SEEK_SET */		file->f_pos = offset;		break;	case 1:  /* SEEK_CUR */		file->f_pos += offset;		break;	case 2:  /* SEEK_END, offset is negative */		file->f_pos = MIXART_BA0_SIZE + offset;		break;	default:		return -EINVAL;	}	if(file->f_pos > MIXART_BA0_SIZE)		file->f_pos = MIXART_BA0_SIZE;	return file->f_pos;}static long long snd_mixart_BA1_llseek(snd_info_entry_t *entry,				       void *private_file_data,				       struct file *file,				       long long offset,				       int orig){	offset = offset & ~3; /* 4 bytes aligned */	switch(orig) {	case 0:  /* SEEK_SET */		file->f_pos = offset;		break;	case 1:  /* SEEK_CUR */		file->f_pos += offset;		break;	case 2: /* SEEK_END, offset is negative */		file->f_pos = MIXART_BA1_SIZE + offset;		break;	default:		return -EINVAL;	}	if(file->f_pos > MIXART_BA1_SIZE)		file->f_pos = MIXART_BA1_SIZE;	return file->f_pos;}/*  mixart_BA0 proc interface for BAR 0 - read callback */static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data,				struct file *file, char __user *buf,				unsigned long count, unsigned long pos){	mixart_mgr_t *mgr = entry->private_data;	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */	if(count <= 0)		return 0;	if(pos + count > MIXART_BA0_SIZE)		count = (long)(MIXART_BA0_SIZE - pos);	if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count))		return -EFAULT;	return count;}/*  mixart_BA1 proc interface for BAR 1 - read callback */static long snd_mixart_BA1_read(snd_info_entry_t *entry, void *file_private_data,				struct file *file, char __user *buf,				unsigned long count, unsigned long pos){	mixart_mgr_t *mgr = entry->private_data;	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */	if(count <= 0)		return 0;	if(pos + count > MIXART_BA1_SIZE)		count = (long)(MIXART_BA1_SIZE - pos);	if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count))		return -EFAULT;	return count;}static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {	.read   = snd_mixart_BA0_read,	.llseek = snd_mixart_BA0_llseek};static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {	.read   = snd_mixart_BA1_read,	.llseek = snd_mixart_BA1_llseek};static void snd_mixart_proc_read(snd_info_entry_t *entry,                                  snd_info_buffer_t * buffer){	mixart_t *chip = entry->private_data;        	u32 ref; 	snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);	/* stats available when embedded OS is running */	if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {		snd_iprintf(buffer, "- hardware -\n");		switch (chip->mgr->board_type ) {		case MIXART_DAUGHTER_TYPE_NONE     : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break;		case MIXART_DAUGHTER_TYPE_AES      : snd_iprintf(buffer, "\tmiXart8 AES/EBU\n\n"); break;		case MIXART_DAUGHTER_TYPE_COBRANET : snd_iprintf(buffer, "\tmiXart8 Cobranet\n\n"); break;		default:                             snd_iprintf(buffer, "\tUNKNOWN!\n\n"); break;		}		snd_iprintf(buffer, "- system load -\n");	 		/* get perf reference */		ref = readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET));		if (ref) {			u32 mailbox   = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET)) / ref;			u32 streaming = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET)) / ref;			u32 interr    = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET)) / ref;			snd_iprintf(buffer, "\tstreaming          : %d\n", streaming);			snd_iprintf(buffer, "\tmailbox            : %d\n", mailbox);			snd_iprintf(buffer, "\tinterrups handling : %d\n\n", interr);		}	} /* endif elf loaded */}static void __devinit snd_mixart_proc_init(mixart_t *chip){	snd_info_entry_t *entry;	/* text interface to read perf and temp meters */	if (! snd_card_proc_new(chip->card, "board_info", &entry)) {		entry->private_data = chip;		entry->c.text.read_size = 1024;		entry->c.text.read = snd_mixart_proc_read;	}	if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) {		entry->content = SNDRV_INFO_CONTENT_DATA;		entry->private_data = chip->mgr;			entry->c.ops = &snd_mixart_proc_ops_BA0;		entry->size = MIXART_BA0_SIZE;	}	if (! snd_card_proc_new(chip->card, "mixart_BA1", &entry)) {		entry->content = SNDRV_INFO_CONTENT_DATA;		entry->private_data = chip->mgr;		entry->c.ops = &snd_mixart_proc_ops_BA1;		entry->size = MIXART_BA1_SIZE;	}}/* end of proc interface *//* *    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;	mixart_mgr_t *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, 0xffffffff) < 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 = ioremap_nocache(mgr->mem[i].phys,						   pci_resource_len(pci, i));	}	if (request_irq(pci->irq, snd_mixart_interrupt, SA_INTERRUPT|SA_SHIRQ, CARD_NAME, (void *)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);	init_MUTEX(&mgr->msg_mutex);	init_waitqueue_head(&mgr->msg_sleep);	atomic_set(&mgr->msg_processed, 0);	/* init setup mutex*/	init_MUTEX(&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++) {		snd_card_t *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_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(mixart_flowinfo_t)) );	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(mixart_bufferinfo_t)) );	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 void __devexit snd_mixart_remove(struct pci_dev *pci){	snd_mixart_free(pci_get_drvdata(pci));	pci_set_drvdata(pci, NULL);}static struct pci_driver driver = {	.name = "Digigram miXart",	.id_table = snd_mixart_ids,	.probe = snd_mixart_probe,	.remove = __devexit_p(snd_mixart_remove),};static int __init alsa_card_mixart_init(void){	return pci_register_driver(&driver);}static void __exit alsa_card_mixart_exit(void){	pci_unregister_driver(&driver);}module_init(alsa_card_mixart_init)module_exit(alsa_card_mixart_exit)

⌨️ 快捷键说明

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