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

📄 cmpci.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		i = generic_hweight32(val);		for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {			if (!(val & (1 << i)))				continue;			if (!mixtable[i].rec) {				val &= ~(1 << i);				continue;			}			j |= mixtable[i].rec;		}		spin_lock_irqsave(&s->lock, flags);		wrmixer(s, DSP_MIX_ADCMIXIDX_L, j);		wrmixer(s, DSP_MIX_ADCMIXIDX_R, (j & 1) | (j>>1));		spin_unlock_irqrestore(&s->lock, flags);		return 0;	case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */		if (get_user(val, (int *)arg))			return -EFAULT;		for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {			if (!(val & (1 << i)))				continue;			if (!mixtable[i].play) {				val &= ~(1 << i);				continue;			}			j |= mixtable[i].play;		}		spin_lock_irqsave(&s->lock, flags);		frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, j);		spin_unlock_irqrestore(&s->lock, flags);		return 0;		default:		i = _IOC_NR(cmd);		if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)			return -EINVAL;		if (get_user(val, (int *)arg))			return -EFAULT;		l = val & 0xff;		r = (val >> 8) & 0xff;		if (l > 100)			l = 100;		if (r > 100)			r = 100;		spin_lock_irqsave(&s->lock, flags);		switch (mixtable[i].type) {		case MT_4:			if (l >= 10)				l -= 10;			if (r >= 10)				r -= 10;			frobindir(s, mixtable[i].left, 0xf0, l / 6);			frobindir(s, mixtable[i].right, 0xf0, l / 6);			break;		case MT_4MUTEMONO:			rl = (l < 4 ? 0 : (l - 5) / 3) & 31;			rr = (rl >> 2) & 7;			wrmixer(s, mixtable[i].left, rl<<3);			maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1);			break;					case MT_5MUTEMONO:			r = l;			rl = l < 4 ? 0 : (l - 5) / 3;			rr = rl >> 2; 			wrmixer(s, mixtable[i].left, rl<<3);			maskb(s->iobase + CODEC_CMI_MIXER2, ~0x0e, rr<<1);			break;						case MT_5MUTE:			rl = l < 4 ? 0 : (l - 5) / 3;			rr = r < 4 ? 0 : (r - 5) / 3; 			wrmixer(s, mixtable[i].left, rl<<3);			wrmixer(s, mixtable[i].right, rr<<3);			break;		case MT_6MUTE:			if (l < 6)				rl = 0x00;			else				rl = l * 2 / 3;			if (r < 6)				rr = 0x00;			else				rr = r * 2 / 3;			wrmixer(s, mixtable[i].left, rl);			wrmixer(s, mixtable[i].right, rr);			break;		}		spin_unlock_irqrestore(&s->lock, flags);		if (!volidx[i])			return -EINVAL;		s->mix.vol[volidx[i]-1] = val;		return put_user(s->mix.vol[volidx[i]-1], (int *)arg);	}}/* --------------------------------------------------------------------- */static int cm_open_mixdev(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct cm_state *s = devs;	while (s && s->dev_mixer != minor)		s = s->next;	if (!s)		return -ENODEV;       	VALIDATE_STATE(s);	file->private_data = s;	return 0;}static int cm_release_mixdev(struct inode *inode, struct file *file){	struct cm_state *s = (struct cm_state *)file->private_data;		VALIDATE_STATE(s);	return 0;}static int cm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	return mixer_ioctl((struct cm_state *)file->private_data, cmd, arg);}static /*const*/ struct file_operations cm_mixer_fops = {	owner:		THIS_MODULE,	llseek:		no_llseek,	ioctl:		cm_ioctl_mixdev,	open:		cm_open_mixdev,	release:	cm_release_mixdev,};/* --------------------------------------------------------------------- */static int drain_dac(struct cm_state *s, int nonblock){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	int count, tmo;	if (s->dma_dac.mapped || !s->dma_dac.ready)		return 0;        set_current_state(TASK_INTERRUPTIBLE);        add_wait_queue(&s->dma_dac.wait, &wait);        for (;;) {                spin_lock_irqsave(&s->lock, flags);		count = s->dma_dac.count;                spin_unlock_irqrestore(&s->lock, flags);		if (count <= 0)			break;		if (signal_pending(current))                        break;                if (nonblock) {                        remove_wait_queue(&s->dma_dac.wait, &wait);                        set_current_state(TASK_RUNNING);                        return -EBUSY;                }		tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;		tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK];		if (!schedule_timeout(tmo + 1))			printk(KERN_DEBUG "cmpci: dma timed out??\n");        }        remove_wait_queue(&s->dma_dac.wait, &wait);        set_current_state(TASK_RUNNING);        if (signal_pending(current))                return -ERESTARTSYS;        return 0;}/* --------------------------------------------------------------------- */static ssize_t cm_read(struct file *file, char *buffer, size_t count, loff_t *ppos){	struct cm_state *s = (struct cm_state *)file->private_data;	ssize_t ret;	unsigned long flags;	unsigned swptr;	int cnt;	VALIDATE_STATE(s);	if (ppos != &file->f_pos)		return -ESPIPE;	if (s->dma_adc.mapped)		return -ENXIO;	if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))		return ret;	if (!access_ok(VERIFY_WRITE, buffer, count))		return -EFAULT;	ret = 0;	while (count > 0) {		spin_lock_irqsave(&s->lock, flags);		swptr = s->dma_adc.swptr;		cnt = s->dma_adc.dmasize-swptr;		if (s->dma_adc.count < cnt)			cnt = s->dma_adc.count;		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			start_adc(s);			if (file->f_flags & O_NONBLOCK)				return ret ? ret : -EAGAIN;			if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {				printk(KERN_DEBUG "cmpci: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",				       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count,				       s->dma_adc.hwptr, s->dma_adc.swptr);				spin_lock_irqsave(&s->lock, flags);				stop_adc_unlocked(s);				set_dmaadc(s, s->dma_adc.rawphys, s->dma_adc.dmasamples);				/* program sample counts */				set_countadc(s, s->dma_adc.fragsamples);				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current))				return ret ? ret : -ERESTARTSYS;			continue;		}		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))			return ret ? ret : -EFAULT;		swptr = (swptr + cnt) % s->dma_adc.dmasize;		spin_lock_irqsave(&s->lock, flags);		s->dma_adc.swptr = swptr;		s->dma_adc.count -= cnt;		count -= cnt;		buffer += cnt;		ret += cnt;		start_adc_unlocked(s);		spin_unlock_irqrestore(&s->lock, flags);	}	return ret;}static ssize_t cm_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){	struct cm_state *s = (struct cm_state *)file->private_data;	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;	if (s->status & DO_DUAL_DAC) {		if (s->dma_adc.mapped)			return -ENXIO;		if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))			return ret;		if (!access_ok(VERIFY_READ, buffer, count))			return -EFAULT;	}	ret = 0;	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;		}		if (s->status & DO_DUAL_DAC) {			s->dma_adc.swptr = s->dma_dac.swptr;			s->dma_adc.count = s->dma_dac.count;			s->dma_adc.endcleared = s->dma_dac.endcleared;		}		swptr = s->dma_dac.swptr;		cnt = s->dma_dac.dmasize-swptr;		if (s->status & DO_AC3_SW) {			if (s->dma_dac.count + 2 * cnt > s->dma_dac.dmasize)				cnt = (s->dma_dac.dmasize - s->dma_dac.count) / 2;		} else {			if (s->dma_dac.count + cnt > s->dma_dac.dmasize)				cnt = s->dma_dac.dmasize - s->dma_dac.count;		}		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if ((s->status & DO_DUAL_DAC) && (cnt > count / 2))		    cnt = count / 2;		if (cnt <= 0) {			start_dac(s);			if (file->f_flags & O_NONBLOCK)				return ret ? ret : -EAGAIN;			if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {				printk(KERN_DEBUG "cmpci: 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);				spin_lock_irqsave(&s->lock, flags);				stop_dac_unlocked(s);				set_dmadac(s, s->dma_dac.rawphys, s->dma_dac.dmasamples);				/* program sample counts */				set_countdac(s, s->dma_dac.fragsamples);				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;				if (s->status & DO_DUAL_DAC)  {					set_dmadac1(s, s->dma_adc.rawphys, s->dma_adc.dmasamples);					s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;				}				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current))				return ret ? ret : -ERESTARTSYS;			continue;		}		if (s->status & DO_AC3_SW) {			// clip exceeded data, caught by 033 and 037			if (swptr + 2 * cnt > s->dma_dac.dmasize)				cnt = (s->dma_dac.dmasize - swptr) / 2;			trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt);			swptr = (swptr + 2 * cnt) % s->dma_dac.dmasize;		} else if (s->status & DO_DUAL_DAC) {			int	i;			unsigned long *src, *dst0, *dst1;			src = (unsigned long *) buffer;			dst0 = (unsigned long *) (s->dma_dac.rawbuf + swptr);			dst1 = (unsigned long *) (s->dma_adc.rawbuf + swptr);			// copy left/right sample at one time			for (i = 0; i <= cnt / 4; i++) {				*dst0++ = *src++;				*dst1++ = *src++;			}			swptr = (swptr + cnt) % s->dma_dac.dmasize;		} else {			if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))				return ret ? ret : -EFAULT;			swptr = (swptr + cnt) % s->dma_dac.dmasize;		}		spin_lock_irqsave(&s->lock, flags);		s->dma_dac.swptr = swptr;		s->dma_dac.count += cnt;		if (s->status & DO_AC3_SW)			s->dma_dac.count += cnt;		s->dma_dac.endcleared = 0;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		if (s->status & DO_DUAL_DAC) {			count -= cnt;			buffer += cnt;			ret += cnt;		}		start_dac(s);	}	return ret;}static unsigned int cm_poll(struct file *file, struct poll_table_struct *wait){	struct cm_state *s = (struct cm_state *)file->private_data;	unsigned long flags;	unsigned int mask = 0;	VALIDATE_STATE(s);	if (file->f_mode & FMODE_WRITE)		poll_wait(file, &s->dma_dac.wait, wait);	if (file->f_mode & FMODE_READ)		poll_wait(file, &s->dma_adc.wait, wait);	spin_lock_irqsave(&s->lock, flags);	cm_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 cm_mmap(struct file *file, struct vm_area_struct *vma){	struct cm_state *s = (struct cm_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, 0)) != 0)			goto out;		db = &s->dma_dac;	} else if (vma->vm_flags & VM_READ) {		if ((ret = prog_dmabuf(s, 1)) != 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 = -EINVAL;	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 cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct cm_state *s = (struct cm_state *)file->private_data;	unsigned long flags;        audio_buf_info abinfo;        count_info cinfo;	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;		

⌨️ 快捷键说明

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