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

📄 rme96xx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
		abinfo.fragsize = (s->fragsize*dma->inchannels)>>dma->formatshift;                abinfo.bytes = (count*dma->inchannels)>>dma->formatshift;;                abinfo.fragstotal = 2;                abinfo.fragments = count > s->fragsize; 		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;		        case SNDCTL_DSP_NONBLOCK:                file->f_flags |= O_NONBLOCK;                return 0;        case SNDCTL_DSP_GETODELAY: /* What shold this exactly do ? , 				      ATM it is just abinfo.bytes */		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		val = rme96xx_gethwptr(dma->s,0);		count = val - dma->readptr;		if (count < 0)			count += s->fragsize<<1;		return put_user(count, (int *)arg);/* check out how to use mmaped mode (can only be blocked !!!) */        case SNDCTL_DSP_GETIPTR:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		val = rme96xx_gethwptr(dma->s,0);		spin_lock_irqsave(&s->lock,flags);                cinfo.bytes = s->fragsize<<1;;		count = val - dma->readptr;		if (count < 0)			count += s->fragsize<<1;                cinfo.blocks = (count > s->fragsize);                 cinfo.ptr = val;		if (dma->mmapped)			dma->readptr &= s->fragsize<<1;		spin_unlock_irqrestore(&s->lock,flags);                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));        case SNDCTL_DSP_GETOPTR:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		val = rme96xx_gethwptr(dma->s,0);		spin_lock_irqsave(&s->lock,flags);                cinfo.bytes = s->fragsize<<1;;		count = val - dma->writeptr;		if (count < 0)			count += s->fragsize<<1;                cinfo.blocks = (count > s->fragsize);                 cinfo.ptr = val;		if (dma->mmapped)			dma->writeptr &= s->fragsize<<1;		spin_unlock_irqrestore(&s->lock,flags);                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));        case SNDCTL_DSP_GETBLKSIZE:	     return put_user(s->fragsize, (int *)arg);        case SNDCTL_DSP_SETFRAGMENT:                if (get_user(val, (int *)arg))			return -EFAULT;		val&=0xffff;		val -= 7;		if (val < 0) val = 0;		if (val > 7) val = 7;		rme96xx_setlatency(s,val);		return 0;        case SNDCTL_DSP_SUBDIVIDE:#if 0		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||		    (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))			return -EINVAL;                if (get_user(val, (int *)arg))			return -EFAULT;		if (val != 1 && val != 2 && val != 4)			return -EINVAL;		if (file->f_mode & FMODE_READ)			s->dma_adc.subdivision = val;		if (file->f_mode & FMODE_WRITE)			s->dma_dac2.subdivision = val;#endif				return 0;        case SOUND_PCM_READ_RATE:		return put_user(s->rate, (int *)arg);        case SOUND_PCM_READ_CHANNELS:		return put_user(dma->outchannels, (int *)arg);        case SOUND_PCM_READ_BITS:		switch (dma->format) {			case AFMT_S32_BLOCKED:				val = 32;				break;			case AFMT_S16_LE:				val = 16;				break;		}		return put_user(val, (int *)arg);        case SOUND_PCM_WRITE_FILTER:        case SNDCTL_DSP_SETSYNCRO:        case SOUND_PCM_READ_FILTER:                return -EINVAL;			}	return -ENODEV;}static int rme96xx_open(struct inode *in, struct file *f){	int minor = MINOR(in->i_rdev);	struct list_head *list;	int devnum = ((minor-3)/16) % devices; /* default = 0 */	rme96xx_info *s;	struct dmabuf* dma;	DECLARE_WAITQUEUE(wait, current); 	DBG(printk("device num %d open\n",devnum));/* ??? */	for (list = devs.next; ; list = list->next) {		if (list == &devs)			return -ENODEV;		s = list_entry(list, rme96xx_info, devs);		if (!((s->dspnum[devnum] ^ minor) & ~0xf)) 			break;	}       	VALIDATE_STATE(s);/* ??? */	dma = &s->dma[devnum];	f->private_data = dma;	/* wait for device to become free */	down(&s->dma[devnum].open_sem);	while (dma->open_mode & f->f_mode) {		if (f->f_flags & O_NONBLOCK) {			up(&dma->open_sem);			return -EBUSY;		}		add_wait_queue(&dma->open_wait, &wait);		__set_current_state(TASK_INTERRUPTIBLE);		up(&dma->open_sem);		schedule();		remove_wait_queue(&dma->open_wait, &wait);		set_current_state(TASK_RUNNING);		if (signal_pending(current))			return -ERESTARTSYS;		down(&dma->open_sem);	}	COMM                ("hardware open")	if (!s->dma[devnum].opened) rme96xx_dmabuf_init(dma->s,dma,dma->inoffset,dma->outoffset);	s->dma[devnum].open_mode |= (f->f_mode & (FMODE_READ | FMODE_WRITE));	s->dma[devnum].opened = 1;	up(&s->dma[devnum].open_sem);	DBG(printk("device num %d open finished\n",devnum));	return 0;}static int rme96xx_release(struct inode *in, struct file *file){	struct dmabuf * dma = (struct dmabuf*) file->private_data;	int hwp;	DBG(printk(__FUNCTION__"\n"));	COMM          ("draining")	if (dma->open_mode & FMODE_WRITE) {#if 0 /* Why doesn't this work with some cards ?? */	     hwp = rme96xx_gethwptr(dma->s,0);	     while (rme96xx_getospace(dma,hwp)) {		  interruptible_sleep_on(&(dma->wait));		  hwp = rme96xx_gethwptr(dma->s,0);	     }#endif	     rme96xx_clearbufs(dma);	}	dma->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);	if (!(dma->open_mode & (FMODE_READ|FMODE_WRITE))) {	     dma->opened = 0;	     if (dma->s->started) rme96xx_startcard(dma->s,1);	}	wake_up(&dma->open_wait);	up(&dma->open_sem);	return 0;}static ssize_t rme96xx_write(struct file *file, const char *buffer, 									  size_t count, loff_t *ppos){	struct dmabuf *dma = (struct dmabuf *)file->private_data;	ssize_t ret = 0;	int cnt; /* number of bytes from "buffer" that will/can be used */	int hop = count/dma->outchannels;	int hwp;	int exact = (file->f_flags & O_NONBLOCK); 	if(dma == NULL || (dma->s) == NULL) 		return -ENXIO;	if (ppos != &file->f_pos)		return -ESPIPE;	if (dma->mmapped || !dma->opened)		return -ENXIO;	if (!access_ok(VERIFY_READ, buffer, count))		return -EFAULT;	if (! (dma->open_mode  & FMODE_WRITE))                return -ENXIO;	if (!dma->s->started) rme96xx_startcard(dma->s,exact);	hwp = rme96xx_gethwptr(dma->s,0);	if(!(dma->started)){		 		COMM          ("first write")					dma->readptr = hwp;		dma->writeptr = hwp;		dma->started = 1;		COMM          ("first write done")	}  	while (count > 0) {		cnt = rme96xx_getospace(dma,hwp);				cnt>>=dma->formatshift;		cnt*=dma->outchannels;		if (cnt > count)			cnt = count;		if (cnt != 0) {		        if (rme96xx_copyfromuser(dma,buffer,cnt,hop))				return ret ? ret : -EFAULT;			count -= cnt;			buffer += cnt;			ret += cnt;			if (count == 0) return ret;		}		if (file->f_flags & O_NONBLOCK)			return ret ? ret : -EAGAIN;				if ((hwp - dma->writeptr) <= 0) {			interruptible_sleep_on(&(dma->wait));						if (signal_pending(current))				return ret ? ret : -ERESTARTSYS;		}					hwp = rme96xx_gethwptr(dma->s,exact);	}; /* count > 0 */	return ret;}static ssize_t rme96xx_read(struct file *file, char *buffer,size_t count, loff_t *ppos){ 	struct dmabuf *dma = (struct dmabuf *)file->private_data;	ssize_t ret = 0;	int cnt;	int hop = count/dma->inchannels;	int hwp;	int exact = (file->f_flags & O_NONBLOCK); 	if(dma == NULL || (dma->s) == NULL) 		return -ENXIO;	if (ppos != &file->f_pos)		return -ESPIPE;	if (dma->mmapped || !dma->opened)		return -ENXIO;	if (!access_ok(VERIFY_WRITE, buffer, count))		return -EFAULT;	if (! (dma->open_mode  & FMODE_READ))                return -ENXIO;	if (count > ((dma->s->fragsize*dma->inchannels)>>dma->formatshift))	    return -EFAULT;	if (!dma->s->started) rme96xx_startcard(dma->s,exact);	hwp = rme96xx_gethwptr(dma->s,0);	if(!(dma->started)){		 		COMM          ("first read")		     		dma->writeptr = hwp;		dma->readptr = hwp;		dma->started = 1;	}  	while (count > 0) {		cnt = rme96xx_getispace(dma,hwp);				cnt>>=dma->formatshift;		cnt*=dma->inchannels;		if (cnt > count)			cnt = count;		if (cnt != 0) {		        			if (rme96xx_copytouser(dma,buffer,cnt,hop))				return ret ? ret : -EFAULT;						count -= cnt;			buffer += cnt;			ret += cnt;			if (count == 0) return ret;		}		if (file->f_flags & O_NONBLOCK)			return ret ? ret : -EAGAIN;				if ((hwp - dma->readptr) <= 0) {			interruptible_sleep_on(&(dma->wait));						if (signal_pending(current))				return ret ? ret : -ERESTARTSYS;		}					hwp = rme96xx_gethwptr(dma->s,exact);	}; /* count > 0 */	return ret;}static int rm96xx_mmap(struct file *file, struct vm_area_struct *vma) {	struct dmabuf *dma = (struct dmabuf *)file->private_data;	rme96xx_info* s = dma->s;	unsigned long size;	VALIDATE_STATE(s);	lock_kernel();	if (vma->vm_pgoff != 0) {		unlock_kernel();		return -EINVAL;	}	size = vma->vm_end - vma->vm_start;	if (size > RME96xx_DMA_MAX_SIZE) {		unlock_kernel();		return -EINVAL;	}	if (vma->vm_flags & VM_WRITE) {		if (!s->started) rme96xx_startcard(s,1);		if (remap_page_range(vma->vm_start, virt_to_phys(s->playbuf + dma->outoffset*RME96xx_DMA_MAX_SIZE), size, vma->vm_page_prot)) {			unlock_kernel();			return -EAGAIN;		}	} 	else if (vma->vm_flags & VM_READ) {		if (!s->started) rme96xx_startcard(s,1);		if (remap_page_range(vma->vm_start, virt_to_phys(s->playbuf + dma->inoffset*RME96xx_DMA_MAX_SIZE), size, vma->vm_page_prot)) {			unlock_kernel();			return -EAGAIN;		}	} else  {		unlock_kernel();		return -EINVAL;	}/* this is the mapping */	dma->mmapped = 1;	unlock_kernel();	return 0;}static unsigned int rme96xx_poll(struct file *file, struct poll_table_struct *wait){	struct dmabuf *dma = (struct dmabuf *)file->private_data;	rme96xx_info* s = dma->s;	unsigned int mask = 0;	unsigned int hwp,cnt;        DBG(printk("rme96xx poll_wait ...\n"));	VALIDATE_STATE(s);	if (!s->started) {		  mask |= POLLOUT | POLLWRNORM;	}	poll_wait(file, &dma->wait, wait);	hwp = rme96xx_gethwptr(dma->s,0);        DBG(printk("rme96xx poll: ..cnt %d > %d\n",cnt,s->fragsize));		cnt = rme96xx_getispace(dma,hwp);	if (file->f_mode & FMODE_READ) 	     if (cnt > 0)		  mask |= POLLIN | POLLRDNORM;	cnt = rme96xx_getospace(dma,hwp);	if (file->f_mode & FMODE_WRITE) 	     if (cnt > 0)		  mask |= POLLOUT | POLLWRNORM;//        printk("rme96xx poll_wait ...%d > %d\n",rme96xx_getospace(dma,hwp),rme96xx_getispace(dma,hwp));	return mask;}static struct file_operations rme96xx_audio_fops = {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	owner: THIS_MODULE,#endif	read: rme96xx_read,	write: rme96xx_write,	poll: rme96xx_poll,	ioctl: rme96xx_ioctl,  	mmap: rm96xx_mmap,	open: rme96xx_open,  	release: rme96xx_release };static int rme96xx_mixer_open(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct list_head *list;	rme96xx_info *s;	COMM  ("mixer open");	for (list = devs.next; ; list = list->next) {		if (list == &devs)			return -ENODEV;		s = list_entry(list, rme96xx_info, devs);		if (s->mixer== minor)			break;	}       	VALIDATE_STATE(s);	file->private_data = s;	COMM                       ("mixer opened")	return 0;}static int rme96xx_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	rme96xx_info *s = (rme96xx_info *)file->private_data;	u32 status;	status = readl(s->iobase + RME96xx_status_register);	VALIDATE_STATE(s);	if (cmd == SOUND_MIXER_PRIVATE1) {		rme_mixer mixer;		copy_from_user(&mixer,(void*)arg,sizeof(mixer));				if (file->f_mode & FMODE_WRITE) {		     s->dma[mixer.devnr].outoffset = mixer.o_offset;		     s->dma[mixer.devnr].inoffset = mixer.i_offset;		}		mixer.o_offset = s->dma[mixer.devnr].outoffset;		mixer.i_offset = s->dma[mixer.devnr].inoffset;		return copy_to_user((void *)arg, &mixer, sizeof(mixer)) ? -EFAULT : 0;	}	if (cmd == SOUND_MIXER_PRIVATE2) {		return put_user(status, (int *)arg);	}	if (cmd == SOUND_MIXER_PRIVATE3) {	     u32 control;	     copy_from_user(&control,(void*)arg,sizeof(control)); 	     if (file->f_mode & FMODE_WRITE) {		  s->control_register = control;		  writel(control,s->iobase + RME96xx_control_register);	     }	     return put_user(s->control_register, (int *)arg);	}	return -1;}static int rme96xx_mixer_release(struct inode *inode, struct file *file){	return 0;}static /*const*/ struct file_operations rme96xx_mixer_fops = {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	owner: THIS_MODULE,#endif	ioctl:		rme96xx_mixer_ioctl,	open:		rme96xx_mixer_open,	release:	rme96xx_mixer_release,};

⌨️ 快捷键说明

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