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

📄 sonicvibes.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		return;	spin_lock(&s->lock);	sv_update_ptr(s);	sv_handle_midi(s);	spin_unlock(&s->lock);}static void sv_midi_timer(unsigned long data){	struct sv_state *s = (struct sv_state *)data;	unsigned long flags;		spin_lock_irqsave(&s->lock, flags);	sv_handle_midi(s);	spin_unlock_irqrestore(&s->lock, flags);	s->midi.timer.expires = jiffies+1;	add_timer(&s->midi.timer);}/* --------------------------------------------------------------------- */static const char invalid_magic[] = KERN_CRIT "sv: invalid magic value\n";#define VALIDATE_STATE(s)                         \({                                                \	if (!(s) || (s)->magic != SV_MAGIC) { \		printk(invalid_magic);            \		return -ENXIO;                    \	}                                         \})/* --------------------------------------------------------------------- */#define MT_4          1#define MT_5MUTE      2#define MT_4MUTEMONO  3#define MT_6MUTE      4static const struct {	unsigned left:5;	unsigned right:5;	unsigned type:3;	unsigned rec:3;} mixtable[SOUND_MIXER_NRDEVICES] = {	[SOUND_MIXER_RECLEV] = { SV_CIMIX_ADCINL,    SV_CIMIX_ADCINR,    MT_4,         0 },	[SOUND_MIXER_LINE1]  = { SV_CIMIX_AUX1INL,   SV_CIMIX_AUX1INR,   MT_5MUTE,     5 },	[SOUND_MIXER_CD]     = { SV_CIMIX_CDINL,     SV_CIMIX_CDINR,     MT_5MUTE,     1 },	[SOUND_MIXER_LINE]   = { SV_CIMIX_LINEINL,   SV_CIMIX_LINEINR,   MT_5MUTE,     4 },	[SOUND_MIXER_MIC]    = { SV_CIMIX_MICIN,     SV_CIMIX_ADCINL,    MT_4MUTEMONO, 6 },	[SOUND_MIXER_SYNTH]  = { SV_CIMIX_SYNTHINL,  SV_CIMIX_SYNTHINR,  MT_5MUTE,     2 },	[SOUND_MIXER_LINE2]  = { SV_CIMIX_AUX2INL,   SV_CIMIX_AUX2INR,   MT_5MUTE,     3 },	[SOUND_MIXER_VOLUME] = { SV_CIMIX_ANALOGINL, SV_CIMIX_ANALOGINR, MT_5MUTE,     7 },	[SOUND_MIXER_PCM]    = { SV_CIMIX_PCMINL,    SV_CIMIX_PCMINR,    MT_6MUTE,     0 }};#ifdef OSS_DOCUMENTED_MIXER_SEMANTICSstatic int return_mixval(struct sv_state *s, unsigned i, int *arg){	unsigned long flags;	unsigned char l, r, rl, rr;	spin_lock_irqsave(&s->lock, flags);	l = rdindir(s, mixtable[i].left);	r = rdindir(s, mixtable[i].right);	spin_unlock_irqrestore(&s->lock, flags);	switch (mixtable[i].type) {	case MT_4:		r &= 0xf;		l &= 0xf;		rl = 10 + 6 * (l & 15);		rr = 10 + 6 * (r & 15);		break;	case MT_4MUTEMONO:		rl = 55 - 3 * (l & 15);		if (r & 0x10)			rl += 45;		rr = rl;		r = l;		break;	case MT_5MUTE:	default:		rl = 100 - 3 * (l & 31);		rr = 100 - 3 * (r & 31);		break;					case MT_6MUTE:		rl = 100 - 3 * (l & 63) / 2;		rr = 100 - 3 * (r & 63) / 2;		break;	}	if (l & 0x80)		rl = 0;	if (r & 0x80)		rr = 0;	return put_user((rr << 8) | rl, arg);}#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = {	[SOUND_MIXER_RECLEV] = 1,	[SOUND_MIXER_LINE1]  = 2,	[SOUND_MIXER_CD]     = 3,	[SOUND_MIXER_LINE]   = 4,	[SOUND_MIXER_MIC]    = 5,	[SOUND_MIXER_SYNTH]  = 6,	[SOUND_MIXER_LINE2]  = 7,	[SOUND_MIXER_VOLUME] = 8,	[SOUND_MIXER_PCM]    = 9};#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */static unsigned mixer_recmask(struct sv_state *s){	unsigned long flags;	int i, j;	spin_lock_irqsave(&s->lock, flags);	j = rdindir(s, SV_CIMIX_ADCINL) >> 5;	spin_unlock_irqrestore(&s->lock, flags);	j &= 7;	for (i = 0; i < SOUND_MIXER_NRDEVICES && mixtable[i].rec != j; i++);	return 1 << i;}static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg){	unsigned long flags;	int i, val;	unsigned char l, r, rl, rr;	VALIDATE_STATE(s);        if (cmd == SOUND_MIXER_INFO) {		mixer_info info;		strncpy(info.id, "SonicVibes", sizeof(info.id));		strncpy(info.name, "S3 SonicVibes", sizeof(info.name));		info.modify_counter = s->mix.modcnt;		if (copy_to_user((void *)arg, &info, sizeof(info)))			return -EFAULT;		return 0;	}	if (cmd == SOUND_OLD_MIXER_INFO) {		_old_mixer_info info;		strncpy(info.id, "SonicVibes", sizeof(info.id));		strncpy(info.name, "S3 SonicVibes", sizeof(info.name));		if (copy_to_user((void *)arg, &info, sizeof(info)))			return -EFAULT;		return 0;	}	if (cmd == OSS_GETVERSION)		return put_user(SOUND_VERSION, (int *)arg);	if (cmd == SOUND_MIXER_PRIVATE1) {  /* SRS settings */		if (get_user(val, (int *)arg))			return -EFAULT;		spin_lock_irqsave(&s->lock, flags);		if (val & 1) {			if (val & 2) {				l = 4 - ((val >> 2) & 7);				if (l & ~3)					l = 4;				r = 4 - ((val >> 5) & 7);				if (r & ~3)					r = 4;				wrindir(s, SV_CISRSSPACE, l);				wrindir(s, SV_CISRSCENTER, r);			} else				wrindir(s, SV_CISRSSPACE, 0x80);		}		l = rdindir(s, SV_CISRSSPACE);		r = rdindir(s, SV_CISRSCENTER);		spin_unlock_irqrestore(&s->lock, flags);		if (l & 0x80)			return put_user(0, (int *)arg);		return put_user(((4 - (l & 7)) << 2) | ((4 - (r & 7)) << 5) | 2, (int *)arg);	}	if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))                return -EINVAL;        if (_SIOC_DIR(cmd) == _SIOC_READ) {                switch (_IOC_NR(cmd)) {                case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */			return put_user(mixer_recmask(s), (int *)arg);			                case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)				if (mixtable[i].type)					val |= 1 << i;			return put_user(val, (int *)arg);                case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)				if (mixtable[i].rec)					val |= 1 << i;			return put_user(val, (int *)arg);			                case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)				if (mixtable[i].type && mixtable[i].type != MT_4MUTEMONO)					val |= 1 << i;			return put_user(val, (int *)arg);			                case SOUND_MIXER_CAPS:			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);		default:			i = _IOC_NR(cmd);                        if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)                                return -EINVAL;#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS			return return_mixval(s, i, (int *)arg);#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */			if (!volidx[i])				return -EINVAL;			return put_user(s->mix.vol[volidx[i]-1], (int *)arg);#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */		}	}        if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) 		return -EINVAL;	s->mix.modcnt++;	switch (_IOC_NR(cmd)) {	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */		if (get_user(val, (int *)arg))			return -EFAULT;		i = hweight32(val);		if (i == 0)			return 0; /*val = mixer_recmask(s);*/		else if (i > 1) 			val &= ~mixer_recmask(s);		for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {			if (!(val & (1 << i)))				continue;			if (mixtable[i].rec)				break;		}		if (!mixtable[i].rec)			return 0;		spin_lock_irqsave(&s->lock, flags);		frobindir(s, SV_CIMIX_ADCINL, 0x1f, mixtable[i].rec << 5);		frobindir(s, SV_CIMIX_ADCINR, 0x1f, mixtable[i].rec << 5);		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 (mixtable[i].type == MT_4MUTEMONO)			l = (r + l) / 2;		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:			rr = 0;			if (l < 10)				rl = 0x80;			else {				if (l >= 55) {					rr = 0x10;					l -= 45;				}				rl = (55 - l) / 3;			}			wrindir(s, mixtable[i].left, rl);			frobindir(s, mixtable[i].right, ~0x10, rr);			break;					case MT_5MUTE:			if (l < 7)				rl = 0x80;			else				rl = (100 - l) / 3;			if (r < 7)				rr = 0x80;			else				rr = (100 - r) / 3;			wrindir(s, mixtable[i].left, rl);			wrindir(s, mixtable[i].right, rr);			break;						case MT_6MUTE:			if (l < 6)				rl = 0x80;			else				rl = (100 - l) * 2 / 3;			if (r < 6)				rr = 0x80;			else				rr = (100 - r) * 2 / 3;			wrindir(s, mixtable[i].left, rl);			wrindir(s, mixtable[i].right, rr);			break;		}		spin_unlock_irqrestore(&s->lock, flags);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS                return return_mixval(s, i, (int *)arg);#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */		if (!volidx[i])			return -EINVAL;		s->mix.vol[volidx[i]-1] = val;		return put_user(s->mix.vol[volidx[i]-1], (int *)arg);#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */	}}/* --------------------------------------------------------------------- */static int sv_open_mixdev(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct list_head *list;	struct sv_state *s;	for (list = devs.next; ; list = list->next) {		if (list == &devs)			return -ENODEV;		s = list_entry(list, struct sv_state, devs);		if (s->dev_mixer == minor)			break;	}       	VALIDATE_STATE(s);	file->private_data = s;	return 0;}static int sv_release_mixdev(struct inode *inode, struct file *file){	struct sv_state *s = (struct sv_state *)file->private_data;		VALIDATE_STATE(s);	return 0;}static int sv_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	return mixer_ioctl((struct sv_state *)file->private_data, cmd, arg);}static /*const*/ struct file_operations sv_mixer_fops = {	owner:		THIS_MODULE,	llseek:		no_llseek,	ioctl:		sv_ioctl_mixdev,	open:		sv_open_mixdev,	release:	sv_release_mixdev,};/* --------------------------------------------------------------------- */static int drain_dac(struct sv_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;        add_wait_queue(&s->dma_dac.wait, &wait);        for (;;) {		__set_current_state(TASK_INTERRUPTIBLE);                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 >> SV_CFMT_ASHIFT) & SV_CFMT_MASK];		if (!schedule_timeout(tmo + 1))			printk(KERN_DEBUG "sv: 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 sv_read(struct file *file, 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_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;#if 0	spin_lock_irqsave(&s->lock, flags);	sv_update_ptr(s);	spin_unlock_irqrestore(&s->lock, flags);#endif        add_wait_queue(&s->dma_adc.wait, &wait);	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;		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_adc.enabled)				start_adc(s);			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				break;			}			if (!schedule_timeout(HZ)) {				printk(KERN_DEBUG "sv: 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);				stop_adc(s);

⌨️ 快捷键说明

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