swarm_cs4297a.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,962 行 · 第 1/5 页

C
1,962
字号
#if CSDEBUG	cs_printioctl(cmd);#endif#if CSDEBUG_INTERFACE	if ((cmd == SOUND_MIXER_CS_GETDBGMASK) ||	    (cmd == SOUND_MIXER_CS_SETDBGMASK) ||	    (cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||	    (cmd == SOUND_MIXER_CS_SETDBGLEVEL))	{		switch (cmd) {		case SOUND_MIXER_CS_GETDBGMASK:			return put_user(cs_debugmask,					(unsigned long *) arg);		case SOUND_MIXER_CS_GETDBGLEVEL:			return put_user(cs_debuglevel,					(unsigned long *) arg);		case SOUND_MIXER_CS_SETDBGMASK:			if (get_user(val, (unsigned long *) arg))				return -EFAULT;			cs_debugmask = val;			return 0;		case SOUND_MIXER_CS_SETDBGLEVEL:			if (get_user(val, (unsigned long *) arg))				return -EFAULT;			cs_debuglevel = val;			return 0;		default:			CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO				"cs4297a: mixer_ioctl(): ERROR unknown debug cmd\n"));			return 0;		}	}#endif	if (cmd == SOUND_MIXER_PRIVATE1) {                return -EINVAL;	}	if (cmd == SOUND_MIXER_PRIVATE2) {		// enable/disable/query spatializer 		if (get_user(val, (int *) arg))			return -EFAULT;		if (val != -1) {			temp1 = (val & 0x3f) >> 2;			cs4297a_write_ac97(s, AC97_3D_CONTROL, temp1);			cs4297a_read_ac97(s, AC97_GENERAL_PURPOSE,					 &temp1);			cs4297a_write_ac97(s, AC97_GENERAL_PURPOSE,					  temp1 | 0x2000);		}		cs4297a_read_ac97(s, AC97_3D_CONTROL, &temp1);		return put_user((temp1 << 2) | 3, (int *) arg);	}	if (cmd == SOUND_MIXER_INFO) {		mixer_info info;		memset(&info, 0, sizeof(info));		strlcpy(info.id, "CS4297a", sizeof(info.id));		strlcpy(info.name, "Crystal CS4297a", 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;		memset(&info, 0, sizeof(info));		strlcpy(info.id, "CS4297a", sizeof(info.id));		strlcpy(info.name, "Crystal CS4297a", 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 (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))		return -EINVAL;	// If ioctl has only the SIOC_READ bit(bit 31)	// on, process the only-read commands. 	if (_SIOC_DIR(cmd) == _SIOC_READ) {		switch (_IOC_NR(cmd)) {		case SOUND_MIXER_RECSRC:	// Arg contains a bit for each recording source 			cs4297a_read_ac97(s, AC97_RECORD_SELECT,					 &temp1);			return put_user(mixer_src[temp1 & 7], (int *) arg);		case SOUND_MIXER_DEVMASK:	// Arg contains a bit for each supported device 			return put_user(SOUND_MASK_PCM | SOUND_MASK_LINE |					SOUND_MASK_VOLUME | SOUND_MASK_RECLEV,                                        (int *) arg);		case SOUND_MIXER_RECMASK:	// Arg contains a bit for each supported recording source 			return put_user(SOUND_MASK_LINE | SOUND_MASK_VOLUME,                                        (int *) arg);		case SOUND_MIXER_STEREODEVS:	// Mixer channels supporting stereo 			return put_user(SOUND_MASK_PCM | SOUND_MASK_LINE |					SOUND_MASK_VOLUME | SOUND_MASK_RECLEV,                                        (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			    || !(vidx = mixtable1[i]))				return -EINVAL;			return put_user(s->mix.vol[vidx - 1], (int *) arg);		}	}	// If ioctl doesn't have both the SIOC_READ and 	// the SIOC_WRITE bit set, return invalid.	if (_SIOC_DIR(cmd) != (_SIOC_READ | _SIOC_WRITE))		return -EINVAL;	// Increment the count of volume writes.	s->mix.modcnt++;	// Isolate the command; it must be a write.	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);	// i = # bits on in val.		if (i != 1)	// One & only 1 bit must be on.			return 0;		for (i = 0; i < sizeof(mixer_src) / sizeof(int); i++) {			if (val == mixer_src[i]) {				temp1 = (i << 8) | i;				cs4297a_write_ac97(s,						  AC97_RECORD_SELECT,						  temp1);				return 0;			}		}		return 0;	case SOUND_MIXER_VOLUME:		if (get_user(val, (int *) arg))			return -EFAULT;		l = val & 0xff;		if (l > 100)			l = 100;	// Max soundcard.h vol is 100.		if (l < 6) {			rl = 63;			l = 0;		} else			rl = attentbl[(10 * l) / 100];	// Convert 0-100 vol to 63-0 atten.		r = (val >> 8) & 0xff;		if (r > 100)			r = 100;	// Max right volume is 100, too		if (r < 6) {			rr = 63;			r = 0;		} else			rr = attentbl[(10 * r) / 100];	// Convert volume to attenuation.		if ((rl > 60) && (rr > 60))	// If both l & r are 'low',          			temp1 = 0x8000;	//  turn on the mute bit.		else			temp1 = 0;		temp1 |= (rl << 8) | rr;		cs4297a_write_ac97(s, AC97_MASTER_VOL_STEREO, temp1);		cs4297a_write_ac97(s, AC97_PHONE_VOL, temp1);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS		s->mix.vol[8] = ((unsigned int) r << 8) | l;#else		s->mix.vol[8] = val;#endif		return put_user(s->mix.vol[8], (int *) arg);	case SOUND_MIXER_SPEAKER:		if (get_user(val, (int *) arg))			return -EFAULT;		l = val & 0xff;		if (l > 100)			l = 100;		if (l < 3) {			rl = 0;			l = 0;		} else {			rl = (l * 2 - 5) / 13;	// Convert 0-100 range to 0-15.			l = (rl * 13 + 5) / 2;		}		if (rl < 3) {			temp1 = 0x8000;			rl = 0;		} else			temp1 = 0;		rl = 15 - rl;	// Convert volume to attenuation.		temp1 |= rl << 1;		cs4297a_write_ac97(s, AC97_PCBEEP_VOL, temp1);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS		s->mix.vol[6] = l << 8;#else		s->mix.vol[6] = val;#endif		return put_user(s->mix.vol[6], (int *) arg);	case SOUND_MIXER_RECLEV:		if (get_user(val, (int *) arg))			return -EFAULT;		l = val & 0xff;		if (l > 100)			l = 100;		r = (val >> 8) & 0xff;		if (r > 100)			r = 100;		rl = (l * 2 - 5) / 13;	// Convert 0-100 scale to 0-15.		rr = (r * 2 - 5) / 13;		if (rl < 3 && rr < 3)			temp1 = 0x8000;		else			temp1 = 0;		temp1 = temp1 | (rl << 8) | rr;		cs4297a_write_ac97(s, AC97_RECORD_GAIN, temp1);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS		s->mix.vol[7] = ((unsigned int) r << 8) | l;#else		s->mix.vol[7] = val;#endif		return put_user(s->mix.vol[7], (int *) arg);	case SOUND_MIXER_MIC:		if (get_user(val, (int *) arg))			return -EFAULT;		l = val & 0xff;		if (l > 100)			l = 100;		if (l < 1) {			l = 0;			rl = 0;		} else {			rl = ((unsigned) l * 5 - 4) / 16;	// Convert 0-100 range to 0-31.			l = (rl * 16 + 4) / 5;		}		cs4297a_read_ac97(s, AC97_MIC_VOL, &temp1);		temp1 &= 0x40;	// Isolate 20db gain bit.		if (rl < 3) {			temp1 |= 0x8000;			rl = 0;		}		rl = 31 - rl;	// Convert volume to attenuation.		temp1 |= rl;		cs4297a_write_ac97(s, AC97_MIC_VOL, temp1);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS		s->mix.vol[5] = val << 8;#else		s->mix.vol[5] = val;#endif		return put_user(s->mix.vol[5], (int *) arg);	case SOUND_MIXER_SYNTH:		if (get_user(val, (int *) arg))			return -EFAULT;		l = val & 0xff;		if (l > 100)			l = 100;		if (get_user(val, (int *) arg))			return -EFAULT;		r = (val >> 8) & 0xff;		if (r > 100)			r = 100;		rl = (l * 2 - 11) / 3;	// Convert 0-100 range to 0-63.		rr = (r * 2 - 11) / 3;		if (rl < 3)	// If l is low, turn on			temp1 = 0x0080;	//  the mute bit.		else			temp1 = 0;		rl = 63 - rl;	// Convert vol to attenuation.//		writel(temp1 | rl, s->pBA0 + FMLVC);		if (rr < 3)	//  If rr is low, turn on			temp1 = 0x0080;	//   the mute bit.		else			temp1 = 0;		rr = 63 - rr;	// Convert vol to attenuation.//		writel(temp1 | rr, s->pBA0 + FMRVC);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS		s->mix.vol[4] = (r << 8) | l;#else		s->mix.vol[4] = val;#endif		return put_user(s->mix.vol[4], (int *) arg);	default:		CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO			"cs4297a: mixer_ioctl(): default\n"));		i = _IOC_NR(cmd);		if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))			return -EINVAL;		if (get_user(val, (int *) arg))			return -EFAULT;		l = val & 0xff;		if (l > 100)			l = 100;		if (l < 1) {			l = 0;			rl = 31;		} else			rl = (attentbl[(l * 10) / 100]) >> 1;		r = (val >> 8) & 0xff;		if (r > 100)			r = 100;		if (r < 1) {			r = 0;			rr = 31;		} else			rr = (attentbl[(r * 10) / 100]) >> 1;		if ((rl > 30) && (rr > 30))			temp1 = 0x8000;		else			temp1 = 0;		temp1 = temp1 | (rl << 8) | rr;		cs4297a_write_ac97(s, mixreg[vidx - 1], temp1);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS		s->mix.vol[vidx - 1] = ((unsigned int) r << 8) | l;#else		s->mix.vol[vidx - 1] = val;#endif		return put_user(s->mix.vol[vidx - 1], (int *) arg);	}}// --------------------------------------------------------------------- static int cs4297a_open_mixdev(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct cs4297a_state *s=NULL;	struct list_head *entry;	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,		  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));	list_for_each(entry, &cs4297a_devs)	{		s = list_entry(entry, struct cs4297a_state, list);		if(s->dev_mixer == minor)			break;	}	if (!s)	{		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,			printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));		return -ENODEV;	}	VALIDATE_STATE(s);	file->private_data = s;	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,		  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));	return nonseekable_open(inode, file);}static int cs4297a_release_mixdev(struct inode *inode, struct file *file){	struct cs4297a_state *s =	    (struct cs4297a_state *) file->private_data;	VALIDATE_STATE(s);	return 0;}static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file,			       unsigned int cmd, unsigned long arg){

⌨️ 快捷键说明

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