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

📄 dmasound_awacs.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		msleep(100);		awacs_write(awacs_reg[6] + MASK_ADDR6);		msleep(2);		awacs_write(awacs_reg[1] + MASK_ADDR1);		awacs_write(awacs_reg[7] + MASK_ADDR7);	}	if (awacs) {		if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE))			out_le32(&awacs->byteswap, BS_VAL);		else			out_le32(&awacs->byteswap, 0);	}}#ifdef CONFIG_PMAC_PBOOK/* * Save state when going to sleep, restore it afterwards. *//* FIXME: sort out disabling/re-enabling of read stuff as well */static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when){	unsigned long flags;	switch (when) {	case PBOOK_SLEEP_NOW:				LOCK();		awacs_sleeping = 1;		/* Tell the rest of the driver we are now going to sleep */		mb();		if (awacs_revision == AWACS_SCREAMER ||		    awacs_revision == AWACS_AWACS) {			awacs_reg1_save = awacs_reg[1];			awacs_reg[1] |= MASK_AMUTE | MASK_CMUTE;			awacs_write(MASK_ADDR1 | awacs_reg[1]);		}		PMacSilence();		/* stop rx - if going - a bit of a daft user... but */		out_le32(&awacs_rxdma->control, (RUN|WAKE|FLUSH << 16));		/* deny interrupts */		if (awacs)			disable_irq(awacs_irq);		disable_irq(awacs_tx_irq);		disable_irq(awacs_rx_irq);		/* Chip specific sleep code */		switch (awacs_revision) {			case AWACS_TUMBLER:			case AWACS_SNAPPER:				write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);				write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);				tas_enter_sleep();				write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);				break ;			case AWACS_DACA:				daca_enter_sleep();				break ;			case AWACS_BURGUNDY:				break ;			case AWACS_SCREAMER:			case AWACS_AWACS:			default:				out_le32(&awacs->control, 0x11) ;				break ;		}		/* Disable sound clock */		pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0);		/* According to Darwin, we do that after turning off the sound		 * chip clock. All this will have to be cleaned up once we properly		 * parse the OF sound-objects		 */		if ((machine_is_compatible("PowerBook3,1") ||		    machine_is_compatible("PowerBook3,2")) && awacs) {			awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;			awacs_write(MASK_ADDR1 | awacs_reg[1]);			msleep(200);		}		break;	case PBOOK_WAKE:		/* Enable sound clock */		pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 1);		if ((machine_is_compatible("PowerBook3,1") ||		    machine_is_compatible("PowerBook3,2")) && awacs) {			msleep(100);			awacs_reg[1] &= ~(MASK_PAROUT0 | MASK_PAROUT1);			awacs_write(MASK_ADDR1 | awacs_reg[1]);			msleep(300);		} else			msleep(1000); 		/* restore settings */		switch (awacs_revision) {			case AWACS_TUMBLER:			case AWACS_SNAPPER:				write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);				write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);				write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);				msleep(100);				write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol);				msleep(150);				tas_leave_sleep(); /* Stub for now */				headphone_intr(0,NULL,NULL);				break;			case AWACS_DACA:				msleep(10); /* Check this !!! */				daca_leave_sleep();				break ;		/* dont know how yet */			case AWACS_BURGUNDY:				break ;			case AWACS_SCREAMER:			case AWACS_AWACS:			default:		 		load_awacs() ;				break ;		}		/* Recalibrate chip */		if (awacs_revision == AWACS_SCREAMER && awacs)			awacs_recalibrate();		/* Make sure dma is stopped */		PMacSilence();		if (awacs)			enable_irq(awacs_irq);		enable_irq(awacs_tx_irq); 		enable_irq(awacs_rx_irq); 		if (awacs) { 			/* OK, allow ints back again */	 		out_le32(&awacs->control, MASK_IEPC 			 	| (awacs_rate_index << 8) | 0x11 				 | (awacs_revision < AWACS_DACA ? MASK_IEE: 0)); 		} 		if (macio_base && is_pbook_g3) {			/* FIXME: should restore the setup we had...*/			out_8(macio_base + 0x37, 3); 		} else if (is_pbook_3X00) {			in_8(latch_base + 0x190);		}		/* Remove mute */		if (awacs_revision == AWACS_SCREAMER ||		    awacs_revision == AWACS_AWACS) {			awacs_reg[1] = awacs_reg1_save;			awacs_write(MASK_ADDR1 | awacs_reg[1]);		} 		awacs_sleeping = 0;		/* Resume pending sounds. */		/* we don't try to restart input... */		spin_lock_irqsave(&dmasound.lock, flags);		__PMacPlay();		spin_unlock_irqrestore(&dmasound.lock, flags);		UNLOCK();	}	return PBOOK_SLEEP_OK;}#endif /* CONFIG_PMAC_PBOOK *//* All the burgundy functions: *//* Waits for busy flag to clear */inline static voidawacs_burgundy_busy_wait(void){	int count = 50; /* > 2 samples at 44k1 */	while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--)		udelay(1) ;}inline static voidawacs_burgundy_extend_wait(void){	int count = 50 ; /* > 2 samples at 44k1 */	while ((!(in_le32(&awacs->codec_stat) & MASK_EXTEND)) && count--)		udelay(1) ;	count = 50;	while ((in_le32(&awacs->codec_stat) & MASK_EXTEND) && count--)		udelay(1);}static voidawacs_burgundy_wcw(unsigned addr, unsigned val){	out_le32(&awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff));	awacs_burgundy_busy_wait();	out_le32(&awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff));	awacs_burgundy_busy_wait();	out_le32(&awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff));	awacs_burgundy_busy_wait();	out_le32(&awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff));	awacs_burgundy_busy_wait();}static unsignedawacs_burgundy_rcw(unsigned addr){	unsigned val = 0;	unsigned long flags;	/* should have timeouts here */	spin_lock_irqsave(&dmasound.lock, flags);	out_le32(&awacs->codec_ctrl, addr + 0x100000);	awacs_burgundy_busy_wait();	awacs_burgundy_extend_wait();	val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;	out_le32(&awacs->codec_ctrl, addr + 0x100100);	awacs_burgundy_busy_wait();	awacs_burgundy_extend_wait();	val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<8;	out_le32(&awacs->codec_ctrl, addr + 0x100200);	awacs_burgundy_busy_wait();	awacs_burgundy_extend_wait();	val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<16;	out_le32(&awacs->codec_ctrl, addr + 0x100300);	awacs_burgundy_busy_wait();	awacs_burgundy_extend_wait();	val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<24;	spin_unlock_irqrestore(&dmasound.lock, flags);	return val;}static voidawacs_burgundy_wcb(unsigned addr, unsigned val){	out_le32(&awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));	awacs_burgundy_busy_wait();}static unsignedawacs_burgundy_rcb(unsigned addr){	unsigned val = 0;	unsigned long flags;	/* should have timeouts here */	spin_lock_irqsave(&dmasound.lock, flags);	out_le32(&awacs->codec_ctrl, addr + 0x100000);	awacs_burgundy_busy_wait();	awacs_burgundy_extend_wait();	val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;	spin_unlock_irqrestore(&dmasound.lock, flags);	return val;}static intawacs_burgundy_check(void){	/* Checks to see the chip is alive and kicking */	int error = in_le32(&awacs->codec_ctrl) & MASK_ERRCODE;	return error == 0xf0000;}static intawacs_burgundy_init(void){	if (awacs_burgundy_check()) {		printk(KERN_WARNING "dmasound_pmac: burgundy not working :-(\n");		return 1;	}	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_OUTPUTENABLES,			   DEF_BURGUNDY_OUTPUTENABLES);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,			   DEF_BURGUNDY_MORE_OUTPUTENABLES);	awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_OUTPUTSELECTS,			   DEF_BURGUNDY_OUTPUTSELECTS);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL21,			   DEF_BURGUNDY_INPSEL21);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL3,			   DEF_BURGUNDY_INPSEL3);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINCD,			   DEF_BURGUNDY_GAINCD);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINLINE,			   DEF_BURGUNDY_GAINLINE);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMIC,			   DEF_BURGUNDY_GAINMIC);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMODEM,			   DEF_BURGUNDY_GAINMODEM);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER,			   DEF_BURGUNDY_ATTENSPEAKER);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENLINEOUT,			   DEF_BURGUNDY_ATTENLINEOUT);	awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENHP,			   DEF_BURGUNDY_ATTENHP);	awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_MASTER_VOLUME,			   DEF_BURGUNDY_MASTER_VOLUME);	awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLCD,			   DEF_BURGUNDY_VOLCD);	awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLLINE,			   DEF_BURGUNDY_VOLLINE);	awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLMIC,			   DEF_BURGUNDY_VOLMIC);	return 0;}static voidawacs_burgundy_write_volume(unsigned address, int volume){	int hardvolume,lvolume,rvolume;	lvolume = (volume & 0xff) ? (volume & 0xff) + 155 : 0;	rvolume = ((volume >>8)&0xff) ? ((volume >> 8)&0xff ) + 155 : 0;	hardvolume = lvolume + (rvolume << 16);	awacs_burgundy_wcw(address, hardvolume);}static intawacs_burgundy_read_volume(unsigned address){	int softvolume,wvolume;	wvolume = awacs_burgundy_rcw(address);	softvolume = (wvolume & 0xff) - 155;	softvolume += (((wvolume >> 16) & 0xff) - 155)<<8;	return softvolume > 0 ? softvolume : 0;}static intawacs_burgundy_read_mvolume(unsigned address){	int lvolume,rvolume,wvolume;	wvolume = awacs_burgundy_rcw(address);	wvolume &= 0xffff;	rvolume = (wvolume & 0xff) - 155;	lvolume = ((wvolume & 0xff00)>>8) - 155;	return lvolume + (rvolume << 8);}static voidawacs_burgundy_write_mvolume(unsigned address, int volume){	int lvolume,rvolume,hardvolume;	lvolume = (volume &0xff) ? (volume & 0xff) + 155 :0;	rvolume = ((volume >>8) & 0xff) ? (volume >> 8) + 155 :0;	hardvolume = lvolume + (rvolume << 8);	hardvolume += (hardvolume << 16);	awacs_burgundy_wcw(address, hardvolume);}/* End burgundy functions *//* Set up output volumes on machines with the 'perch/whisper' extension card. * this has an SGS i2c chip (7433) which is accessed using the cuda. * * TODO: split this out and make use of the other parts of the SGS chip to * do Bass, Treble etc. */static voidawacs_enable_amp(int spkr_vol){#ifdef CONFIG_ADB_CUDA	struct adb_request req;	if (sys_ctrler != SYS_CTRLER_CUDA)		return;	/* turn on headphones */	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,		     0x8a, 4, 0);	while (!req.complete) cuda_poll();	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,		     0x8a, 6, 0);	while (!req.complete) cuda_poll();	/* turn on speaker */	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,		     0x8a, 3, (100 - (spkr_vol & 0xff)) * 32 / 100);	while (!req.complete) cuda_poll();	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,		     0x8a, 5, (100 - ((spkr_vol >> 8) & 0xff)) * 32 / 100);	while (!req.complete) cuda_poll();	cuda_request(&req, NULL, 5, CUDA_PACKET,		     CUDA_GET_SET_IIC, 0x8a, 1, 0x29);	while (!req.complete) cuda_poll();#endif /* CONFIG_ADB_CUDA */}/*** Mid level stuff *********************************************************//* * /dev/mixer abstraction */static void do_line_lev(int data){		line_lev = data ;		awacs_reg[0] &= ~MASK_MUX_AUDIN;		if ((data & 0xff) >= 50)			awacs_reg[0] |= MASK_MUX_AUDIN;		awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_ip_gain(int data){	ip_gain = data ;	data &= 0xff;	awacs_reg[0] &= ~MASK_GAINLINE;	if (awacs_revision == AWACS_SCREAMER) {		awacs_reg[6] &= ~MASK_MIC_BOOST ;		if (data >= 33) {			awacs_reg[0] |= MASK_GAINLINE;			if( data >= 66)				awacs_reg[6] |= MASK_MIC_BOOST ;		}		awacs_write(MASK_ADDR6 | awacs_reg[6]) ;	} else {		if (data >= 50)			awacs_reg[0] |= MASK_GAINLINE;	}	awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_mic_lev(int data){	mic_lev = data ;	data &= 0xff;	awacs_reg[0] &= ~MASK_MUX_MIC;	if (data >= 50)		awacs_reg[0] |= MASK_MUX_MIC;	awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_cd_lev(int data){	cd_lev = data ;	awacs_reg[0] &= ~MASK_MUX_CD;	if ((data & 0xff) >= 50)		awacs_reg[0] |= MASK_MUX_CD;	awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_rec_lev(int data){	int left, right ;	rec_lev = data ;	/* need to fudge this to use the volume setter routine */	left = 100 - (data & 0xff) ; if( left < 0 ) left = 0 ;	right = 100 - ((data >> 8) & 0xff) ; if( right < 0 ) right = 0 ;	left |= (right << 8 );	left = awacs_volume_setter(left, 0, 0, 4);}static void do_passthru_vol(int data){	passthru_vol = data ;

⌨️ 快捷键说明

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