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

📄 trident.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
				if (state->fmt_flag) {						\					spin_unlock_irqrestore(&state->card->lock, flags);	\					return -EFAULT;						\				}								\				state->fmt_flag = 1;						\				spin_unlock_irqrestore(&state->card->lock, flags);}				#define unlock_set_fmt(state)	{spin_lock_irqsave(&state->card->lock, flags);		\				state->fmt_flag = 0;					\				spin_unlock_irqrestore(&state->card->lock, flags);}static int trident_enable_loop_interrupts(struct trident_card * card){	u32 global_control;	global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));	switch (card->pci_id)	{	case PCI_DEVICE_ID_SI_7018:		global_control |= (ENDLP_IE | MIDLP_IE| BANK_B_EN);		break;	case PCI_DEVICE_ID_ALI_5451:	case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:	case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:	case PCI_DEVICE_ID_INTERG_5050:		global_control |= (ENDLP_IE | MIDLP_IE);		break;	default:		return FALSE;	}	outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));#ifdef DEBUG	printk("trident: Enable Loop Interrupts, globctl = 0x%08X\n",			inl(TRID_REG(card, T4D_LFO_GC_CIR)));#endif	return (TRUE);}static int trident_disable_loop_interrupts(struct trident_card * card){	u32 global_control;	global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));	global_control &= ~(ENDLP_IE | MIDLP_IE);	outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));#ifdef DEBUG	printk("trident: Disabled Loop Interrupts, globctl = 0x%08X\n",	       global_control);#endif	return (TRUE);}static void trident_enable_voice_irq(struct trident_card * card, unsigned int channel){	unsigned int mask = 1 << (channel & 0x1f);	struct trident_pcm_bank *bank = &card->banks[channel >> 5];	u32 reg, addr = bank->addresses->aint_en;	reg = inl(TRID_REG(card, addr));	reg |= mask;	outl(reg, TRID_REG(card, addr));#ifdef DEBUG	reg = inl(TRID_REG(card, addr));	printk("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",		channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr);#endif}static void trident_disable_voice_irq(struct trident_card * card, unsigned int channel){	unsigned int mask = 1 << (channel & 0x1f);	struct trident_pcm_bank *bank = &card->banks[channel >> 5];	u32 reg, addr = bank->addresses->aint_en;		reg = inl(TRID_REG(card, addr));	reg &= ~mask;	outl(reg, TRID_REG(card, addr));		/* Ack the channel in case the interrupt was set before we disable it. */	outl(mask, TRID_REG(card, bank->addresses->aint));#ifdef DEBUG	reg = inl(TRID_REG(card, addr));	printk("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",		channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr);#endif}static void trident_start_voice(struct trident_card * card, unsigned int channel){	unsigned int mask = 1 << (channel & 0x1f);	struct trident_pcm_bank *bank = &card->banks[channel >> 5];	u32 addr = bank->addresses->start;#ifdef DEBUG	u32 reg;#endif	outl(mask, TRID_REG(card, addr));#ifdef DEBUG	reg = inl(TRID_REG(card, addr));	printk("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n",		channel, addr==T4D_START_B? "START_B":"START_A",reg,addr);#endif}static void trident_stop_voice(struct trident_card * card, unsigned int channel){	unsigned int mask = 1 << (channel & 0x1f);	struct trident_pcm_bank *bank = &card->banks[channel >> 5];	u32 addr = bank->addresses->stop;#ifdef DEBUG	u32 reg;#endif	outl(mask, TRID_REG(card, addr));#ifdef DEBUG	reg = inl(TRID_REG(card, addr));	printk("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n",		channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr);#endif}static u32 trident_get_interrupt_mask (struct trident_card * card, unsigned int channel){	struct trident_pcm_bank *bank = &card->banks[channel];	u32 addr = bank->addresses->aint;	return inl(TRID_REG(card, addr));}static int trident_check_channel_interrupt(struct trident_card * card, unsigned int channel){	unsigned int mask = 1 << (channel & 0x1f);	u32 reg = trident_get_interrupt_mask (card, channel >> 5);#ifdef DEBUG	if (reg & mask)		printk("trident: channel %d has interrupt, %s = 0x%08x\n",			channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg);#endif	return (reg & mask) ? TRUE : FALSE;}static void trident_ack_channel_interrupt(struct trident_card * card, unsigned int channel){	unsigned int mask = 1 << (channel & 0x1f);	struct trident_pcm_bank *bank = &card->banks[channel >> 5];	u32 reg, addr = bank->addresses->aint;	reg = inl(TRID_REG(card, addr));	reg &= mask;	outl(reg, TRID_REG(card, addr));#ifdef DEBUG	reg = inl(TRID_REG(card, T4D_AINT_B));	printk("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n",	       channel, reg);#endif}static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *card){	struct trident_pcm_bank *bank;	int idx;	bank = &card->banks[BANK_B];	for (idx = 31; idx >= 0; idx--) {		if (!(bank->bitmap & (1 << idx))) {			struct trident_channel *channel = &bank->channels[idx];			bank->bitmap |= 1 << idx;			channel->num = idx + 32;			return channel;		}	}	/* no more free channels available */	printk(KERN_ERR "trident: no more channels available on Bank B.\n");	return NULL;}static void trident_free_pcm_channel(struct trident_card *card, unsigned int channel){	int bank;        unsigned char b;	if (channel < 31 || channel > 63)		return;	if (card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_DX ||            card->pci_id == PCI_DEVICE_ID_TRIDENT_4DWAVE_NX) {          b = inb (TRID_REG(card, T4D_REC_CH));          if ((b & ~0x80) == channel)            outb(0x0, TRID_REG(card, T4D_REC_CH));        }            	bank = channel >> 5;	channel = channel & 0x1f;        	card->banks[bank].bitmap &= ~(1 << (channel));}static struct trident_channel * cyber_alloc_pcm_channel(struct trident_card *card){	struct trident_pcm_bank *bank;	int idx;	/* The cyberpro 5050 has only 32 voices and one bank */	/* .. at least they are not documented (if you want to call that 	 * crap documentation), perhaps broken ? */	bank = &card->banks[BANK_A];	for (idx = 31; idx >= 0; idx--) {		if (!(bank->bitmap & (1 << idx))) {			struct trident_channel *channel = &bank->channels[idx];			bank->bitmap |= 1 << idx;			channel->num = idx;			return channel;		}	}	/* no more free channels available */	printk(KERN_ERR "cyberpro5050: no more channels available on Bank A.\n");	return NULL;}static void cyber_free_pcm_channel(struct trident_card *card, unsigned int channel){	if (channel > 31)		return;	card->banks[BANK_A].bitmap &= ~(1 << (channel));}static inline void cyber_outidx(int port,int idx,int data){	outb(idx,port);	outb(data,port+1);}static inline int cyber_inidx(int port,int idx){	outb(idx,port);	return inb(port+1);}static int cyber_init_ritual(struct trident_card *card){	/* some black magic, taken from SDK samples */	/* remove this and nothing will work */	int portDat;	int ret = 0;	unsigned long flags;	/* 	 *	Keep interrupts off for the configure - we don't want to 	 *	clash with another cyberpro config event 	 */ 	save_flags(flags);	cli();	portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);	/* enable, if it was disabled */	if( (portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE ) {		printk(KERN_INFO "cyberpro5050: enabling audio controller\n" );		cyber_outidx( CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE,			portDat | CYBER_BMSK_AUENZ_ENABLE );		/* check again if hardware is enabled now */		portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);	}	if( (portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE )	{		printk(KERN_ERR "cyberpro5050: initAudioAccess: no success\n" );		ret = -1;	}	else	{		cyber_outidx( CYBER_PORT_AUDIO, CYBER_IDX_IRQ_ENABLE, CYBER_BMSK_AUDIO_INT_ENABLE );		cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x01 );		cyber_outidx( CYBER_PORT_AUDIO, 0xba, 0x20 );		cyber_outidx( CYBER_PORT_AUDIO, 0xbb, 0x08 );		cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x02 );		cyber_outidx( CYBER_PORT_AUDIO, 0xb3, 0x06 );		cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x00 );	}	restore_flags(flags);	return ret;}/*  called with spin lock held */static int trident_load_channel_registers(struct trident_card *card, u32 *data, unsigned int channel){	int i;	if (channel > 63)		return FALSE;	/* select hardware channel to write */	outb(channel, TRID_REG(card, T4D_LFO_GC_CIR));	/* Output the channel registers, but don't write register	   three to an ALI chip. */	for (i = 0; i < CHANNEL_REGS; i++) {		if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451)			continue;		outl(data[i], TRID_REG(card, CHANNEL_START + 4*i));	}	if (card->pci_id == PCI_DEVICE_ID_ALI_5451 ||		card->pci_id == PCI_DEVICE_ID_INTERG_5050) {		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1));		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2));	}	return TRUE;}/* called with spin lock held */static int trident_write_voice_regs(struct trident_state *state){	unsigned int data[CHANNEL_REGS + 1];	struct trident_channel *channel;	channel = state->dmabuf.channel;	data[1] = channel->lba;	data[4] = channel->control;	switch (state->card->pci_id)	{	case PCI_DEVICE_ID_ALI_5451:		data[0] = 0; /* Current Sample Offset */		data[2] = (channel->eso << 16) | (channel->delta & 0xffff);		data[3] = 0;		break;		case PCI_DEVICE_ID_SI_7018:	case PCI_DEVICE_ID_INTERG_5050:		data[0] = 0; /* Current Sample Offset */		data[2] = (channel->eso << 16) | (channel->delta & 0xffff);		data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff);		break;	case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:		data[0] = 0; /* Current Sample Offset */		data[2] = (channel->eso << 16) | (channel->delta & 0xffff);		data[3] = channel->fm_vol & 0xffff;		break;	case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:		data[0] = (channel->delta << 24);		data[2] = ((channel->delta << 16) & 0xff000000) | (channel->eso & 0x00ffffff);		data[3] = channel->fm_vol & 0xffff;		break;	default:		return FALSE;	}	return trident_load_channel_registers(state->card, data, channel->num);}static int compute_rate_play(u32 rate){	int delta;	/* We special case 44100 and 8000 since rounding with the equation	   does not give us an accurate enough value. For 11025 and 22050	   the equation gives us the best answer. All other frequencies will	   also use the equation. JDW */	if (rate == 44100)		delta = 0xeb3;	else if (rate == 8000)		delta = 0x2ab;	else if (rate == 48000)		delta = 0x1000;	else		delta = (((rate << 12) + rate) / 48000) & 0x0000ffff;	return delta;}static int compute_rate_rec(u32 rate){	int delta;	if (rate == 44100)		delta = 0x116a;	else if (rate == 8000)		delta = 0x6000;	else if (rate == 48000)		delta = 0x1000;	else		delta = ((48000 << 12) / rate) & 0x0000ffff;	return delta;}/* set playback sample rate */static unsigned int trident_set_dac_rate(struct trident_state * state, unsigned int rate){		struct dmabuf *dmabuf = &state->dmabuf;	if (rate > 48000)		rate = 48000;	if (rate < 4000)		rate = 4000;	dmabuf->rate = rate;	dmabuf->channel->delta = compute_rate_play(rate);	trident_write_voice_regs(state);#ifdef DEBUG	printk("trident: called trident_set_dac_rate : rate = %d\n", rate);#endif	return rate;}/* set recording sample rate */static unsigned int trident_set_adc_rate(struct trident_state * state, unsigned int rate){	struct dmabuf *dmabuf = &state->dmabuf;	if (rate > 48000)		rate = 48000;	if (rate < 4000)		rate = 4000;	dmabuf->rate = rate;	dmabuf->channel->delta = compute_rate_rec(rate);	trident_write_voice_regs(state);#ifdef DEBUG	printk("trident: called trident_set_adc_rate : rate = %d\n", rate);#endif	return rate;}/* prepare channel attributes for playback */ static void trident_play_setup(struct trident_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct trident_channel *channel = dmabuf->channel;	channel->lba = dmabuf->dma_handle;	channel->delta = compute_rate_play(dmabuf->rate);	channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];

⌨️ 快捷键说明

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