📄 mixart.c
字号:
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 + -