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

📄 dmasound_awacs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		if ((data & 0xff) >= 50)			awacs_reg[1] |= MASK_LOOPTHRU;		awacs_write(MASK_ADDR1 | awacs_reg[1]);		data = (awacs_reg[1] & MASK_LOOPTHRU)? 100: 0;	}}static int awacs_mixer_ioctl(u_int cmd, u_long arg){	int data;	int rc;	switch (cmd) {	case SOUND_MIXER_READ_CAPS:		/* say we will allow multiple inputs?  prob. wrong			so I'm switching it to single */		return IOCTL_OUT(arg, 1);	case SOUND_MIXER_READ_DEVMASK:		data  = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER			| SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD			| SOUND_MASK_IGAIN | SOUND_MASK_RECLEV			| SOUND_MASK_ALTPCM			| SOUND_MASK_MONITOR;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECMASK:		data = SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECSRC:		data = 0;		if (awacs_reg[0] & MASK_MUX_AUDIN)			data |= SOUND_MASK_LINE;		if (awacs_reg[0] & MASK_MUX_MIC)			data |= SOUND_MASK_MIC;		if (awacs_reg[0] & MASK_MUX_CD)			data |= SOUND_MASK_CD;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_RECSRC:		IOCTL_IN(arg, data);		data &= (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD);		awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC				  | MASK_MUX_AUDIN);		if (data & SOUND_MASK_LINE)			awacs_reg[0] |= MASK_MUX_AUDIN;		if (data & SOUND_MASK_MIC)			awacs_reg[0] |= MASK_MUX_MIC;		if (data & SOUND_MASK_CD)			awacs_reg[0] |= MASK_MUX_CD;		awacs_write(awacs_reg[0] | MASK_ADDR0);		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_STEREODEVS:		data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER| SOUND_MASK_RECLEV  ;		if (awacs_revision == AWACS_SCREAMER)			data |= SOUND_MASK_MONITOR ;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_VOLUME:		IOCTL_IN(arg, data);		line_vol = data ;		awacs_volume_setter(data, 2, 0, 6);		/* fall through */	case SOUND_MIXER_READ_VOLUME:		rc = IOCTL_OUT(arg, line_vol);		break;	case SOUND_MIXER_WRITE_SPEAKER:		IOCTL_IN(arg, data);		spk_vol = data ;		if (has_perch)			awacs_enable_amp(data);		else			(void)awacs_volume_setter(data, 4, MASK_CMUTE, 6);		/* fall though */	case SOUND_MIXER_READ_SPEAKER:		rc = IOCTL_OUT(arg, spk_vol);		break;	case SOUND_MIXER_WRITE_ALTPCM:	/* really bell volume */		IOCTL_IN(arg, data);		beep_vol = data & 0xff;		/* fall through */	case SOUND_MIXER_READ_ALTPCM:		rc = IOCTL_OUT(arg, beep_vol);		break;	case SOUND_MIXER_WRITE_LINE:		IOCTL_IN(arg, data);		do_line_lev(data) ;		/* fall through */	case SOUND_MIXER_READ_LINE:		rc = IOCTL_OUT(arg, line_lev);		break;	case SOUND_MIXER_WRITE_IGAIN:		IOCTL_IN(arg, data);		do_ip_gain(data) ;		/* fall through */	case SOUND_MIXER_READ_IGAIN:		rc = IOCTL_OUT(arg, ip_gain);		break;	case SOUND_MIXER_WRITE_MIC:		IOCTL_IN(arg, data);		do_mic_lev(data);		/* fall through */	case SOUND_MIXER_READ_MIC:		rc = IOCTL_OUT(arg, mic_lev);		break;	case SOUND_MIXER_WRITE_CD:		IOCTL_IN(arg, data);		do_cd_lev(data);		/* fall through */	case SOUND_MIXER_READ_CD:		rc = IOCTL_OUT(arg, cd_lev);		break;	case SOUND_MIXER_WRITE_RECLEV:		IOCTL_IN(arg, data);		do_rec_lev(data) ;		/* fall through */	case SOUND_MIXER_READ_RECLEV:		rc = IOCTL_OUT(arg, rec_lev);		break;	case MIXER_WRITE(SOUND_MIXER_MONITOR):		IOCTL_IN(arg, data);		do_passthru_vol(data) ;		/* fall through */	case MIXER_READ(SOUND_MIXER_MONITOR):		rc = IOCTL_OUT(arg, passthru_vol);		break;	default:		rc = -EINVAL;	}		return rc;}static void awacs_mixer_init(void){	awacs_volume_setter(line_vol, 2, 0, 6);	if (has_perch)		awacs_enable_amp(spk_vol);	else		(void)awacs_volume_setter(spk_vol, 4, MASK_CMUTE, 6);	do_line_lev(line_lev) ;	do_ip_gain(ip_gain) ;	do_mic_lev(mic_lev) ;	do_cd_lev(cd_lev) ;	do_rec_lev(rec_lev) ;	do_passthru_vol(passthru_vol) ;}static int burgundy_mixer_ioctl(u_int cmd, u_long arg){	int data;	int rc;	/* We are, we are, we are... Burgundy or better */	switch(cmd) {	case SOUND_MIXER_READ_DEVMASK:		data = SOUND_MASK_VOLUME | SOUND_MASK_CD |			SOUND_MASK_LINE | SOUND_MASK_MIC |			SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECMASK:		data = SOUND_MASK_LINE | SOUND_MASK_MIC			| SOUND_MASK_CD;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECSRC:		data = 0;		if (awacs_reg[0] & MASK_MUX_AUDIN)			data |= SOUND_MASK_LINE;		if (awacs_reg[0] & MASK_MUX_MIC)			data |= SOUND_MASK_MIC;		if (awacs_reg[0] & MASK_MUX_CD)			data |= SOUND_MASK_CD;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_RECSRC:		IOCTL_IN(arg, data);		data &= (SOUND_MASK_LINE			 | SOUND_MASK_MIC | SOUND_MASK_CD);		awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC				  | MASK_MUX_AUDIN);		if (data & SOUND_MASK_LINE)			awacs_reg[0] |= MASK_MUX_AUDIN;		if (data & SOUND_MASK_MIC)			awacs_reg[0] |= MASK_MUX_MIC;		if (data & SOUND_MASK_CD)			awacs_reg[0] |= MASK_MUX_CD;		awacs_write(awacs_reg[0] | MASK_ADDR0);		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_STEREODEVS:		data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER			| SOUND_MASK_RECLEV | SOUND_MASK_CD			| SOUND_MASK_LINE;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_CAPS:		rc = IOCTL_OUT(arg, 0);		break;	case SOUND_MIXER_WRITE_VOLUME:		IOCTL_IN(arg, data);		awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data);				/* Fall through */	case SOUND_MIXER_READ_VOLUME:		rc = IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME));		break;	case SOUND_MIXER_WRITE_SPEAKER:		IOCTL_IN(arg, data);		if (!(data & 0xff)) {			/* Mute the left speaker */			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2);		} else {			/* Unmute the left speaker */			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2);		}		if (!(data & 0xff00)) {			/* Mute the right speaker */			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4);		} else {			/* Unmute the right speaker */			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4);		}		data = (((data&0xff)*16)/100 > 0xf ? 0xf :			(((data&0xff)*16)/100)) +			((((data>>8)*16)/100 > 0xf ? 0xf :			  ((((data>>8)*16)/100)))<<4);		awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data);				/* Fall through */	case SOUND_MIXER_READ_SPEAKER:		data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER);		data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8);		rc = IOCTL_OUT(arg, (~data) & 0x0000ffff);		break;	case SOUND_MIXER_WRITE_ALTPCM:	/* really bell volume */		IOCTL_IN(arg, data);		beep_vol = data & 0xff;				/* fall through */	case SOUND_MIXER_READ_ALTPCM:		rc = IOCTL_OUT(arg, beep_vol);		break;	case SOUND_MIXER_WRITE_LINE:		IOCTL_IN(arg, data);		awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data);				/* fall through */	case SOUND_MIXER_READ_LINE:		data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE);		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_MIC:		IOCTL_IN(arg, data);				/* Mic is mono device */		data = (data << 8) + (data << 24);		awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data);				/* fall through */	case SOUND_MIXER_READ_MIC:		data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC);		data <<= 24;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_CD:		IOCTL_IN(arg, data);		awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data);				/* fall through */	case SOUND_MIXER_READ_CD:		data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD);		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_RECLEV:		IOCTL_IN(arg, data);		data = awacs_volume_setter(data, 0, 0, 4);		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECLEV:		data = awacs_get_volume(awacs_reg[0], 4);		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_OUTMASK:	case SOUND_MIXER_OUTSRC:	default:		rc = -EINVAL;	}		return rc;}static int daca_mixer_ioctl(u_int cmd, u_long arg){	int data;	int rc;	/* And the DACA's no genius either! */	switch(cmd) {	case SOUND_MIXER_READ_DEVMASK:		data = SOUND_MASK_VOLUME;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECMASK:		data = 0;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_RECSRC:		data = 0;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_WRITE_RECSRC:		IOCTL_IN(arg, data);		data =0;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_STEREODEVS:		data = SOUND_MASK_VOLUME;		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_READ_CAPS:		rc = IOCTL_OUT(arg, 0);		break;	case SOUND_MIXER_WRITE_VOLUME:		IOCTL_IN(arg, data);		daca_set_volume(data, data);		/* Fall through */	case SOUND_MIXER_READ_VOLUME:		daca_get_volume(& data, &data);		rc = IOCTL_OUT(arg, data);		break;	case SOUND_MIXER_OUTMASK:	case SOUND_MIXER_OUTSRC:	default:		rc = -EINVAL;	}	return rc;}static int PMacMixerIoctl(u_int cmd, u_long arg){	int rc;		/* Different IOCTLS for burgundy and, eventually, DACA & Tumbler */	TRY_LOCK();		switch (awacs_revision){		case AWACS_BURGUNDY:			rc = burgundy_mixer_ioctl(cmd, arg);			break ;		case AWACS_DACA:			rc = daca_mixer_ioctl(cmd, arg);			break;		case AWACS_TUMBLER:		case AWACS_SNAPPER:			rc = tas_mixer_ioctl(cmd, arg);			break ;		default: /* ;-)) */			rc = awacs_mixer_ioctl(cmd, arg);	}	UNLOCK();		return rc;}static void PMacMixerInit(void){	switch (awacs_revision) {		case AWACS_TUMBLER:		  printk("AE-Init tumbler mixer\n");		  break ;		case AWACS_SNAPPER:		  printk("AE-Init snapper mixer\n");		  break ;		case AWACS_DACA:		case AWACS_BURGUNDY:			break ;	/* don't know yet */		case AWACS_AWACS:		case AWACS_SCREAMER:		default:			awacs_mixer_init() ;			break ;	}}/* Write/Read sq setup functions:   Check to see if we have enough (or any) dbdma cmd buffers for the   user's fragment settings.  If not, allocate some. If this fails we will   point at the beep buffer - as an emergency provision - to stop dma tromping   on some random bit of memory (if someone lets it go anyway).   The command buffers are then set up to point to the fragment buffers   (allocated elsewhere).  We need n+1 commands the last of which holds   a NOP + loop to start.*/static int PMacWriteSqSetup(void){	int i, count = 600 ;	volatile struct dbdma_cmd *cp;	LOCK();		/* stop the controller from doing any output - if it isn't already.	   it _should_ be before this is called anyway */	out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);	while ((in_le32(&awacs_txdma->status) & RUN) && count--)		udelay(1);#ifdef DEBUG_DMASOUNDif (count <= 0)	printk("dmasound_pmac: write sq setup: timeout waiting for dma to stop\n");#endif	if ((write_sq.max_count + 1) > number_of_tx_cmd_buffers) {		kfree(awacs_tx_cmd_space);		number_of_tx_cmd_buffers = 0;		/* we need nbufs + 1 (for the loop) and we should request + 1		   again because the DBDMA_ALIGN might pull the start up by up		   to sizeof(struct dbdma_cmd) - 4.		*/		awacs_tx_cmd_space = kmalloc			((write_sq.max_count + 1 + 1) * sizeof(struct dbdma_cmd),			 GFP_KERNEL);		if (awacs_tx_cmd_space == NULL) {			/* don't leave it dangling - nasty but better than a			   random address */			out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));			printk(KERN_ERR			   "dmasound_pmac: can't allocate dbdma cmd buffers"			   ", driver disabled\n");			UNLOCK();			return -ENOMEM;		}		awacs_tx_cmds = (volatile struct dbdma_cmd *)			DBDMA_ALIGN(awacs_tx_cmd_space);		number_of_tx_cmd_buffers = write_sq.max_count + 1;	}	cp = awacs_tx_cmds;	memset((void *)cp, 0, (write_sq.max_count+1) * sizeof(struct dbdma_cmd));	for (i = 0; i < write_sq.max_count; ++i, ++cp) {		st_le32(&cp->phy_addr, virt_to_bus(write_sq.buffers[i]));	}	st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);	st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds));	/* point the controller at the command stack - ready to go */	out_le32(&awacs_txdma->cmdptr, virt_to_bus(awacs_tx_cmds));	UNLOCK();	return 0;}static int PMacReadSqSetup(void){	int i, count = 600;	volatile struct dbdma_cmd *cp;	LOCK();		/* stop the controller from doing any input - if it isn't 

⌨️ 快捷键说明

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