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

📄 sonicvibes.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
				spin_lock_irqsave(&s->lock, flags);				set_dmac(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.numfrag << s->dma_adc.fragshift);				/* program enhanced mode registers */				wrindir(s, SV_CIDMACBASECOUNT1, (s->dma_adc.fragsamples-1) >> 8);				wrindir(s, SV_CIDMACBASECOUNT0, s->dma_adc.fragsamples-1);				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				break;			}			continue;		}		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {			if (!ret)				ret = -EFAULT;			break;		}		swptr = (swptr + cnt) % s->dma_adc.dmasize;		spin_lock_irqsave(&s->lock, flags);		s->dma_adc.swptr = swptr;		s->dma_adc.count -= cnt;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		if (s->dma_adc.enabled)			start_adc(s);	}        remove_wait_queue(&s->dma_adc.wait, &wait);	set_current_state(TASK_RUNNING);	return ret;}static ssize_t sv_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){	struct sv_state *s = (struct sv_state *)file->private_data;	DECLARE_WAITQUEUE(wait, current);	ssize_t ret;	unsigned long flags;	unsigned swptr;	int cnt;	VALIDATE_STATE(s);	if (ppos != &file->f_pos)		return -ESPIPE;	if (s->dma_dac.mapped)		return -ENXIO;	if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))		return ret;	if (!access_ok(VERIFY_READ, buffer, count))		return -EFAULT;	ret = 0;#if 0	spin_lock_irqsave(&s->lock, flags);	sv_update_ptr(s);	spin_unlock_irqrestore(&s->lock, flags);#endif        add_wait_queue(&s->dma_dac.wait, &wait);	while (count > 0) {		spin_lock_irqsave(&s->lock, flags);		if (s->dma_dac.count < 0) {			s->dma_dac.count = 0;			s->dma_dac.swptr = s->dma_dac.hwptr;		}		swptr = s->dma_dac.swptr;		cnt = s->dma_dac.dmasize-swptr;		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)			cnt = s->dma_dac.dmasize - s->dma_dac.count;		if (cnt <= 0)			__set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			if (s->dma_dac.enabled)				start_dac(s);			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				break;			}			if (!schedule_timeout(HZ)) {				printk(KERN_DEBUG "sv: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",				       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, 				       s->dma_dac.hwptr, s->dma_dac.swptr);				stop_dac(s);				spin_lock_irqsave(&s->lock, flags);				set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.numfrag << s->dma_dac.fragshift);				/* program enhanced mode registers */				wrindir(s, SV_CIDMAABASECOUNT1, (s->dma_dac.fragsamples-1) >> 8);				wrindir(s, SV_CIDMAABASECOUNT0, s->dma_dac.fragsamples-1);				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				break;			}			continue;		}		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {			if (!ret)				ret = -EFAULT;			break;		}		swptr = (swptr + cnt) % s->dma_dac.dmasize;		spin_lock_irqsave(&s->lock, flags);		s->dma_dac.swptr = swptr;		s->dma_dac.count += cnt;		s->dma_dac.endcleared = 0;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		if (s->dma_dac.enabled)			start_dac(s);	}        remove_wait_queue(&s->dma_dac.wait, &wait);	set_current_state(TASK_RUNNING);	return ret;}/* No kernel lock - we have our own spinlock */static unsigned int sv_poll(struct file *file, struct poll_table_struct *wait){	struct sv_state *s = (struct sv_state *)file->private_data;	unsigned long flags;	unsigned int mask = 0;	VALIDATE_STATE(s);	if (file->f_mode & FMODE_WRITE) {		if (!s->dma_dac.ready && prog_dmabuf(s, 1))			return 0;		poll_wait(file, &s->dma_dac.wait, wait);	}	if (file->f_mode & FMODE_READ) {		if (!s->dma_adc.ready && prog_dmabuf(s, 0))			return 0;		poll_wait(file, &s->dma_adc.wait, wait);	}	spin_lock_irqsave(&s->lock, flags);	sv_update_ptr(s);	if (file->f_mode & FMODE_READ) {		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)			mask |= POLLIN | POLLRDNORM;	}	if (file->f_mode & FMODE_WRITE) {		if (s->dma_dac.mapped) {			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) 				mask |= POLLOUT | POLLWRNORM;		} else {			if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)				mask |= POLLOUT | POLLWRNORM;		}	}	spin_unlock_irqrestore(&s->lock, flags);	return mask;}static int sv_mmap(struct file *file, struct vm_area_struct *vma){	struct sv_state *s = (struct sv_state *)file->private_data;	struct dmabuf *db;	int ret = -EINVAL;	unsigned long size;	VALIDATE_STATE(s);	lock_kernel();	if (vma->vm_flags & VM_WRITE) {		if ((ret = prog_dmabuf(s, 1)) != 0)			goto out;		db = &s->dma_dac;	} else if (vma->vm_flags & VM_READ) {		if ((ret = prog_dmabuf(s, 0)) != 0)			goto out;		db = &s->dma_adc;	} else 		goto out;	ret = -EINVAL;	if (vma->vm_pgoff != 0)		goto out;	size = vma->vm_end - vma->vm_start;	if (size > (PAGE_SIZE << db->buforder))		goto out;	ret = -EAGAIN;	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))		goto out;	db->mapped = 1;	ret = 0;out:	unlock_kernel();	return ret;}static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct sv_state *s = (struct sv_state *)file->private_data;	unsigned long flags;        audio_buf_info abinfo;        count_info cinfo;	int count;	int val, mapped, ret;	unsigned char fmtm, fmtd;	VALIDATE_STATE(s);        mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||		((file->f_mode & FMODE_READ) && s->dma_adc.mapped);	switch (cmd) {	case OSS_GETVERSION:		return put_user(SOUND_VERSION, (int *)arg);	case SNDCTL_DSP_SYNC:		if (file->f_mode & FMODE_WRITE)			return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);		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:		if (file->f_mode & FMODE_WRITE) {			stop_dac(s);			synchronize_irq();			s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0;		}		if (file->f_mode & FMODE_READ) {			stop_adc(s);			synchronize_irq();			s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;		}		return 0;        case SNDCTL_DSP_SPEED:                if (get_user(val, (int *)arg))			return -EFAULT;		if (val >= 0) {			if (file->f_mode & FMODE_READ) {				stop_adc(s);				s->dma_adc.ready = 0;				set_adc_rate(s, val);			}			if (file->f_mode & FMODE_WRITE) {				stop_dac(s);				s->dma_dac.ready = 0;				set_dac_rate(s, val);			}		}		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);		        case SNDCTL_DSP_STEREO:                if (get_user(val, (int *)arg))			return -EFAULT;		fmtd = 0;		fmtm = ~0;		if (file->f_mode & FMODE_READ) {			stop_adc(s);			s->dma_adc.ready = 0;			if (val)				fmtd |= SV_CFMT_STEREO << SV_CFMT_CSHIFT;			else				fmtm &= ~(SV_CFMT_STEREO << SV_CFMT_CSHIFT);		}		if (file->f_mode & FMODE_WRITE) {			stop_dac(s);			s->dma_dac.ready = 0;			if (val)				fmtd |= SV_CFMT_STEREO << SV_CFMT_ASHIFT;			else				fmtm &= ~(SV_CFMT_STEREO << SV_CFMT_ASHIFT);		}		set_fmt(s, fmtm, fmtd);		return 0;        case SNDCTL_DSP_CHANNELS:                if (get_user(val, (int *)arg))			return -EFAULT;		if (val != 0) {			fmtd = 0;			fmtm = ~0;			if (file->f_mode & FMODE_READ) {				stop_adc(s);				s->dma_adc.ready = 0;				if (val >= 2)					fmtd |= SV_CFMT_STEREO << SV_CFMT_CSHIFT;				else					fmtm &= ~(SV_CFMT_STEREO << SV_CFMT_CSHIFT);			}			if (file->f_mode & FMODE_WRITE) {				stop_dac(s);				s->dma_dac.ready = 0;				if (val >= 2)					fmtd |= SV_CFMT_STEREO << SV_CFMT_ASHIFT;				else					fmtm &= ~(SV_CFMT_STEREO << SV_CFMT_ASHIFT);			}			set_fmt(s, fmtm, fmtd);		}		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (SV_CFMT_STEREO << SV_CFMT_CSHIFT) 					   : (SV_CFMT_STEREO << SV_CFMT_ASHIFT))) ? 2 : 1, (int *)arg);			case SNDCTL_DSP_GETFMTS: /* Returns a mask */                return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);			case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/		if (get_user(val, (int *)arg))			return -EFAULT;		if (val != AFMT_QUERY) {			fmtd = 0;			fmtm = ~0;			if (file->f_mode & FMODE_READ) {				stop_adc(s);				s->dma_adc.ready = 0;				if (val == AFMT_S16_LE)					fmtd |= SV_CFMT_16BIT << SV_CFMT_CSHIFT;				else					fmtm &= ~(SV_CFMT_16BIT << SV_CFMT_CSHIFT);			}			if (file->f_mode & FMODE_WRITE) {				stop_dac(s);				s->dma_dac.ready = 0;				if (val == AFMT_S16_LE)					fmtd |= SV_CFMT_16BIT << SV_CFMT_ASHIFT;				else					fmtm &= ~(SV_CFMT_16BIT << SV_CFMT_ASHIFT);			}			set_fmt(s, fmtm, fmtd);		}		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (SV_CFMT_16BIT << SV_CFMT_CSHIFT) 					   : (SV_CFMT_16BIT << SV_CFMT_ASHIFT))) ? AFMT_S16_LE : AFMT_U8, (int *)arg);			case SNDCTL_DSP_POST:                return 0;        case SNDCTL_DSP_GETTRIGGER:		val = 0;		if (file->f_mode & FMODE_READ && s->enable & SV_CENABLE_RE) 			val |= PCM_ENABLE_INPUT;		if (file->f_mode & FMODE_WRITE && s->enable & SV_CENABLE_PE) 			val |= PCM_ENABLE_OUTPUT;		return put_user(val, (int *)arg);			case SNDCTL_DSP_SETTRIGGER:		if (get_user(val, (int *)arg))			return -EFAULT;		if (file->f_mode & FMODE_READ) {			if (val & PCM_ENABLE_INPUT) {				if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))					return ret;				s->dma_adc.enabled = 1;				start_adc(s);			} else {				s->dma_adc.enabled = 0;				stop_adc(s);			}		}		if (file->f_mode & FMODE_WRITE) {			if (val & PCM_ENABLE_OUTPUT) {				if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))					return ret;				s->dma_dac.enabled = 1;				start_dac(s);			} else {				s->dma_dac.enabled = 0;				stop_dac(s);			}		}		return 0;	case SNDCTL_DSP_GETOSPACE:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)			return val;		spin_lock_irqsave(&s->lock, flags);		sv_update_ptr(s);		abinfo.fragsize = s->dma_dac.fragsize;		count = s->dma_dac.count;		if (count < 0)			count = 0;                abinfo.bytes = s->dma_dac.dmasize - count;                abinfo.fragstotal = s->dma_dac.numfrag;                abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      		spin_unlock_irqrestore(&s->lock, flags);		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;	case SNDCTL_DSP_GETISPACE:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0)			return val;		spin_lock_irqsave(&s->lock, flags);		sv_update_ptr(s);		abinfo.fragsize = s->dma_adc.fragsize;		count = s->dma_adc.count;		if (count < 0)			count = 0;                abinfo.bytes = count;                abinfo.fragstotal = s->dma_adc.numfrag;                abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      		spin_unlock_irqrestore(&s->lock, flags);		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:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)			return val;		spin_lock_irqsave(&s->lock, flags);		sv_update_ptr(s);                count = s->dma_dac.count;		spin_unlock_irqrestore(&s->lock, flags);		if (count < 0)			count = 0;		return put_user(count, (int *)arg);        case SNDCTL_DSP_GETIPTR:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0)			return val;		spin_lock_irqsave(&s->lock, flags);		sv_update_ptr(s);                cinfo.bytes = s->dma_adc.total_bytes;		count = s->dma_adc.count;		if (count < 0)			count = 0;                cinfo.blocks = count >> s->dma_adc.fragshift;                cinfo.ptr = s->dma_adc.hwptr;		if (s->dma_adc.mapped)			s->dma_adc.count &= s->dma_adc.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_WRITE))			return -EINVAL;		if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)			return val;		spin_lock_irqsave(&s->lock, flags);		sv_update_ptr(s);                cinfo.bytes = s->dma_dac.total_bytes;		count = s->dma_dac.count;		if (count < 0)

⌨️ 快捷键说明

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