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

📄 mixer.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
	l2 = i & 0xff;	r2 = (i >> 8) & 0xff;	i = card->arrwVol[volidx[SOUND_MIXER_PCM]];	l3 = i & 0xff;	r3 = (i >> 8) & 0xff;	i = card->arrwVol[volidx[SOUND_MIXER_DIGITAL1]];	l4 = i & 0xff;	r4 = (i >> 8) & 0xff;	i = (r1 * r2) / 50;	if (r2 > 50)		r2 = 2 * r1 - i;	else {		r2 = r1;		r1 = i;	}	i = (l1 * l2) / 50;	if (l2 > 50)		l2 = 2 * l1 - i;	else {		l2 = l1;		l1 = i;	}	for (i = 0; i < 36; i++) {		if (card->digmix[i] != DM_MUTE) {			if (((i >= 0) && (i < 4)) || ((i >= 18) && (i < 22)))				j = (i & 1) ? ((u64) db_table[r1] * (u64) db_table[r3]) : ((u64) db_table[l1] * (u64) db_table[l3]);			else if ((i == 6) || (i == 7) || (i == 24) || (i == 25))				j = (i & 1) ? ((u64) db_table[r1] * (u64) db_table[r4]) : ((u64) db_table[l1] * (u64) db_table[l4]);			else				j = ((i & 1) ? db_table[r1] : db_table[l1]) << 31;			card->digmix[i] = j >> 31;			sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, card->digmix[i]);		}	}	for (i = 72; i < 90; i++) {		if (card->digmix[i] != DM_MUTE) {			if ((i >= 72) && (i < 76))				j = (i & 1) ? ((u64) db_table[r2] * (u64) db_table[r3]) : ((u64) db_table[l2] * (u64) db_table[l3]);			else if ((i == 78) || (i == 79))				j = (i & 1) ? ((u64) db_table[r2] * (u64) db_table[r4]) : ((u64) db_table[l2] * (u64) db_table[l4]);			else				j = ((i & 1) ? db_table[r2] : db_table[l2]) << 31;			card->digmix[i] = j >> 31;			sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, card->digmix[i]);		}	}	for (i = 36; i <= 90; i += 18) {		if (i != 72) {			for (k = 0; k < 4; k++)				if (card->digmix[i + k] != DM_MUTE) {					card->digmix[i + k] = db_table[l3];					sblive_writeptr(card, FXGPREGBASE + 0x10 + i + k, 0, card->digmix[i + k]);				}			if (card->digmix[i + 6] != DM_MUTE) {				card->digmix[i + 6] = db_table[l4];				sblive_writeptr(card, FXGPREGBASE + 0x10 + i + 6, 0, card->digmix[i + 6]);			}			if (card->digmix[i + 7] != DM_MUTE) {				card->digmix[i + 7] = db_table[r4];				sblive_writeptr(card, FXGPREGBASE + 0x10 + i + 7, 0, card->digmix[i + 7]);			}		}	}}#ifdef PRIVATE_PCM_VOLUME/* calc & set attenuation factor for given channel */static int set_pcm_attn(struct emu10k1_card *card, int ch, int l){#ifndef PCMLEVEL#define PCMLEVEL 110		/* almost silence */#endif	int vol = IFATN_ATTENUATION_MASK;	/* silence */	if (l > 0)		vol = (PCMLEVEL - (l * PCMLEVEL + 50) / 100);	sblive_writeptr(card, IFATN, ch, IFATN_FILTERCUTOFF_MASK | vol);	DPD(2, "SOUND_MIXER_PCM: channel:%d  level:%d  attn:%d\n", ch, l, vol);	return vol;#undef PCMLEVEL}/* update value of local PCM volume level (using channel attenuation) * * return 1: in case its local change *        0: if the current process doesn't have entry in table *	     (it means this process have not opened audio (mixer usually) */static int update_pcm_attn(struct emu10k1_card *card, unsigned l1, unsigned r1){	int i;	int mixer = (r1 << 8) | l1;	for (i = 0; i < MAX_PCM_CHANNELS; i++) {		if (sblive_pcm_volume[i].files == current->files) {			sblive_pcm_volume[i].mixer = pcm_last_mixer = mixer;			if (sblive_pcm_volume[i].opened) {				if (sblive_pcm_volume[i].channel_r < NUM_G) {					sblive_pcm_volume[i].attn_r = set_pcm_attn(card, sblive_pcm_volume[i].channel_r, r1);					if (sblive_pcm_volume[i].channel_l < NUM_G)						sblive_pcm_volume[i].attn_l = set_pcm_attn(card, sblive_pcm_volume[i].channel_l, l1);				} else {					/* mono voice */					if (sblive_pcm_volume[i].channel_l < NUM_G)						sblive_pcm_volume[i].attn_l =						    set_pcm_attn(card, sblive_pcm_volume[i].channel_l, (l1 >= r1) ? l1 : r1);						/* to correctly handle mono voice here we would need						   to go into stereo mode and move the voice to the right & left						   looks a bit overcomplicated... */				}			}			return 1;		}	}	card->arrwVol[volidx[SOUND_MIXER_PCM]] = mixer;	return 0;}#endifint emu10k1_mixer_wrch(struct emu10k1_card *card, unsigned int ch, int val){	int i;	unsigned l1, r1;	u16 wval;	l1 = val & 0xff;	r1 = (val >> 8) & 0xff;	if (l1 > 100)		l1 = 100;	if (r1 > 100)		r1 = 100;	DPD(4, "emu10k1_mixer_wrch() called: ch=%u, l1=%u, r1=%u\n", ch, l1, r1);	if (!volidx[ch])		return -EINVAL;#ifdef PRIVATE_PCM_VOLUME	if (ch != SOUND_MIXER_PCM)#endif		card->arrwVol[volidx[ch]] = (r1 << 8) | l1;	switch (ch) {	case SOUND_MIXER_VOLUME:		DPF(4, "SOUND_MIXER_VOLUME:\n");		if (card->isaps)			aps_update_digital(card);		else			update_digital(card);		return 0;	case SOUND_MIXER_PCM:		DPF(4, "SOUND_MIXER_PCM\n");#ifdef PRIVATE_PCM_VOLUME		if (update_pcm_attn(card, l1, r1))			return 0;#endif		if (card->isaps)			aps_update_digital(card);		else			update_digital(card);		return 0;#ifdef TONE_CONTROL	case SOUND_MIXER_TREBLE:                DPF(4, "SOUND_MIXER_TREBLE:\n");                set_treble(card, l1, r1);                return 0;        case SOUND_MIXER_BASS:                DPF(4, "SOUND_MIXER_BASS:\n");                set_bass(card, l1, r1);		return 0;#endif	default:		break;	}	if (card->isaps)		return -EINVAL;	switch (ch) {	case SOUND_MIXER_DIGITAL1:	case SOUND_MIXER_LINE3:		DPD(4, "SOUND_MIXER_%s:\n", (ch == SOUND_MIXER_DIGITAL1) ? "DIGITAL1" : "LINE3");		update_digital(card);		return 0;	case SOUND_MIXER_DIGITAL2:	case SOUND_MIXER_LINE2:	case SOUND_MIXER_LINE1:	case SOUND_MIXER_LINE:	case SOUND_MIXER_CD:		DPD(4, "SOUND_MIXER_%s:\n",		    (ch == SOUND_MIXER_LINE1) ? "LINE1" :		    (ch == SOUND_MIXER_LINE2) ? "LINE2" : (ch == SOUND_MIXER_LINE) ? "LINE" : (ch == SOUND_MIXER_DIGITAL2) ? "DIGITAL2" : "CD");		wval = ((((100 - l1) * 32 + 50) / 100) << 8) | (((100 - r1) * 32 + 50) / 100);		if (wval == 0x2020)			wval = 0x8000;		else			wval -= ((wval & 0x2020) / 0x20);		sblive_writeac97(card, volreg[ch], wval);		return 0;	case SOUND_MIXER_OGAIN:	case SOUND_MIXER_PHONEIN:		DPD(4, "SOUND_MIXER_%s:\n", (ch == SOUND_MIXER_PHONEIN) ? "PHONEIN" : "OGAIN");		sblive_writeac97(card, volreg[ch], (l1 < 2) ? 0x8000 : ((100 - l1) * 32 + 50) / 100);		return 0;	case SOUND_MIXER_SPEAKER:		DPF(4, "SOUND_MIXER_SPEAKER:\n");		sblive_writeac97(card, volreg[ch], (l1 < 4) ? 0x8000 : (((100 - l1) * 16 + 50) / 100) << 1);		return 0;	case SOUND_MIXER_MIC:		DPF(4, "SOUND_MIXER_MIC:\n");		i = 0;		if (l1 >= 30)			/* 20dB / (34.5dB + 12dB + 20dB) * 100 = 30 */		{			l1 -= 30;			i = 0x40;		}		sblive_writeac97(card, volreg[ch], (l1 < 2) ? 0x8000 : ((((70 - l1) * 0x20 + 35) / 70) | i));		return 0;	case SOUND_MIXER_RECLEV:		DPF(4, "SOUND_MIXER_RECLEV:\n");		wval = (((l1 * 16 + 50) / 100) << 8) | ((r1 * 16 + 50) / 100);		if (wval == 0)			wval = 0x8000;		else {			if (wval & 0xff)				wval--;			if (wval & 0xff00)				wval -= 0x0100;		}		sblive_writeac97(card, volreg[ch], wval);		return 0;	default:		DPF(2, "Got unknown SOUND_MIXER ioctl\n");		return -EINVAL;	}}static loff_t emu10k1_mixer_llseek(struct file *file, loff_t offset, int origin){	DPF(2, "sblive_mixer_llseek() called\n");	return -ESPIPE;}/* Mixer file operations *//* FIXME: Do we need spinlocks in here? *//* WARNING! not all the ioctl's are supported by the emu-APS   (anything AC97 related). As a general rule keep the AC97 related ioctls   separate from the rest. This will make it easier to rewrite the mixer   using the kernel AC97 interface. */ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	static const char id[] = "SBLive";	static const char name[] = "Creative SBLive";	int i, val;	struct emu10k1_card *card = (struct emu10k1_card *) file->private_data;	u16 reg;	switch (cmd) {	case SOUND_MIXER_INFO:{			mixer_info info;			DPF(4, "SOUND_MIXER_INFO\n");			strncpy(info.id, id, sizeof(info.id));			strncpy(info.name, name, sizeof(info.name));			info.modify_counter = card->modcnt;			if (copy_to_user((void *) arg, &info, sizeof(info)))				return -EFAULT;			return 0;		}		break;	case SOUND_OLD_MIXER_INFO:{			_old_mixer_info info;			DPF(4, "SOUND_OLD_MIXER_INFO\n");			strncpy(info.id, id, sizeof(info.id));			strncpy(info.name, name, sizeof(info.name));			if (copy_to_user((void *) arg, &info, sizeof(info)))				return -EFAULT;			return 0;		}		break;	case OSS_GETVERSION:		DPF(4, "OSS_GETVERSION\n");		return put_user(SOUND_VERSION, (int *) arg);		break;	case SOUND_MIXER_PRIVATE1:		DPF(4, "SOUND_MIXER_PRIVATE1");		if (copy_to_user((void *) arg, card->digmix, sizeof(card->digmix)))			return -EFAULT;		return 0;		break;	case SOUND_MIXER_PRIVATE2:		DPF(4, "SOUND_MIXER_PRIVATE2");		if (copy_from_user(card->digmix, (void *) arg, sizeof(card->digmix)))			return -EFAULT;		for (i = 0; i < sizeof(card->digmix) / sizeof(card->digmix[0]); i++)			sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, (card->digmix[i] & DM_MUTE) ? 0 : card->digmix[i]);		return 0;		break;	case SOUND_MIXER_PRIVATE3: {			struct mixer_private_ioctl ctl;			if (copy_from_user(&ctl, (void *) arg, sizeof(struct mixer_private_ioctl)))				return -EFAULT;			switch (ctl.cmd) {#ifdef EMU10K1_DEBUG			case CMD_WRITEFN0:				emu10k1_writefn0(card, ctl.val[0], ctl.val[1]);				return 0;				break;			case CMD_WRITEPTR:				if(ctl.val[1] >= 0x40)					return -EINVAL;				if(ctl.val[0] > 0xff)					return -EINVAL;				if((ctl.val[0] & 0x7ff) > 0x3f)					ctl.val[1] = 0x00;				sblive_writeptr(card, ctl.val[0], ctl.val[1], ctl.val[2]);				return 0;				break;#endif			case CMD_READFN0:				ctl.val[2] = emu10k1_readfn0(card, ctl.val[0]);				if (copy_to_user((void *) arg, &ctl, sizeof(struct mixer_private_ioctl)))					return -EFAULT;				return 0;				break;

⌨️ 快捷键说明

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