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

📄 ali5455.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
static void ali_set_spdif_output(struct ali_state *state, int slots,				 int rate){	int vol;	int aud_reg;	struct ac97_codec *codec = state->card->ac97_codec[0];	if (!(state->card->ac97_features & 4)) {		state->card->ac97_status &= ~SPDIF_ON;	} else {		if (slots == -1) {	/* Turn off S/PDIF */			aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS);			ali_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF));			/* If the volume wasn't muted before we turned on S/PDIF, unmute it */			if (!(state->card->ac97_status & VOL_MUTED)) {				aud_reg = ali_ac97_get(codec, AC97_MASTER_VOL_STEREO);				ali_ac97_set(codec, AC97_MASTER_VOL_STEREO,					     (aud_reg & ~VOL_MUTED));			}			state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON);			return;		}		vol = ali_ac97_get(codec, AC97_MASTER_VOL_STEREO);		state->card->ac97_status = vol & VOL_MUTED;		/* Set S/PDIF transmitter sample rate */		aud_reg = ali_ac97_get(codec, AC97_SPDIF_CONTROL);		switch (rate) {		case 32000:			aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_32K;			break;		case 44100:			aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_44K;			break;		case 48000:			aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_48K;			break;		default:			/* turn off S/PDIF */			aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS);			ali_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF));			state->card->ac97_status &= ~SPDIF_ON;			return;		}		ali_ac97_set(codec, AC97_SPDIF_CONTROL, aud_reg);		aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS);		aud_reg = (aud_reg & AC97_EA_SLOT_MASK) | slots | AC97_EA_SPDIF;		ali_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg);		aud_reg = ali_ac97_get(codec, AC97_POWER_CONTROL);		aud_reg |= 0x0002;		ali_ac97_set(codec, AC97_POWER_CONTROL, aud_reg);		udelay(1);		state->card->ac97_status |= SPDIF_ON;		/* Check to make sure the configuration is valid */		aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS);		if (!(aud_reg & 0x0400)) {			/* turn off S/PDIF */			ali_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF));			state->card->ac97_status &= ~SPDIF_ON;			return;		}		if (codec_independent_spdif_locked > 0) {			aud_reg = ali_ac97_get(codec, 0x6a);			ali_ac97_set(codec, 0x6a, (aud_reg & 0xefff));		}		/* Mute the analog output */		/* Should this only mute the PCM volume??? */	}}/* ali_set_dac_channels * *  Configure the codec's multi-channel DACs * *  The logic is backwards. Setting the bit to 1 turns off the DAC.  * *  What about the ICH? We currently configure it using the *  SNDCTL_DSP_CHANNELS ioctl.  If we're turnning on the DAC,  *  does that imply that we want the ICH set to support *  these channels? *   *  TODO: *    vailidate that the codec really supports these DACs *    before turning them on.  */static void ali_set_dac_channels(struct ali_state *state, int channel){	int aud_reg;	struct ac97_codec *codec = state->card->ac97_codec[0];	aud_reg = ali_ac97_get(codec, AC97_EXTENDED_STATUS);	aud_reg |= AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK;	state->card->ac97_status &= ~(SURR_ON | CENTER_LFE_ON);	switch (channel) {	case 2:		/* always enabled */		break;	case 4:		aud_reg &= ~AC97_EA_PRJ;		state->card->ac97_status |= SURR_ON;		break;	case 6:		aud_reg &= ~(AC97_EA_PRJ | AC97_EA_PRI | AC97_EA_PRK);		state->card->ac97_status |= SURR_ON | CENTER_LFE_ON;		break;	default:		break;	}	ali_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg);}/* set playback sample rate */static unsigned int ali_set_dac_rate(struct ali_state *state,				     unsigned int rate){	struct dmabuf *dmabuf = &state->dmabuf;	u32 new_rate;	struct ac97_codec *codec = state->card->ac97_codec[0];	if (!(state->card->ac97_features & 0x0001)) {		dmabuf->rate = clocking;		return clocking;	}	if (rate > 48000)		rate = 48000;	if (rate < 8000)		rate = 8000;	dmabuf->rate = rate;	/*	 *      Adjust for misclocked crap	 */	rate = (rate * clocking) / 48000;	if (strict_clocking && rate < 8000) {		rate = 8000;		dmabuf->rate = (rate * 48000) / clocking;	}	new_rate = ac97_set_dac_rate(codec, rate);	if (new_rate != rate) {		dmabuf->rate = (new_rate * 48000) / clocking;	}	rate = new_rate;	return dmabuf->rate;}/* set recording sample rate */static unsigned int ali_set_adc_rate(struct ali_state *state,				     unsigned int rate){	struct dmabuf *dmabuf = &state->dmabuf;	u32 new_rate;	struct ac97_codec *codec = state->card->ac97_codec[0];	if (!(state->card->ac97_features & 0x0001)) {		dmabuf->rate = clocking;		return clocking;	}	if (rate > 48000)		rate = 48000;	if (rate < 8000)		rate = 8000;	dmabuf->rate = rate;	/*	 *      Adjust for misclocked crap	 */	rate = (rate * clocking) / 48000;	if (strict_clocking && rate < 8000) {		rate = 8000;		dmabuf->rate = (rate * 48000) / clocking;	}	new_rate = ac97_set_adc_rate(codec, rate);	if (new_rate != rate) {		dmabuf->rate = (new_rate * 48000) / clocking;		rate = new_rate;	}	return dmabuf->rate;}/* set codec independent spdifout sample rate */static unsigned int ali_set_codecspdifout_rate(struct ali_state *state,					       unsigned int rate){	struct dmabuf *dmabuf = &state->dmabuf;	if (!(state->card->ac97_features & 0x0001)) {		dmabuf->rate = clocking;		return clocking;	}	if (rate > 48000)		rate = 48000;	if (rate < 8000)		rate = 8000;	dmabuf->rate = rate;	return dmabuf->rate;}/* set  controller independent spdif out function sample rate */static void ali_set_spdifout_rate(struct ali_state *state,				  unsigned int rate){	unsigned char ch_st_sel;	unsigned short status_rate;	switch (rate) {	case 44100:		status_rate = 0;		break;	case 32000:		status_rate = 0x300;		break;	case 48000:	default:		status_rate = 0x200;		break;	}	ch_st_sel = inb(state->card->iobase + ALI_SPDIFICS) & ALI_SPDIF_OUT_CH_STATUS;	//select spdif_out	ch_st_sel |= 0x80;	//select right	outb(ch_st_sel, (state->card->iobase + ALI_SPDIFICS));	outb(status_rate | 0x20, (state->card->iobase + ALI_SPDIFCSR + 2));	ch_st_sel &= (~0x80);	//select left	outb(ch_st_sel, (state->card->iobase + ALI_SPDIFICS));	outw(status_rate | 0x10, (state->card->iobase + ALI_SPDIFCSR + 2));}/* get current playback/recording dma buffer pointer (byte offset from LBA),   called with spinlock held! */static inline unsigned ali_get_dma_addr(struct ali_state *state, int rec){	struct dmabuf *dmabuf = &state->dmabuf;	unsigned int civ, offset, port, port_picb;	unsigned int data;	if (!dmabuf->enable)		return 0;	if (rec == 1)		port = state->card->iobase + dmabuf->read_channel->port;	else if (rec == 2)		port = state->card->iobase + dmabuf->codec_spdifout_channel->port;	else if (rec == 3)		port = state->card->iobase + dmabuf->controller_spdifout_channel->port;	else		port = state->card->iobase + dmabuf->write_channel->port;	port_picb = port + OFF_PICB;	do {		civ = inb(port + OFF_CIV) & 31;		offset = inw(port_picb);		/* Must have a delay here! */		if (offset == 0)			udelay(1);		/* Reread both registers and make sure that that total		 * offset from the first reading to the second is 0.		 * There is an issue with SiS hardware where it will count		 * picb down to 0, then update civ to the next value,		 * then set the new picb to fragsize bytes.  We can catch		 * it between the civ update and the picb update, making		 * it look as though we are 1 fragsize ahead of where we		 * are.  The next to we get the address though, it will		 * be back in thdelay is more than long enough		 * that we won't have to worry about the chip still being		 * out of sync with reality ;-)		 */	} while (civ != (inb(port + OFF_CIV) & 31) || offset != inw(port_picb));	data = ((civ + 1) * dmabuf->fragsize - (2 * offset)) % dmabuf->dmasize;	if (inw(port_picb) == 0)		data -= 2048;	return data;}/* Stop recording (lock held) */static inline void __stop_adc(struct ali_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct ali_card *card = state->card;	dmabuf->enable &= ~ADC_RUNNING;	outl((1 << 18) | (1 << 16), card->iobase + ALI_DMACR);	udelay(1);	outb(0, card->iobase + PI_CR);	while (inb(card->iobase + PI_CR) != 0);	// now clear any latent interrupt bits (like the halt bit)	outb(inb(card->iobase + PI_SR) | 0x001e, card->iobase + PI_SR);	outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_PCMIN, card->iobase + ALI_INTERRUPTSR);}static void stop_adc(struct ali_state *state){	struct ali_card *card = state->card;	unsigned long flags;	spin_lock_irqsave(&card->lock, flags);	__stop_adc(state);	spin_unlock_irqrestore(&card->lock, flags);}static inline void __start_adc(struct ali_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	if (dmabuf->count < dmabuf->dmasize && dmabuf->ready	    && !dmabuf->enable && (dmabuf->trigger & PCM_ENABLE_INPUT)) {		dmabuf->enable |= ADC_RUNNING;		outb((1 << 4) | (1 << 2), state->card->iobase + PI_CR);		if (state->card->channel[0].used == 1)			outl(1, state->card->iobase + ALI_DMACR);	// DMA CONTROL REGISTRER		udelay(100);		if (state->card->channel[2].used == 1)			outl((1 << 2), state->card->iobase + ALI_DMACR);	//DMA CONTROL REGISTER		udelay(100);	}}static void start_adc(struct ali_state *state){	struct ali_card *card = state->card;	unsigned long flags;	spin_lock_irqsave(&card->lock, flags);	__start_adc(state);	spin_unlock_irqrestore(&card->lock, flags);}/* stop playback (lock held) */static inline void __stop_dac(struct ali_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct ali_card *card = state->card;	dmabuf->enable &= ~DAC_RUNNING;	outl(0x00020000, card->iobase + 0x08);	outb(0, card->iobase + PO_CR);	while (inb(card->iobase + PO_CR) != 0)		cpu_relax();	outb(inb(card->iobase + PO_SR) | 0x001e, card->iobase + PO_SR);	outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_PCMOUT, card->iobase + ALI_INTERRUPTSR);}static void stop_dac(struct ali_state *state){	struct ali_card *card = state->card;	unsigned long flags;	spin_lock_irqsave(&card->lock, flags);	__stop_dac(state);	spin_unlock_irqrestore(&card->lock, flags);}static inline void __start_dac(struct ali_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable &&	    (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {		dmabuf->enable |= DAC_RUNNING;		outb((1 << 4) | (1 << 2), state->card->iobase + PO_CR);		outl((1 << 1), state->card->iobase + 0x08);	//dma control register	}}static void start_dac(struct ali_state *state){	struct ali_card *card = state->card;	unsigned long flags;	spin_lock_irqsave(&card->lock, flags);	__start_dac(state);	spin_unlock_irqrestore(&card->lock, flags);}/* stop codec and controller spdif out  (lock held) */static inline void __stop_spdifout(struct ali_state *state){	struct dmabuf *dmabuf = &state->dmabuf;	struct ali_card *card = state->card;	if (codec_independent_spdif_locked > 0) {		dmabuf->enable &= ~CODEC_SPDIFOUT_RUNNING;		outl((1 << 19), card->iobase + 0x08);		outb(0, card->iobase + CODECSPDIFOUT_CR);		while (inb(card->iobase + CODECSPDIFOUT_CR) != 0)			cpu_relax();		outb(inb(card->iobase + CODECSPDIFOUT_SR) | 0x001e, card->iobase + CODECSPDIFOUT_SR);		outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_CODECSPDIFOUT, card->iobase + ALI_INTERRUPTSR);	} else {		if (controller_independent_spdif_locked > 0) {			dmabuf->enable &= ~CONTROLLER_SPDIFOUT_RUNNING;			outl((1 << 23), card->iobase + 0x08);			outb(0, card->iobase + CONTROLLERSPDIFOUT_CR);			while (inb(card->iobase + CONTROLLERSPDIFOUT_CR) != 0)				cpu_relax();			outb(inb(card->iobase + CONTROLLERSPDIFOUT_SR) | 0x001e, card->iobase + CONTROLLERSPDIFOUT_SR);			outl(inl(card->iobase + ALI_INTERRUPTSR) & INT_SPDIFOUT, card->iobase + ALI_INTERRUPTSR);		}	}}static void stop_spdifout(struct ali_state *state){	struct ali_card *card = state->card;	unsigned long flags;	spin_lock_irqsave(&card->lock, flags);	__stop_spdifout(state);	spin_unlock_irqrestore(&card->lock, flags);}

⌨️ 快捷键说明

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