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

📄 trident_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	voice->FMC = 3;	voice->RVol = 0x7f;	voice->CVol = 0x7f;	voice->GVSel = 1;	voice->Pan = 0x7f;	/* mute */	voice->Vol = 0x3ff;	/* mute */	voice->EC = 0;	voice->Alpha = 0;	voice->FMS = 0;	voice->Attribute = 0;	/* set up capture channel */	outb(((voice->number & 0x3f) | 0x80), TRID_REG(trident, T4D_RCI + voice->foldback_chan));	snd_trident_write_voice_regs(trident, voice);	if (evoice != NULL) {		evoice->Delta = voice->Delta;		evoice->spurious_threshold = voice->spurious_threshold;		evoice->LBA = voice->LBA;		evoice->CSO = 0;		evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */		evoice->CTRL = voice->CTRL;		evoice->FMC = 3;		evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;		evoice->EC = 0;		evoice->Alpha = 0;		evoice->FMS = 0;		evoice->Vol = 0x3ff;			/* mute */		evoice->RVol = evoice->CVol = 0x7f;	/* mute */		evoice->Pan = 0x7f;			/* mute */		evoice->Attribute = 0;		snd_trident_write_voice_regs(trident, evoice);		evoice->isync2 = 1;		evoice->isync_mark = runtime->period_size;		evoice->ESO = (runtime->period_size * 2) - 1;	}	spin_unlock_irq(&trident->reg_lock);	return 0;}/*---------------------------------------------------------------------------   snd_trident_spdif_hw_params     Description: Set the hardware parameters for the spdif device.     Parameters:  substream  - PCM substream class		hw_params  - hardware parameters     Returns:     Error status    ---------------------------------------------------------------------------*/static int snd_trident_spdif_hw_params(snd_pcm_substream_t * substream,				       snd_pcm_hw_params_t * hw_params){	trident_t *trident = snd_pcm_substream_chip(substream);	unsigned int old_bits = 0, change = 0;	int err;	err = snd_trident_allocate_pcm_mem(substream, hw_params);	if (err < 0)		return err;	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {		err = snd_trident_allocate_evoice(substream, hw_params);		if (err < 0)			return err;	}	/* prepare SPDIF channel */	spin_lock_irq(&trident->reg_lock);	old_bits = trident->spdif_pcm_bits;	if (old_bits & IEC958_AES0_PROFESSIONAL)		trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS;	else		trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24);	if (params_rate(hw_params) >= 48000) {		trident->spdif_pcm_ctrl = 0x3c;	// 48000 Hz		trident->spdif_pcm_bits |=			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?				IEC958_AES0_PRO_FS_48000 :				(IEC958_AES3_CON_FS_48000 << 24);	}	else if (params_rate(hw_params) >= 44100) {		trident->spdif_pcm_ctrl = 0x3e;	// 44100 Hz		trident->spdif_pcm_bits |=			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?				IEC958_AES0_PRO_FS_44100 :				(IEC958_AES3_CON_FS_44100 << 24);	}	else {		trident->spdif_pcm_ctrl = 0x3d;	// 32000 Hz		trident->spdif_pcm_bits |=			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?				IEC958_AES0_PRO_FS_32000 :				(IEC958_AES3_CON_FS_32000 << 24);	}	change = old_bits != trident->spdif_pcm_bits;	spin_unlock_irq(&trident->reg_lock);	if (change)		snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE, &trident->spdif_pcm_ctl->id);	return 0;}/*---------------------------------------------------------------------------   snd_trident_spdif_prepare     Description: Prepare SPDIF device for playback.     Parameters:  substream  - PCM substream class     Returns:     Error status    ---------------------------------------------------------------------------*/static int snd_trident_spdif_prepare(snd_pcm_substream_t * substream){	trident_t *trident = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;	snd_trident_voice_t *evoice = voice->extra;	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];	unsigned int RESO, LBAO;	unsigned int temp;	spin_lock_irq(&trident->reg_lock);	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {		/* set delta (rate) value */		voice->Delta = snd_trident_convert_rate(runtime->rate);		voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);		/* set Loop Back Address */		LBAO = runtime->dma_addr;		if (voice->memblk)			voice->LBA = voice->memblk->offset;		else			voice->LBA = LBAO;		voice->isync = 1;		voice->isync3 = 1;		voice->isync_mark = runtime->period_size;		voice->isync_max = runtime->buffer_size;		/* set target ESO for channel */		RESO = runtime->buffer_size - 1;		voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;		/* set ctrl mode */		voice->CTRL = snd_trident_control_mode(substream);		voice->FMC = 3;		voice->RVol = 0x7f;		voice->CVol = 0x7f;		voice->GVSel = 1;		voice->Pan = 0x7f;		voice->Vol = 0x3ff;		voice->EC = 0;		voice->CSO = 0;		voice->Alpha = 0;		voice->FMS = 0;		voice->Attribute = 0;		/* prepare surrogate IRQ channel */		snd_trident_write_voice_regs(trident, voice);		outw((RESO & 0xffff), TRID_REG(trident, NX_SPESO));		outb((RESO >> 16), TRID_REG(trident, NX_SPESO + 2));		outl((LBAO & 0xfffffffc), TRID_REG(trident, NX_SPLBA));		outw((voice->CSO & 0xffff), TRID_REG(trident, NX_SPCTRL_SPCSO));		outb((voice->CSO >> 16), TRID_REG(trident, NX_SPCTRL_SPCSO + 2));		/* set SPDIF setting */		outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));		outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));	} else {	/* SiS */			/* set delta (rate) value */		voice->Delta = 0x800;		voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);		/* set Loop Begin Address */		if (voice->memblk)			voice->LBA = voice->memblk->offset;		else			voice->LBA = runtime->dma_addr;		voice->CSO = 0;		voice->ESO = runtime->buffer_size - 1;	/* in samples */		voice->CTRL = snd_trident_control_mode(substream);		voice->FMC = 3;		voice->GVSel = 1;		voice->EC = 0;		voice->Alpha = 0;		voice->FMS = 0;		voice->Vol = mix->vol;		voice->RVol = mix->rvol;		voice->CVol = mix->cvol;		voice->Pan = mix->pan;		voice->Attribute = (1<<(30-16))|(7<<(26-16))|				   (0<<(24-16))|(0<<(19-16));		snd_trident_write_voice_regs(trident, voice);		if (evoice != NULL) {			evoice->Delta = voice->Delta;			evoice->spurious_threshold = voice->spurious_threshold;			evoice->LBA = voice->LBA;			evoice->CSO = 0;			evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */			evoice->CTRL = voice->CTRL;			evoice->FMC = 3;			evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;			evoice->EC = 0;			evoice->Alpha = 0;			evoice->FMS = 0;			evoice->Vol = 0x3ff;			/* mute */			evoice->RVol = evoice->CVol = 0x7f;	/* mute */			evoice->Pan = 0x7f;			/* mute */			evoice->Attribute = 0;			snd_trident_write_voice_regs(trident, evoice);			evoice->isync2 = 1;			evoice->isync_mark = runtime->period_size;			evoice->ESO = (runtime->period_size * 2) - 1;		}		outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));		temp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));		temp &= ~(1<<19);		outl(temp, TRID_REG(trident, T4D_LFO_GC_CIR));		temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));		temp |= SPDIF_EN;		outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));	}	spin_unlock_irq(&trident->reg_lock);	return 0;}/*---------------------------------------------------------------------------   snd_trident_trigger     Description: Start/stop devices     Parameters:  substream  - PCM substream class   		cmd	- trigger command (STOP, GO)     Returns:     Error status    ---------------------------------------------------------------------------*/static int snd_trident_trigger(snd_pcm_substream_t *substream,			       int cmd)				    {	trident_t *trident = snd_pcm_substream_chip(substream);	struct list_head *pos;	snd_pcm_substream_t *s;	unsigned int what, whati, capture_flag, spdif_flag;	snd_trident_voice_t *voice, *evoice;	unsigned int val, go;	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:	case SNDRV_PCM_TRIGGER_RESUME:		go = 1;		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:	case SNDRV_PCM_TRIGGER_SUSPEND:		go = 0;		break;	default:		return -EINVAL;	}	what = whati = capture_flag = spdif_flag = 0;	spin_lock(&trident->reg_lock);	val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;	snd_pcm_group_for_each(pos, substream) {		s = snd_pcm_group_substream_entry(pos);		if ((trident_t *) snd_pcm_substream_chip(s) == trident) {			voice = (snd_trident_voice_t *) s->runtime->private_data;			evoice = voice->extra;			what |= 1 << (voice->number & 0x1f);			if (evoice == NULL) {				whati |= 1 << (voice->number & 0x1f);			} else {				what |= 1 << (evoice->number & 0x1f);				whati |= 1 << (evoice->number & 0x1f);				if (go)					evoice->stimer = val;			}			if (go) {				voice->running = 1;				voice->stimer = val;			} else {				voice->running = 0;			}			snd_pcm_trigger_done(s, substream);			if (voice->capture)				capture_flag = 1;			if (voice->spdif)				spdif_flag = 1;		}	}	if (spdif_flag) {		if (trident->device != TRIDENT_DEVICE_ID_SI7018) {			outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));			outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));		} else {			outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));			val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN;			outl(val, TRID_REG(trident, SI_SERIAL_INTF_CTRL));		}	}	if (!go)		outl(what, TRID_REG(trident, T4D_STOP_B));	val = inl(TRID_REG(trident, T4D_AINTEN_B));	if (go) {		val |= whati;	} else {		val &= ~whati;	}	outl(val, TRID_REG(trident, T4D_AINTEN_B));	if (go) {		outl(what, TRID_REG(trident, T4D_START_B));		if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)			outb(trident->bDMAStart, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));	} else {		if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)			outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));	}	spin_unlock(&trident->reg_lock);	return 0;}/*---------------------------------------------------------------------------   snd_trident_playback_pointer     Description: This routine return the playback position                   Parameters:	substream  - PCM substream class   Returns:     position of buffer    ---------------------------------------------------------------------------*/static snd_pcm_uframes_t snd_trident_playback_pointer(snd_pcm_substream_t * substream){	trident_t *trident = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;	unsigned int cso;	if (!voice->running)		return 0;	spin_lock(&trident->reg_lock);	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));	if (trident->device != TRIDENT_DEVICE_ID_NX) {		cso = inw(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));	} else {		// ID_4DWAVE_NX		cso = (unsigned int) inl(TRID_REG(trident, CH_NX_DELTA_CSO)) & 0x00ffffff;	}	spin_unlock(&trident->reg_lock);	if (cso >= runtime->buffer_size)		cso = 0;	return cso;}/*---------------------------------------------------------------------------   snd_trident_capture_pointer     Description: This routine return the capture position                   Paramters:   pcm1    - PCM device class   Returns:     position of buffer    ---------------------------------------------------------------------------*/static snd_pcm_uframes_t snd_trident_capture_pointer(snd_pcm_substream_t * substream){	trident_t *trident = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;	unsigned int result;	if (!voice->running)		return 0;	result = inw(TRID_REG(trident, T4D_SBBL_SBCL));	if (runtime->channels > 1)		result >>= 1;	if (result > 0)		result = runtime->buffer_size - result;	return result;}

⌨️ 快捷键说明

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