📄 trident_main.c
字号:
}}/*--------------------------------------------------------------------------- snd_trident_write_voice_regs Description: This routine will complete and write the 5 hardware channel registers to hardware. Paramters: trident - pointer to target device class for 4DWave. voice - synthesizer voice structure Each register field. ---------------------------------------------------------------------------*/void snd_trident_write_voice_regs(trident_t * trident, snd_trident_voice_t * voice){ unsigned int FmcRvolCvol; unsigned int regs[5]; regs[1] = voice->LBA; regs[4] = (voice->GVSel << 31) | ((voice->Pan & 0x0000007f) << 24) | ((voice->CTRL & 0x0000000f) << 12); FmcRvolCvol = ((voice->FMC & 3) << 14) | ((voice->RVol & 0x7f) << 7) | (voice->CVol & 0x7f); switch (trident->device) { case TRIDENT_DEVICE_ID_SI7018: regs[4] |= voice->number > 31 ? (voice->Vol & 0x000003ff) : ((voice->Vol & 0x00003fc) << (16-2)) | (voice->EC & 0x00000fff); regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f); regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff); regs[3] = (voice->Attribute << 16) | FmcRvolCvol; break; case TRIDENT_DEVICE_ID_DX: regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) | (voice->EC & 0x00000fff); regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f); regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff); regs[3] = FmcRvolCvol; break; case TRIDENT_DEVICE_ID_NX: regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) | (voice->EC & 0x00000fff); regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff); regs[2] = ((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff); regs[3] = (voice->Alpha << 20) | ((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol; break; default: snd_BUG(); } outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); outl(regs[0], TRID_REG(trident, CH_START + 0)); outl(regs[1], TRID_REG(trident, CH_START + 4)); outl(regs[2], TRID_REG(trident, CH_START + 8)); outl(regs[3], TRID_REG(trident, CH_START + 12)); outl(regs[4], TRID_REG(trident, CH_START + 16));}/*--------------------------------------------------------------------------- snd_trident_write_cso_reg Description: This routine will write the new CSO offset register to hardware. Paramters: trident - pointer to target device class for 4DWave. voice - synthesizer voice structure CSO - new CSO value ---------------------------------------------------------------------------*/static void snd_trident_write_cso_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CSO){ voice->CSO = CSO; outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); if (trident->device != TRIDENT_DEVICE_ID_NX) { outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2); } else { outl((voice->Delta << 24) | (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO)); }}/*--------------------------------------------------------------------------- snd_trident_write_vol_reg Description: This routine will write the new voice volume register to hardware. Paramters: trident - pointer to target device class for 4DWave. voice - synthesizer voice structure Vol - new voice volume ---------------------------------------------------------------------------*/static void snd_trident_write_vol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Vol){ voice->Vol = Vol; outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); switch (trident->device) { case TRIDENT_DEVICE_ID_DX: case TRIDENT_DEVICE_ID_NX: outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2)); break; case TRIDENT_DEVICE_ID_SI7018: // printk("voice->Vol = 0x%x\n", voice->Vol); outw((voice->CTRL << 12) | voice->Vol, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC)); break; }}/*--------------------------------------------------------------------------- snd_trident_write_pan_reg Description: This routine will write the new voice pan register to hardware. Paramters: trident - pointer to target device class for 4DWave. voice - synthesizer voice structure Pan - new pan value ---------------------------------------------------------------------------*/static void snd_trident_write_pan_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Pan){ voice->Pan = Pan; outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));}/*--------------------------------------------------------------------------- snd_trident_write_rvol_reg Description: This routine will write the new reverb volume register to hardware. Paramters: trident - pointer to target device class for 4DWave. voice - synthesizer voice structure RVol - new reverb volume ---------------------------------------------------------------------------*/static void snd_trident_write_rvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int RVol){ voice->RVol = RVol; outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f), TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));}/*--------------------------------------------------------------------------- snd_trident_write_cvol_reg Description: This routine will write the new chorus volume register to hardware. Paramters: trident - pointer to target device class for 4DWave. voice - synthesizer voice structure CVol - new chorus volume ---------------------------------------------------------------------------*/static void snd_trident_write_cvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CVol){ voice->CVol = CVol; outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f), TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));}/*--------------------------------------------------------------------------- snd_trident_convert_rate Description: This routine converts rate in HZ to hardware delta value. Paramters: trident - pointer to target device class for 4DWave. rate - Real or Virtual channel number. Returns: Delta value. ---------------------------------------------------------------------------*/unsigned int snd_trident_convert_rate(unsigned int rate){ unsigned 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) + 24000) / 48000) & 0x0000ffff; return delta;}/*--------------------------------------------------------------------------- snd_trident_convert_adc_rate Description: This routine converts rate in HZ to hardware delta value. Paramters: trident - pointer to target device class for 4DWave. rate - Real or Virtual channel number. Returns: Delta value. ---------------------------------------------------------------------------*/static unsigned int snd_trident_convert_adc_rate(unsigned int rate){ unsigned 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 = 0x116a; else if (rate == 8000) delta = 0x6000; else if (rate == 48000) delta = 0x1000; else delta = ((48000 << 12) / rate) & 0x0000ffff; return delta;}/*--------------------------------------------------------------------------- snd_trident_spurious_threshold Description: This routine converts rate in HZ to spurious threshold. Paramters: trident - pointer to target device class for 4DWave. rate - Real or Virtual channel number. Returns: Delta value. ---------------------------------------------------------------------------*/unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned int period_size){ unsigned int res = (rate * period_size) / 48000; if (res < 64) res = res / 2; else res -= 32; return res;}/*--------------------------------------------------------------------------- snd_trident_control_mode Description: This routine returns a control mode for a PCM channel. Paramters: trident - pointer to target device class for 4DWave. substream - PCM substream Returns: Control value. ---------------------------------------------------------------------------*/unsigned int snd_trident_control_mode(snd_pcm_substream_t *substream){ unsigned int CTRL; snd_pcm_runtime_t *runtime = substream->runtime; /* set ctrl mode CTRL default: 8-bit (unsigned) mono, loop mode enabled */ CTRL = 0x00000001; if (snd_pcm_format_width(runtime->format) == 16) CTRL |= 0x00000008; // 16-bit data if (snd_pcm_format_signed(runtime->format)) CTRL |= 0x00000002; // signed data if (runtime->channels > 1) CTRL |= 0x00000004; // stereo data return CTRL;}/* * PCM part *//*--------------------------------------------------------------------------- snd_trident_ioctl Description: Device I/O control handler for playback/capture parameters. Paramters: substream - PCM substream class cmd - what ioctl message to process arg - additional message infoarg Returns: Error status ---------------------------------------------------------------------------*/static int snd_trident_ioctl(snd_pcm_substream_t * substream, unsigned int cmd, void *arg){ /* FIXME: it seems that with small periods the behaviour of trident hardware is unpredictable and interrupt generator is broken */ return snd_pcm_lib_ioctl(substream, cmd, arg);}/*--------------------------------------------------------------------------- snd_trident_playback_hw_params Description: Set the hardware parameters for the playback device. Parameters: substream - PCM substream class hw_params - hardware parameters Returns: Error status ---------------------------------------------------------------------------*/static int snd_trident_playback_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params){ 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; unsigned long flags; int err; if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) return err; if (err > 0 && trident->tlb.entries) { if (voice->memblk) snd_trident_free_pages(trident, voice->memblk); spin_lock_irqsave(&trident->reg_lock, flags); voice->memblk = snd_trident_alloc_pages(trident, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); spin_unlock_irqrestore(&trident->reg_lock, flags); if (voice->memblk == NULL) return -ENOMEM; } /* voice management */ if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) { if (evoice == NULL) { evoice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0); if (evoice == NULL) return -ENOMEM; voice->extra = evoice; evoice->substream = substream; } } else { if (evoice != NULL) { snd_trident_free_voice(trident, evoice); voice->extra = evoice = NULL; } } return 0;}/*--------------------------------------------------------------------------- snd_trident_playback_hw_free Description: Release the hardware resources for the playback device. Parameters: substream - PCM substream class Returns: Error status ---------------------------------------------------------------------------*/static int snd_trident_playback_hw_free(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 ? voice->extra : NULL; if (trident->tlb.entries && voice && voice->memblk) { snd_trident_free_pages(trident, voice->memblk); voice->memblk = NULL; } snd_pcm_lib_free_pages(substream); if (evoice != NULL) { snd_trident_free_voice(trident, evoice); voice->extra = NULL; } return 0;}/*--------------------------------------------------------------------------- snd_trident_playback_prepare Description: Prepare playback device for playback. Parameters: substream - PCM substream class Returns: Error status ---------------------------------------------------------------------------*/static int snd_trident_playback_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -