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

📄 dmasound_awacs.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (!write_sq.active)		WAKE_UP(write_sq.sync_queue);}static voidpmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs){	/* For some reason on my PowerBook G3, I get one interrupt	 * when the interrupt vector is installed (like something is	 * pending).  This happens before the dbdma is initialize by	 * us, so I just check the command pointer and if it is zero,	 * just blow it off.	 */	if (in_le32(&awacs_rxdma->cmdptr) == 0)		return;	/* We also want to blow 'em off when shutting down.	*/	if (read_sq.active == 0)		return;	/* Check multiple buffers in case we were held off from	 * interrupt processing for a long time.  Geeze, I really hope	 * this doesn't happen.	 */	while (awacs_rx_cmds[read_sq.rear].xfer_status) {		/* Clear status and move on to next buffer.		*/		awacs_rx_cmds[read_sq.rear].xfer_status = 0;		read_sq.rear++;		/* Wrap the buffer ring.		*/		if (read_sq.rear >= read_sq.max_active)			read_sq.rear = 0;		/* If we have caught up to the front buffer, bump it.		 * This will cause weird (but not fatal) results if the		 * read loop is currently using this buffer.  The user is		 * behind in this case anyway, so weird things are going		 * to happen.		 */		if (read_sq.rear == read_sq.front) {			read_sq.front++;			if (read_sq.front >= read_sq.max_active)				read_sq.front = 0;		}	}	WAKE_UP(read_sq.action_queue);}static voidpmac_awacs_intr(int irq, void *devid, struct pt_regs *regs){	int ctrl = in_le32(&awacs->control);	if (ctrl & MASK_PORTCHG) {		/* do something when headphone is plugged/unplugged? */	}	if (ctrl & MASK_CNTLERR) {		int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16;		if (err != 0 && awacs_revision < AWACS_BURGUNDY)			printk(KERN_ERR "AWACS: error %x\n", err);	}	/* Writing 1s to the CNTLERR and PORTCHG bits clears them... */	out_le32(&awacs->control, ctrl);}static voidawacs_write(int val){	if (awacs_revision >= AWACS_BURGUNDY)		return;	while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD)		;	/* XXX should have timeout */	out_le32(&awacs->codec_ctrl, val | (awacs_subframe << 22));}static void awacs_nosound(unsigned long xx){	unsigned long flags;	save_flags(flags); cli();	if (beep_playing) {		st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);		out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);		out_le32(&awacs->control,			 (in_le32(&awacs->control) & ~0x1f00)			 | (awacs_rate_index << 8));		out_le32(&awacs->byteswap, dmasound.hard.format != AFMT_S16_BE);		beep_playing = 0;	}	restore_flags(flags);}static struct timer_list beep_timer = {	function: awacs_nosound};static void awacs_mksound(unsigned int hz, unsigned int ticks){	unsigned long flags;	int beep_speed = 0;	int srate;	int period, ncycles, nsamples;	int i, j, f;	short *p;	static int beep_hz_cache;	static int beep_nsamples_cache;	static int beep_volume_cache;	for (i = 0; i < 8 && awacs_freqs[i] >= BEEP_SRATE; ++i)		if (awacs_freqs_ok[i])			beep_speed = i;	srate = awacs_freqs[beep_speed];	if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) {#if 1		/* this is a hack for broken X server code */		hz = 750;		ticks = 12;#else		/* cancel beep currently playing */		awacs_nosound(0);		return;#endif	}	save_flags(flags); cli();	del_timer(&beep_timer);	if (ticks) {		beep_timer.expires = jiffies + ticks;		add_timer(&beep_timer);	}	if (beep_playing || write_sq.active || beep_buf == NULL) {		restore_flags(flags);		return;		/* too hard, sorry :-( */	}	beep_playing = 1;	st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);	restore_flags(flags);	if (hz == beep_hz_cache && beep_volume == beep_volume_cache) {		nsamples = beep_nsamples_cache;	} else {		period = srate * 256 / hz;	/* fixed point */		ncycles = BEEP_BUFLEN * 256 / period;		nsamples = (period * ncycles) >> 8;		f = ncycles * 65536 / nsamples;		j = 0;		p = beep_buf;		for (i = 0; i < nsamples; ++i, p += 2) {			p[0] = p[1] = beep_wform[j >> 8] * beep_volume;			j = (j + f) & 0xffff;		}		beep_hz_cache = hz;		beep_volume_cache = beep_volume;		beep_nsamples_cache = nsamples;	}	st_le16(&beep_dbdma_cmd->req_count, nsamples*4);	st_le16(&beep_dbdma_cmd->xfer_status, 0);	st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd));	st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));	awacs_beep_state = 1;	save_flags(flags); cli();	if (beep_playing) {	/* i.e. haven't been terminated already */		out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);		out_le32(&awacs->control,			 (in_le32(&awacs->control) & ~0x1f00)			 | (beep_speed << 8));		out_le32(&awacs->byteswap, 0);		out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));		out_le32(&awacs_txdma->control, RUN | (RUN << 16));	}	restore_flags(flags);}#ifdef CONFIG_PMAC_PBOOK/* * Save state when going to sleep, restore it afterwards. */static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when){	switch (when) {	case PBOOK_SLEEP_NOW:		/* XXX we should stop any dma in progress when going to sleep		   and restart it when we wake. */		PMacSilence();		disable_irq(awacs_irq);		disable_irq(awacs_tx_irq);		if (is_pbook_G3) {			feature_clear(awacs_node, FEATURE_Sound_CLK_enable);			feature_clear(awacs_node, FEATURE_Sound_power);		}		break;	case PBOOK_WAKE:		/* There is still a problem on wake. Sound seems to work fine		   if I launch mpg123 and resumes fine if mpg123 was playing,		   but the console beep is dead until I do something with the		   mixer. Probably yet another timing issue */		if (!feature_test(awacs_node, FEATURE_Sound_CLK_enable)		    || !feature_test(awacs_node, FEATURE_Sound_power)) {			/* these aren't present on the 3400 AFAIK -- paulus */			feature_set(awacs_node, FEATURE_Sound_CLK_enable);			feature_set(awacs_node, FEATURE_Sound_power);			mdelay(1000);		}		out_le32(&awacs->control, MASK_IEPC			 | (awacs_rate_index << 8) | 0x11			 | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0));		awacs_write(awacs_reg[0] | MASK_ADDR0);		awacs_write(awacs_reg[1] | MASK_ADDR1);		awacs_write(awacs_reg[2] | MASK_ADDR2);		awacs_write(awacs_reg[4] | MASK_ADDR4);		if (awacs_is_screamer) {			awacs_write(awacs_reg[5] + MASK_ADDR5);			awacs_write(awacs_reg[6] + MASK_ADDR6);			awacs_write(awacs_reg[7] + MASK_ADDR7);		}		out_le32(&awacs->byteswap, dmasound.hard.format != AFMT_S16_BE);		enable_irq(awacs_irq);		enable_irq(awacs_tx_irq);		if (awacs_revision == 3) {			mdelay(100);			awacs_write(0x6000);			mdelay(2);			awacs_write(awacs_reg[1] | MASK_ADDR1);		}		/* enable CD sound input */		if (macio_base && is_pbook_G3) {			out_8(macio_base + 0x37, 3);		} else if (is_pbook_3400) {			feature_set(awacs_node, FEATURE_IOBUS_enable);			udelay(10);			in_8(latch_base + 0x190);		}		/* Resume pending sounds. */		PMacPlay();	}	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){	while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD)		;}inline static voidawacs_burgundy_extend_wait(void){	while (!(in_le32(&awacs->codec_stat) & MASK_EXTEND))		;	while (in_le32(&awacs->codec_stat) & MASK_EXTEND)		;}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 */	save_flags(flags); cli();	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;	restore_flags(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 */	save_flags(flags); cli();	out_le32(&awacs->codec_ctrl, addr + 0x100000);	awacs_burgundy_busy_wait();	awacs_burgundy_extend_wait();	val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;	restore_flags(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 "AWACS: disabled by MacOS :-(\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 *//* Turn on sound output, needed on G3 desktop powermacs */static voidawacs_enable_amp(int spkr_vol){	struct adb_request req;	awacs_spkr_vol = spkr_vol;	if (sys_ctrler != SYS_CTRLER_CUDA)		return;#ifdef CONFIG_ADB_CUDA	/* 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 int awacs_mixer_ioctl(u_int cmd, u_long arg){	int data;	switch (cmd) {	case SOUND_MIXER_READ_DEVMASK:		data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER			| SOUND_MASK_LINE | SOUND_MASK_MIC			| SOUND_MASK_CD | SOUND_MASK_RECLEV			| SOUND_MASK_ALTPCM			| SOUND_MASK_MONITOR;		return IOCTL_OUT(arg, data);	case SOUND_MIXER_READ_RECMASK:		data = SOUND_MASK_LINE | SOUND_MASK_MIC			| SOUND_MASK_CD;		return IOCTL_OUT(arg, data);	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;		if (awacs_reg[1] & MASK_LOOPTHRU)			data |= SOUND_MASK_MONITOR;		return IOCTL_OUT(arg, data);	case SOUND_MIXER_WRITE_RECSRC:		IOCTL_IN(arg, data);		data &= (SOUND_MASK_LINE			 | SOUND_MASK_MIC | SOUND_MASK_CD			 | SOUND_MASK_MONITOR);		awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC				  | MASK_MUX_AUDIN);		awacs_reg[1] &= ~MASK_LOOPTHRU;		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;		if (data & SOUND_MASK_MONITOR)

⌨️ 快捷键说明

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