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

📄 rme96xx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	{	     int i,j;	     int cnt = count/dma->inchannels;	     for (i=0;i < dma->inchannels;i++) {		  short* sbuf = (short*)buffer + i;		  short* hwbuf =(short*) &dma->s->recbuf[(dma->inoffset + i)*RME96xx_DMA_MAX_SAMPLES];	     		  hwbuf+=(swptr>>1);		  for (j=0;j<(cnt>>1);j++) {		       hwbuf++;		       __put_user(*hwbuf++,sbuf++);		       sbuf+=(dma->inchannels-1);		  }	     }	     swptr += (cnt<<1);	     break;	}	default:	     printk(RME_MESS" unsupported format\n");	     return -1;	} /* switch */		swptr&=((dma->s->fragsize<<1) -1);		dma->readptr = swptr;	return 0;}static void rme96xx_interrupt(int irq, void *dev_id, struct pt_regs *regs){	int i;	rme96xx_info *s = (rme96xx_info *)dev_id;	struct dmabuf *db;	u32 status;	unsigned long flags;	status = readl(s->iobase + RME96xx_status_register);	if (!(status & RME96xx_IRQ)) {		return;	}	spin_lock_irqsave(&s->lock,flags);	writel(0,s->iobase + RME96xx_irq_clear);	s->hwbufid = (status & RME96xx_buffer_id)>>26;		if ((status & 0xffc0) <= 256) s->hwptr = 0; 	for(i=0;i<devices;i++)	{		db = &(s->dma[i]);		if(db->started > 0)			wake_up(&(db->wait));			}  	spin_unlock_irqrestore(&s->lock,flags);}/*----------------------------------------------------------------------------  PCI detection and module initialization stuff  ----------------------------------------------------------------------------*/void* busmaster_malloc(int size) {     int pg; /* 2 s exponent of memory size */        char *buf;        DBG(printk("kernel malloc pages ..\n"));                for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);        buf = (char *) __get_free_pages(GFP_KERNEL | GFP_DMA, pg);        if (buf) {                struct page* page, *last_page;                page = virt_to_page(buf);                last_page = virt_to_page(buf + (1 << pg));                DBG(printk("setting reserved bit\n"));                while (page < last_page) {			SetPageReserved(page);                        page++;                }		return buf;        }	DBG(printk("allocated %ld",(long)buf));	return NULL;}void busmaster_free(void* ptr,int size) {        int pg;	struct page* page, *last_page;        if (ptr == NULL)                return;        for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);        page = virt_to_page(ptr);        last_page = page + (1 << pg);        while (page < last_page) {		ClearPageReserved(page);		page++;	}	DBG(printk("freeing pages\n"));        free_pages((unsigned long) ptr, pg);	DBG(printk("done\n"));}/* initialize those parts of the info structure which are not pci detectable resources */static int rme96xx_dmabuf_init(rme96xx_info * s,struct dmabuf* dma,int ioffset,int ooffset) {	init_MUTEX(&dma->open_sem);	init_waitqueue_head(&dma->open_wait);	init_waitqueue_head(&dma->wait);	dma->s = s; 	dma->error = 0;	dma->format = AFMT_S32_BLOCKED;	dma->formatshift = 0;	dma->inchannels = dma->outchannels = 1;	dma->inoffset = ioffset;	dma->outoffset = ooffset;	dma->opened=0;	dma->started=0;	dma->mmapped=0;	dma->open_mode=0;	dma->mono=0;	rme96xx_clearbufs(dma);	return 0;}int rme96xx_init(rme96xx_info* s){	int i;	DBG(printk(__FUNCTION__"\n"));	numcards++;	s->magic = RME96xx_MAGIC; 	spin_lock_init(&s->lock);	COMM            ("setup busmaster memory")	s->recbuf = busmaster_malloc(RME96xx_DMA_MAX_SIZE_ALL);	s->playbuf = busmaster_malloc(RME96xx_DMA_MAX_SIZE_ALL);	if (!s->recbuf || !s->playbuf) {		printk(KERN_ERR RME_MESS" Unable to allocate busmaster memory\n");		return -ENODEV;	}	COMM            ("setting rec and playbuffers")	writel((u32) virt_to_bus(s->recbuf),s->iobase + RME96xx_rec_buffer);  	writel((u32) virt_to_bus(s->playbuf),s->iobase + RME96xx_play_buffer);	COMM             ("initializing control register")	rme96xx_unset_ctrl(s,0xffffffff);	rme96xx_set_ctrl(s,RME96xx_ctrl_init);	COMM              ("setup devices")		for (i=0;i < devices;i++) {		struct dmabuf * dma = &s->dma[i];		rme96xx_dmabuf_init(s,dma,2*i,2*i);	}	s->started = 0;	rme96xx_setlatency(s,7);	printk(KERN_INFO RME_MESS" card %d initialized\n",numcards); 	return 0;}/* open uses this to figure out which device was opened .. this seems to be    unnecessary complex */static LIST_HEAD(devs);static int __devinit rme96xx_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid){	int i;	rme96xx_info *s;	DBG(printk(__FUNCTION__"\n"));		if (pcidev->irq == 0) 		return -1;	if (!pci_dma_supported(pcidev, 0xffffffff)) {		printk(KERN_WARNING RME_MESS" architecture does not support 32bit PCI busmaster DMA\n");		return -1;	}	if (!(s = kmalloc(sizeof(rme96xx_info), GFP_KERNEL))) {		printk(KERN_WARNING RME_MESS" out of memory\n");		return -1;	}	memset(s, 0, sizeof(rme96xx_info));	s->pcidev = pcidev;	s->iobase = ioremap(pci_resource_start(pcidev, 0),RME96xx_IO_EXTENT);	s->irq = pcidev->irq;        DBG(printk("remapped iobase: %lx irq %d\n",(long)s->iobase,s->irq));	if (pci_enable_device(pcidev))		goto err_irq;	if (request_irq(s->irq, rme96xx_interrupt, SA_SHIRQ, "es1370", s)) {		printk(KERN_ERR RME_MESS" irq %u in use\n", s->irq);		goto err_irq;	}		/* initialize the card */	i = 0;	if (rme96xx_init(s) < 0) {		printk(KERN_ERR RME_MESS" initialization failed\n");		goto err_devices;	}	for (i=0;i<devices;i++) {		if ((s->dspnum[i] = register_sound_dsp(&rme96xx_audio_fops, -1)) < 0)			goto err_devices;	}	if ((s->mixer = register_sound_mixer(&rme96xx_mixer_fops, -1)) < 0)		goto err_devices;	pci_set_drvdata(pcidev, s);	pcidev->dma_mask = 0xffffffff; /* ????? */	/* put it into driver list */	list_add_tail(&s->devs, &devs);	DBG(printk("initialization successful\n"));	return 0;	/* error handler */ err_devices:	while (i--) 		unregister_sound_dsp(s->dspnum[i]);	free_irq(s->irq,s); err_irq:	kfree(s);	return -1;}static void __devinit rme96xx_remove(struct pci_dev *dev){	int i;	rme96xx_info *s = pci_get_drvdata(dev);	if (!s) {		printk(KERN_ERR"device structure not valid\n");		return ;	}	if (s->started) rme96xx_startcard(s,0);	i = devices;	while (i) {		i--;		unregister_sound_dsp(s->dspnum[i]);	}		unregister_sound_mixer(s->mixer);/*	synchronize_irq(); This call got lost somehow ? */        free_irq(s->irq,s);	busmaster_free(s->recbuf,RME96xx_DMA_MAX_SIZE_ALL);	busmaster_free(s->playbuf,RME96xx_DMA_MAX_SIZE_ALL);	kfree(s);	pci_set_drvdata(dev, NULL);}#ifndef PCI_VENDOR_ID_RME #define PCI_VENDOR_ID_RME 0x10ee#endif#ifndef PCI_DEVICE_ID_RME9652#define PCI_DEVICE_ID_RME9652 0x3fc4#endif#ifndef PCI_ANY_ID#define PCI_ANY_ID 0#endifstatic struct pci_device_id id_table[] __devinitdata = {	{ PCI_VENDOR_ID_RME, PCI_DEVICE_ID_RME9652, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },	{ 0, }};MODULE_DEVICE_TABLE(pci, id_table);static struct pci_driver rme96xx_driver = {	name: "rme96xx",	id_table: id_table,	probe: rme96xx_probe,	remove: rme96xx_remove};static int __init init_rme96xx(void){  	if (!pci_present())   /* No PCI bus in this machine! */		return -ENODEV;	printk(KERN_INFO RME_MESS" version "RMEVERSION" time " __TIME__ " " __DATE__ "\n");	printk(KERN_INFO RME_MESS" reserving %d dsp device(s)\n",devices);        numcards = 0;	return pci_module_init(&rme96xx_driver);}static void __exit cleanup_rme96xx(void){	printk(KERN_INFO RME_MESS" unloading\n");	pci_unregister_driver(&rme96xx_driver);}module_init(init_rme96xx);module_exit(cleanup_rme96xx);/*--------------------------------------------------------------------------    Implementation of file operations ---------------------------------------------------------------------------*/#define RME96xx_FMT (AFMT_S16_LE|AFMT_U8|AFMT_S32_BLOCKED)static int rme96xx_ioctl(struct inode *in, struct file *file, 						unsigned int cmd, unsigned long arg){	struct dmabuf * dma = (struct dmabuf *)file->private_data; 	rme96xx_info *s = dma->s;	unsigned long flags;        audio_buf_info abinfo;        count_info cinfo;	int count;	int val = 0;	VALIDATE_STATE(s);	DBG(printk("ioctl %ud\n",cmd));	switch (cmd) {	case OSS_GETVERSION:		return put_user(SOUND_VERSION, (int *)arg);	case SNDCTL_DSP_SYNC:#if 0		if (file->f_mode & FMODE_WRITE)			return drain_dac2(s, 0/*file->f_flags & O_NONBLOCK*/);#endif		return 0;			case SNDCTL_DSP_SETDUPLEX:		return 0;	case SNDCTL_DSP_GETCAPS:		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);		        case SNDCTL_DSP_RESET://		rme96xx_clearbufs(dma);		return 0;        case SNDCTL_DSP_SPEED:                if (get_user(val, (int *)arg))			return -EFAULT;		if (val >= 0) {/* generally it's not a problem if we change the speed 			if (dma->open_mode & (~file->f_mode) & (FMODE_READ|FMODE_WRITE))				return -EINVAL;*/			spin_lock_irqsave(&s->lock, flags);			switch (val) {			case 44100:			case 88200:				rme96xx_unset_ctrl(s,RME96xx_freq);				break;			case 48000: 			case 96000: 				rme96xx_set_ctrl(s,RME96xx_freq);				break;			default:				rme96xx_unset_ctrl(s,RME96xx_freq);				val = 44100;			}			if (val > 50000)				rme96xx_set_ctrl(s,RME96xx_DS);			else				rme96xx_unset_ctrl(s,RME96xx_DS);			s->rate = val;			spin_unlock_irqrestore(&s->lock, flags);		}		DBG(printk("speed set to %d\n",val));		return put_user(val, (int *)arg);		        case SNDCTL_DSP_STEREO: /* this plays a mono file on two channels */                if (get_user(val, (int *)arg))			return -EFAULT;				if (!val) {			DBG(printk("setting to mono\n")); 			dma->mono=1; 			dma->inchannels = 1;			dma->outchannels = 1;		}		else {			DBG(printk("setting to stereo\n")); 			dma->mono = 0;			dma->inchannels = 2;			dma->outchannels = 2;		}		return 0;        case SNDCTL_DSP_CHANNELS:		/* remember to check for resonable offset/channel pairs here */                if (get_user(val, (int *)arg))			return -EFAULT;		if (file->f_mode & FMODE_WRITE) { 						if (val > 0 && (dma->outoffset + val) <= RME96xx_CHANNELS_PER_CARD) 				dma->outchannels = val;			else				dma->outchannels = val = 2;			DBG(printk("setting to outchannels %d\n",val)); 		}		if (file->f_mode & FMODE_READ) {			if (val > 0 && (dma->inoffset + val) <= RME96xx_CHANNELS_PER_CARD) 				dma->inchannels = val;			else				dma->inchannels = val = 2;			DBG(printk("setting to inchannels %d\n",val)); 		}		dma->mono=0;		return put_user(val, (int *)arg);			case SNDCTL_DSP_GETFMTS: /* Returns a mask */                return put_user(RME96xx_FMT, (int *)arg);			case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/		DBG(printk("setting to format %x\n",val)); 		if (get_user(val, (int *)arg))			return -EFAULT;		if (val != AFMT_QUERY) {			if (val & RME96xx_FMT)				dma->format = val;			switch (dma->format) {			case AFMT_S16_LE:				dma->formatshift=1;				break;			case AFMT_S32_BLOCKED:				dma->formatshift=0;				break;			}		}		return put_user(dma->format, (int *)arg);			case SNDCTL_DSP_POST:                return 0;        case SNDCTL_DSP_GETTRIGGER:		val = 0;#if 0		if (file->f_mode & FMODE_READ && s->ctrl & CTRL_ADC_EN) 			val |= PCM_ENABLE_INPUT;		if (file->f_mode & FMODE_WRITE && s->ctrl & CTRL_DAC2_EN) 			val |= PCM_ENABLE_OUTPUT;#endif		return put_user(val, (int *)arg);			case SNDCTL_DSP_SETTRIGGER:		if (get_user(val, (int *)arg))			return -EFAULT;#if 0		if (file->f_mode & FMODE_READ) {			if (val & PCM_ENABLE_INPUT) {				if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))					return ret;				start_adc(s);			} else				stop_adc(s);		}		if (file->f_mode & FMODE_WRITE) {			if (val & PCM_ENABLE_OUTPUT) {				if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))					return ret;				start_dac2(s);			} else				stop_dac2(s);		}#endif		return 0;	case SNDCTL_DSP_GETOSPACE:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		val = rme96xx_gethwptr(dma->s,0);		count = rme96xx_getospace(dma,val);		if (!s->started) count = s->fragsize*2;		abinfo.fragsize =(s->fragsize*dma->outchannels)>>dma->formatshift;                abinfo.bytes = (count*dma->outchannels)>>dma->formatshift;                abinfo.fragstotal = 2;                abinfo.fragments = (count > s->fragsize); 		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;	case SNDCTL_DSP_GETISPACE:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		val = rme96xx_gethwptr(dma->s,0);		count = rme96xx_getispace(dma,val);

⌨️ 快捷键说明

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