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

📄 cs4281.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			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;				cs4281_write_ac97(s,						  BA0_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;		cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, temp1);		cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, 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;		cs4281_write_ac97(s, BA0_AC97_PC_BEEP_VOLUME, 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;		cs4281_write_ac97(s, BA0_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;		}		cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);		temp1 &= 0x40;	// Isolate 20db gain bit.		if (rl < 3) {			temp1 |= 0x8000;			rl = 0;		}		rl = 31 - rl;	// Convert volume to attenuation.		temp1 |= rl;		cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, 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 + BA0_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 + BA0_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					      "cs4281: 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;		cs4281_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 loff_t cs4281_llseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}// --------------------------------------------------------------------- static int cs4281_open_mixdev(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct cs4281_state *s = devs;	while (s && s->dev_mixer != minor)		s = s->next;	if (!s)		return -ENODEV;	VALIDATE_STATE(s);	file->private_data = s;	MOD_INC_USE_COUNT;	return 0;}static int cs4281_release_mixdev(struct inode *inode, struct file *file){	struct cs4281_state *s =	    (struct cs4281_state *) file->private_data;	VALIDATE_STATE(s);	MOD_DEC_USE_COUNT;	return 0;}static int cs4281_ioctl_mixdev(struct inode *inode, struct file *file,			       unsigned int cmd, unsigned long arg){	return mixer_ioctl((struct cs4281_state *) file->private_data, cmd,			   arg);}// ******************************************************************************************//   Mixer file operations struct.// ******************************************************************************************static /*const */ struct file_operations cs4281_mixer_fops = {	llseek:cs4281_llseek,	ioctl:cs4281_ioctl_mixdev,	open:cs4281_open_mixdev,	release:cs4281_release_mixdev,};// --------------------------------------------------------------------- static int drain_adc(struct cs4281_state *s, int nonblock){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	int count;	unsigned tmo;	if (s->dma_adc.mapped)		return 0;	add_wait_queue(&s->dma_adc.wait, &wait);	for (;;) {		set_current_state(TASK_INTERRUPTIBLE);		spin_lock_irqsave(&s->lock, flags);		count = s->dma_adc.count;		CS_DBGOUT(CS_FUNCTION, 2,			  printk(KERN_INFO "cs4281: drain_adc() %d\n",				 count));		spin_unlock_irqrestore(&s->lock, flags);		if (count <= 0) {			CS_DBGOUT(CS_FUNCTION, 2,				  printk(KERN_INFO					 "cs4281: drain_adc() count<0\n"));			break;		}		if (signal_pending(current))			break;		if (nonblock) {			remove_wait_queue(&s->dma_adc.wait, &wait);			current->state = TASK_RUNNING;			return -EBUSY;		}		tmo =		    3 * HZ * (count +			      s->dma_adc.fragsize) / 2 / s->prop_adc.rate;		if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE))			tmo >>= 1;		if (s->prop_adc.channels > 1)			tmo >>= 1;		if (!schedule_timeout(tmo + 1))			printk(KERN_DEBUG "cs4281: dma timed out??\n");	}	remove_wait_queue(&s->dma_adc.wait, &wait);	current->state = TASK_RUNNING;	if (signal_pending(current))		return -ERESTARTSYS;	return 0;}static int drain_dac(struct cs4281_state *s, int nonblock){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	int count;	unsigned tmo;	if (s->dma_dac.mapped)		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);			current->state = TASK_RUNNING;			return -EBUSY;		}		tmo =		    3 * HZ * (count +			      s->dma_dac.fragsize) / 2 / s->prop_dac.rate;		if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE))			tmo >>= 1;		if (s->prop_dac.channels > 1)			tmo >>= 1;		if (!schedule_timeout(tmo + 1))			printk(KERN_DEBUG "cs4281: dma timed out??\n");	}	remove_wait_queue(&s->dma_dac.wait, &wait);	current->state = TASK_RUNNING;	if (signal_pending(current))		return -ERESTARTSYS;	return 0;}//****************************************************************************//// CopySamples copies 16-bit stereo samples from the source to the// destination, possibly converting down to either 8-bit or mono or both.// count specifies the number of output bytes to write.////  Arguments:////  dst             - Pointer to a destination buffer.//  src             - Pointer to a source buffer//  count           - The number of bytes to copy into the destination buffer.//  iChannels       - Stereo - 2//                    Mono   - 1//  fmt             - AFMT_xxx (soundcard.h formats)//// NOTES: only call this routine for conversion to 8bit from 16bit////****************************************************************************static void CopySamples(char *dst, char *src, int count, int iChannels,			unsigned fmt){	unsigned short *psSrc;	long lAudioSample;	CS_DBGOUT(CS_FUNCTION, 2,		  printk(KERN_INFO "cs4281: CopySamples()+ "));	CS_DBGOUT(CS_WAVE_READ, 8,		  printk(KERN_INFO			 " dst=0x%x src=0x%x count=%d iChannels=%d fmt=0x%x\n",			 (unsigned) dst, (unsigned) src, (unsigned) count,			 (unsigned) iChannels, (unsigned) fmt));	// Gershwin does format conversion in hardware so normally	// we don't do any host based coversion. The data formatter	// truncates 16 bit data to 8 bit and that causes some hiss.	// We have already forced the HW to do 16 bit sampling and 	// 2 channel so that we can use software to round instead 	// of truncate	//	// See if the data should be output as 8-bit unsigned stereo.	//	if ((iChannels == 2) && (fmt & AFMT_U8)) {		//		// Convert each 16-bit unsigned stereo sample to 8-bit unsigned 		//

⌨️ 快捷键说明

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