brintos

brintos / linux-shallow public Read only

0
0
Text · 117.9 KiB · e98eea1 Raw
3886 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Maintained by Jaroslav Kysela <perex@perex.cz>4 *  Originated by audio@tridentmicro.com5 *  Fri Feb 19 15:55:28 MST 19996 *  Routines for control of Trident 4DWave (DX and NX) chip7 *8 *  BUGS:9 *10 *  TODO:11 *    ---12 *13 *  SiS7018 S/PDIF support by Thomas Winischhofer <thomas@winischhofer.net>14 */15 16#include <linux/delay.h>17#include <linux/init.h>18#include <linux/interrupt.h>19#include <linux/pci.h>20#include <linux/slab.h>21#include <linux/vmalloc.h>22#include <linux/gameport.h>23#include <linux/dma-mapping.h>24#include <linux/export.h>25#include <linux/io.h>26 27#include <sound/core.h>28#include <sound/info.h>29#include <sound/control.h>30#include <sound/tlv.h>31#include "trident.h"32#include <sound/asoundef.h>33 34static int snd_trident_pcm_mixer_build(struct snd_trident *trident,35				       struct snd_trident_voice * voice,36				       struct snd_pcm_substream *substream);37static int snd_trident_pcm_mixer_free(struct snd_trident *trident,38				      struct snd_trident_voice * voice,39				      struct snd_pcm_substream *substream);40static irqreturn_t snd_trident_interrupt(int irq, void *dev_id);41static int snd_trident_sis_reset(struct snd_trident *trident);42 43static void snd_trident_clear_voices(struct snd_trident * trident,44				     unsigned short v_min, unsigned short v_max);45static void snd_trident_free(struct snd_card *card);46 47/*48 *  common I/O routines49 */50 51 52#if 053static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice)54{55	unsigned int val, tmp;56 57	dev_dbg(trident->card->dev, "Trident voice %i:\n", voice);58	outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR));59	val = inl(TRID_REG(trident, CH_LBA));60	dev_dbg(trident->card->dev, "LBA: 0x%x\n", val);61	val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));62	dev_dbg(trident->card->dev, "GVSel: %i\n", val >> 31);63	dev_dbg(trident->card->dev, "Pan: 0x%x\n", (val >> 24) & 0x7f);64	dev_dbg(trident->card->dev, "Vol: 0x%x\n", (val >> 16) & 0xff);65	dev_dbg(trident->card->dev, "CTRL: 0x%x\n", (val >> 12) & 0x0f);66	dev_dbg(trident->card->dev, "EC: 0x%x\n", val & 0x0fff);67	if (trident->device != TRIDENT_DEVICE_ID_NX) {68		val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS));69		dev_dbg(trident->card->dev, "CSO: 0x%x\n", val >> 16);70		dev_dbg(trident->card->dev, "Alpha: 0x%x\n", (val >> 4) & 0x0fff);71		dev_dbg(trident->card->dev, "FMS: 0x%x\n", val & 0x0f);72		val = inl(TRID_REG(trident, CH_DX_ESO_DELTA));73		dev_dbg(trident->card->dev, "ESO: 0x%x\n", val >> 16);74		dev_dbg(trident->card->dev, "Delta: 0x%x\n", val & 0xffff);75		val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));76	} else {		// TRIDENT_DEVICE_ID_NX77		val = inl(TRID_REG(trident, CH_NX_DELTA_CSO));78		tmp = (val >> 24) & 0xff;79		dev_dbg(trident->card->dev, "CSO: 0x%x\n", val & 0x00ffffff);80		val = inl(TRID_REG(trident, CH_NX_DELTA_ESO));81		tmp |= (val >> 16) & 0xff00;82		dev_dbg(trident->card->dev, "Delta: 0x%x\n", tmp);83		dev_dbg(trident->card->dev, "ESO: 0x%x\n", val & 0x00ffffff);84		val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL));85		dev_dbg(trident->card->dev, "Alpha: 0x%x\n", val >> 20);86		dev_dbg(trident->card->dev, "FMS: 0x%x\n", (val >> 16) & 0x0f);87	}88	dev_dbg(trident->card->dev, "FMC: 0x%x\n", (val >> 14) & 3);89	dev_dbg(trident->card->dev, "RVol: 0x%x\n", (val >> 7) & 0x7f);90	dev_dbg(trident->card->dev, "CVol: 0x%x\n", val & 0x7f);91}92#endif93 94/*---------------------------------------------------------------------------95   unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)96  97   Description: This routine will do all of the reading from the external98                CODEC (AC97).99  100   Parameters:  ac97 - ac97 codec structure101                reg - CODEC register index, from AC97 Hal.102 103   returns:     16 bit value read from the AC97.104  105  ---------------------------------------------------------------------------*/106static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)107{108	unsigned int data = 0, treg;109	unsigned short count = 0xffff;110	unsigned long flags;111	struct snd_trident *trident = ac97->private_data;112 113	spin_lock_irqsave(&trident->reg_lock, flags);114	if (trident->device == TRIDENT_DEVICE_ID_DX) {115		data = (DX_AC97_BUSY_READ | (reg & 0x000000ff));116		outl(data, TRID_REG(trident, DX_ACR1_AC97_R));117		do {118			data = inl(TRID_REG(trident, DX_ACR1_AC97_R));119			if ((data & DX_AC97_BUSY_READ) == 0)120				break;121		} while (--count);122	} else if (trident->device == TRIDENT_DEVICE_ID_NX) {123		data = (NX_AC97_BUSY_READ | (reg & 0x000000ff));124		treg = ac97->num == 0 ? NX_ACR2_AC97_R_PRIMARY : NX_ACR3_AC97_R_SECONDARY;125		outl(data, TRID_REG(trident, treg));126		do {127			data = inl(TRID_REG(trident, treg));128			if ((data & 0x00000C00) == 0)129				break;130		} while (--count);131	} else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {132		data = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);133		if (ac97->num == 1)134			data |= SI_AC97_SECONDARY;135		outl(data, TRID_REG(trident, SI_AC97_READ));136		do {137			data = inl(TRID_REG(trident, SI_AC97_READ));138			if ((data & (SI_AC97_BUSY_READ)) == 0)139				break;140		} while (--count);141	}142 143	if (count == 0 && !trident->ac97_detect) {144		dev_err(trident->card->dev,145			"ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n",146			   reg, data);147		data = 0;148	}149 150	spin_unlock_irqrestore(&trident->reg_lock, flags);151	return ((unsigned short) (data >> 16));152}153 154/*---------------------------------------------------------------------------155   void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,156   unsigned short wdata)157  158   Description: This routine will do all of the writing to the external159                CODEC (AC97).160  161   Parameters:	ac97 - ac97 codec structure162   	        reg - CODEC register index, from AC97 Hal.163                data  - Lower 16 bits are the data to write to CODEC.164  165   returns:     TRUE if everything went ok, else FALSE.166  167  ---------------------------------------------------------------------------*/168static void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,169				    unsigned short wdata)170{171	unsigned int address, data;172	unsigned short count = 0xffff;173	unsigned long flags;174	struct snd_trident *trident = ac97->private_data;175 176	data = ((unsigned long) wdata) << 16;177 178	spin_lock_irqsave(&trident->reg_lock, flags);179	if (trident->device == TRIDENT_DEVICE_ID_DX) {180		address = DX_ACR0_AC97_W;181 182		/* read AC-97 write register status */183		do {184			if ((inw(TRID_REG(trident, address)) & DX_AC97_BUSY_WRITE) == 0)185				break;186		} while (--count);187 188		data |= (DX_AC97_BUSY_WRITE | (reg & 0x000000ff));189	} else if (trident->device == TRIDENT_DEVICE_ID_NX) {190		address = NX_ACR1_AC97_W;191 192		/* read AC-97 write register status */193		do {194			if ((inw(TRID_REG(trident, address)) & NX_AC97_BUSY_WRITE) == 0)195				break;196		} while (--count);197 198		data |= (NX_AC97_BUSY_WRITE | (ac97->num << 8) | (reg & 0x000000ff));199	} else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {200		address = SI_AC97_WRITE;201 202		/* read AC-97 write register status */203		do {204			if ((inw(TRID_REG(trident, address)) & (SI_AC97_BUSY_WRITE)) == 0)205				break;206		} while (--count);207 208		data |= SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);209		if (ac97->num == 1)210			data |= SI_AC97_SECONDARY;211	} else {212		address = 0;	/* keep GCC happy */213		count = 0;	/* return */214	}215 216	if (count == 0) {217		spin_unlock_irqrestore(&trident->reg_lock, flags);218		return;219	}220	outl(data, TRID_REG(trident, address));221	spin_unlock_irqrestore(&trident->reg_lock, flags);222}223 224/*---------------------------------------------------------------------------225   void snd_trident_enable_eso(struct snd_trident *trident)226  227   Description: This routine will enable end of loop interrupts.228                End of loop interrupts will occur when a running229                channel reaches ESO.230                Also enables middle of loop interrupts.231  232   Parameters:  trident - pointer to target device class for 4DWave.233  234  ---------------------------------------------------------------------------*/235 236static void snd_trident_enable_eso(struct snd_trident * trident)237{238	unsigned int val;239 240	val = inl(TRID_REG(trident, T4D_LFO_GC_CIR));241	val |= ENDLP_IE;242	val |= MIDLP_IE;243	if (trident->device == TRIDENT_DEVICE_ID_SI7018)244		val |= BANK_B_EN;245	outl(val, TRID_REG(trident, T4D_LFO_GC_CIR));246}247 248/*---------------------------------------------------------------------------249   void snd_trident_disable_eso(struct snd_trident *trident)250  251   Description: This routine will disable end of loop interrupts.252                End of loop interrupts will occur when a running253                channel reaches ESO.254                Also disables middle of loop interrupts.255  256   Parameters:  257                trident - pointer to target device class for 4DWave.258  259   returns:     TRUE if everything went ok, else FALSE.260  261  ---------------------------------------------------------------------------*/262 263static void snd_trident_disable_eso(struct snd_trident * trident)264{265	unsigned int tmp;266 267	tmp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));268	tmp &= ~ENDLP_IE;269	tmp &= ~MIDLP_IE;270	outl(tmp, TRID_REG(trident, T4D_LFO_GC_CIR));271}272 273/*---------------------------------------------------------------------------274   void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)275 276    Description: Start a voice, any channel 0 thru 63.277                 This routine automatically handles the fact that there are278                 more than 32 channels available.279 280    Parameters : voice - Voice number 0 thru n.281                 trident - pointer to target device class for 4DWave.282 283    Return Value: None.284 285  ---------------------------------------------------------------------------*/286 287void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)288{289	unsigned int mask = 1 << (voice & 0x1f);290	unsigned int reg = (voice & 0x20) ? T4D_START_B : T4D_START_A;291 292	outl(mask, TRID_REG(trident, reg));293}294 295EXPORT_SYMBOL(snd_trident_start_voice);296 297/*---------------------------------------------------------------------------298   void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)299 300    Description: Stop a voice, any channel 0 thru 63.301                 This routine automatically handles the fact that there are302                 more than 32 channels available.303 304    Parameters : voice - Voice number 0 thru n.305                 trident - pointer to target device class for 4DWave.306 307    Return Value: None.308 309  ---------------------------------------------------------------------------*/310 311void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)312{313	unsigned int mask = 1 << (voice & 0x1f);314	unsigned int reg = (voice & 0x20) ? T4D_STOP_B : T4D_STOP_A;315 316	outl(mask, TRID_REG(trident, reg));317}318 319EXPORT_SYMBOL(snd_trident_stop_voice);320 321/*---------------------------------------------------------------------------322    int snd_trident_allocate_pcm_channel(struct snd_trident *trident)323  324    Description: Allocate hardware channel in Bank B (32-63).325  326    Parameters :  trident - pointer to target device class for 4DWave.327  328    Return Value: hardware channel - 32-63 or -1 when no channel is available329  330  ---------------------------------------------------------------------------*/331 332static int snd_trident_allocate_pcm_channel(struct snd_trident * trident)333{334	int idx;335 336	if (trident->ChanPCMcnt >= trident->ChanPCM)337		return -1;338	for (idx = 31; idx >= 0; idx--) {339		if (!(trident->ChanMap[T4D_BANK_B] & (1 << idx))) {340			trident->ChanMap[T4D_BANK_B] |= 1 << idx;341			trident->ChanPCMcnt++;342			return idx + 32;343		}344	}345	return -1;346}347 348/*---------------------------------------------------------------------------349    void snd_trident_free_pcm_channel(int channel)350  351    Description: Free hardware channel in Bank B (32-63)352  353    Parameters :  trident - pointer to target device class for 4DWave.354	          channel - hardware channel number 0-63355  356    Return Value: none357  358  ---------------------------------------------------------------------------*/359 360static void snd_trident_free_pcm_channel(struct snd_trident *trident, int channel)361{362	if (channel < 32 || channel > 63)363		return;364	channel &= 0x1f;365	if (trident->ChanMap[T4D_BANK_B] & (1 << channel)) {366		trident->ChanMap[T4D_BANK_B] &= ~(1 << channel);367		trident->ChanPCMcnt--;368	}369}370 371/*---------------------------------------------------------------------------372    unsigned int snd_trident_allocate_synth_channel(void)373  374    Description: Allocate hardware channel in Bank A (0-31).375  376    Parameters :  trident - pointer to target device class for 4DWave.377  378    Return Value: hardware channel - 0-31 or -1 when no channel is available379  380  ---------------------------------------------------------------------------*/381 382static int snd_trident_allocate_synth_channel(struct snd_trident * trident)383{384	int idx;385 386	for (idx = 31; idx >= 0; idx--) {387		if (!(trident->ChanMap[T4D_BANK_A] & (1 << idx))) {388			trident->ChanMap[T4D_BANK_A] |= 1 << idx;389			trident->synth.ChanSynthCount++;390			return idx;391		}392	}393	return -1;394}395 396/*---------------------------------------------------------------------------397    void snd_trident_free_synth_channel( int channel )398  399    Description: Free hardware channel in Bank B (0-31).400  401    Parameters :  trident - pointer to target device class for 4DWave.402	          channel - hardware channel number 0-63403  404    Return Value: none405  406  ---------------------------------------------------------------------------*/407 408static void snd_trident_free_synth_channel(struct snd_trident *trident, int channel)409{410	if (channel < 0 || channel > 31)411		return;412	channel &= 0x1f;413	if (trident->ChanMap[T4D_BANK_A] & (1 << channel)) {414		trident->ChanMap[T4D_BANK_A] &= ~(1 << channel);415		trident->synth.ChanSynthCount--;416	}417}418 419/*---------------------------------------------------------------------------420   snd_trident_write_voice_regs421  422   Description: This routine will complete and write the 5 hardware channel423                registers to hardware.424  425   Parameters:  trident - pointer to target device class for 4DWave.426                voice - synthesizer voice structure427                Each register field.428  429  ---------------------------------------------------------------------------*/430 431void snd_trident_write_voice_regs(struct snd_trident * trident,432				  struct snd_trident_voice * voice)433{434	unsigned int FmcRvolCvol;435	unsigned int regs[5];436 437	regs[1] = voice->LBA;438	regs[4] = (voice->GVSel << 31) |439		  ((voice->Pan & 0x0000007f) << 24) |440		  ((voice->CTRL & 0x0000000f) << 12);441	FmcRvolCvol = ((voice->FMC & 3) << 14) |442	              ((voice->RVol & 0x7f) << 7) |443	              (voice->CVol & 0x7f);444 445	switch (trident->device) {446	case TRIDENT_DEVICE_ID_SI7018:447		regs[4] |= voice->number > 31 ?448				(voice->Vol & 0x000003ff) :449				((voice->Vol & 0x00003fc) << (16-2)) |450				(voice->EC & 0x00000fff);451		regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |452			(voice->FMS & 0x0000000f);453		regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);454		regs[3] = (voice->Attribute << 16) | FmcRvolCvol;455		break;456	case TRIDENT_DEVICE_ID_DX:457		regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |458			   (voice->EC & 0x00000fff);459		regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |460			(voice->FMS & 0x0000000f);461		regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);462		regs[3] = FmcRvolCvol;463		break;464	case TRIDENT_DEVICE_ID_NX:465		regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |466			   (voice->EC & 0x00000fff);467		regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff);468		regs[2] = ((voice->Delta << 16) & 0xff000000) |469			(voice->ESO & 0x00ffffff);470		regs[3] = (voice->Alpha << 20) |471			((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol;472		break;473	default:474		snd_BUG();475		return;476	}477 478	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));479	outl(regs[0], TRID_REG(trident, CH_START + 0));480	outl(regs[1], TRID_REG(trident, CH_START + 4));481	outl(regs[2], TRID_REG(trident, CH_START + 8));482	outl(regs[3], TRID_REG(trident, CH_START + 12));483	outl(regs[4], TRID_REG(trident, CH_START + 16));484 485#if 0486	dev_dbg(trident->card->dev, "written %i channel:\n", voice->number);487	dev_dbg(trident->card->dev, "  regs[0] = 0x%x/0x%x\n",488	       regs[0], inl(TRID_REG(trident, CH_START + 0)));489	dev_dbg(trident->card->dev, "  regs[1] = 0x%x/0x%x\n",490	       regs[1], inl(TRID_REG(trident, CH_START + 4)));491	dev_dbg(trident->card->dev, "  regs[2] = 0x%x/0x%x\n",492	       regs[2], inl(TRID_REG(trident, CH_START + 8)));493	dev_dbg(trident->card->dev, "  regs[3] = 0x%x/0x%x\n",494	       regs[3], inl(TRID_REG(trident, CH_START + 12)));495	dev_dbg(trident->card->dev, "  regs[4] = 0x%x/0x%x\n",496	       regs[4], inl(TRID_REG(trident, CH_START + 16)));497#endif498}499 500EXPORT_SYMBOL(snd_trident_write_voice_regs);501 502/*---------------------------------------------------------------------------503   snd_trident_write_cso_reg504  505   Description: This routine will write the new CSO offset506                register to hardware.507  508   Parameters:  trident - pointer to target device class for 4DWave.509                voice - synthesizer voice structure510                CSO - new CSO value511  512  ---------------------------------------------------------------------------*/513 514static void snd_trident_write_cso_reg(struct snd_trident * trident,515				      struct snd_trident_voice * voice,516				      unsigned int CSO)517{518	voice->CSO = CSO;519	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));520	if (trident->device != TRIDENT_DEVICE_ID_NX) {521		outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);522	} else {523		outl((voice->Delta << 24) |524		     (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO));525	}526}527 528/*---------------------------------------------------------------------------529   snd_trident_write_eso_reg530  531   Description: This routine will write the new ESO offset532                register to hardware.533  534   Parameters:  trident - pointer to target device class for 4DWave.535                voice - synthesizer voice structure536                ESO - new ESO value537  538  ---------------------------------------------------------------------------*/539 540static void snd_trident_write_eso_reg(struct snd_trident * trident,541				      struct snd_trident_voice * voice,542				      unsigned int ESO)543{544	voice->ESO = ESO;545	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));546	if (trident->device != TRIDENT_DEVICE_ID_NX) {547		outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2);548	} else {549		outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff),550		     TRID_REG(trident, CH_NX_DELTA_ESO));551	}552}553 554/*---------------------------------------------------------------------------555   snd_trident_write_vol_reg556  557   Description: This routine will write the new voice volume558                register to hardware.559  560   Parameters:  trident - pointer to target device class for 4DWave.561                voice - synthesizer voice structure562                Vol - new voice volume563  564  ---------------------------------------------------------------------------*/565 566static void snd_trident_write_vol_reg(struct snd_trident * trident,567				      struct snd_trident_voice * voice,568				      unsigned int Vol)569{570	voice->Vol = Vol;571	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));572	switch (trident->device) {573	case TRIDENT_DEVICE_ID_DX:574	case TRIDENT_DEVICE_ID_NX:575		outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2));576		break;577	case TRIDENT_DEVICE_ID_SI7018:578		/* dev_dbg(trident->card->dev, "voice->Vol = 0x%x\n", voice->Vol); */579		outw((voice->CTRL << 12) | voice->Vol,580		     TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));581		break;582	}583}584 585/*---------------------------------------------------------------------------586   snd_trident_write_pan_reg587  588   Description: This routine will write the new voice pan589                register to hardware.590  591   Parameters:  trident - pointer to target device class for 4DWave.592                voice - synthesizer voice structure593                Pan - new pan value594  595  ---------------------------------------------------------------------------*/596 597static void snd_trident_write_pan_reg(struct snd_trident * trident,598				      struct snd_trident_voice * voice,599				      unsigned int Pan)600{601	voice->Pan = Pan;602	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));603	outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f),604	     TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));605}606 607/*---------------------------------------------------------------------------608   snd_trident_write_rvol_reg609  610   Description: This routine will write the new reverb volume611                register to hardware.612  613   Parameters:  trident - pointer to target device class for 4DWave.614                voice - synthesizer voice structure615                RVol - new reverb volume616  617  ---------------------------------------------------------------------------*/618 619static void snd_trident_write_rvol_reg(struct snd_trident * trident,620				       struct snd_trident_voice * voice,621				       unsigned int RVol)622{623	voice->RVol = RVol;624	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));625	outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |626	     (voice->CVol & 0x007f),627	     TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?628		      CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));629}630 631/*---------------------------------------------------------------------------632   snd_trident_write_cvol_reg633  634   Description: This routine will write the new chorus volume635                register to hardware.636  637   Parameters:  trident - pointer to target device class for 4DWave.638                voice - synthesizer voice structure639                CVol - new chorus volume640  641  ---------------------------------------------------------------------------*/642 643static void snd_trident_write_cvol_reg(struct snd_trident * trident,644				       struct snd_trident_voice * voice,645				       unsigned int CVol)646{647	voice->CVol = CVol;648	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));649	outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |650	     (voice->CVol & 0x007f),651	     TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?652		      CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));653}654 655/*---------------------------------------------------------------------------656   snd_trident_convert_rate657 658   Description: This routine converts rate in HZ to hardware delta value.659  660   Parameters:  trident - pointer to target device class for 4DWave.661                rate - Real or Virtual channel number.662  663   Returns:     Delta value.664  665  ---------------------------------------------------------------------------*/666static unsigned int snd_trident_convert_rate(unsigned int rate)667{668	unsigned int delta;669 670	// We special case 44100 and 8000 since rounding with the equation671	// does not give us an accurate enough value. For 11025 and 22050672	// the equation gives us the best answer. All other frequencies will673	// also use the equation. JDW674	if (rate == 44100)675		delta = 0xeb3;676	else if (rate == 8000)677		delta = 0x2ab;678	else if (rate == 48000)679		delta = 0x1000;680	else681		delta = DIV_ROUND_CLOSEST(rate << 12, 48000) & 0x0000ffff;682	return delta;683}684 685/*---------------------------------------------------------------------------686   snd_trident_convert_adc_rate687 688   Description: This routine converts rate in HZ to hardware delta value.689  690   Parameters:  trident - pointer to target device class for 4DWave.691                rate - Real or Virtual channel number.692  693   Returns:     Delta value.694  695  ---------------------------------------------------------------------------*/696static unsigned int snd_trident_convert_adc_rate(unsigned int rate)697{698	unsigned int delta;699 700	// We special case 44100 and 8000 since rounding with the equation701	// does not give us an accurate enough value. For 11025 and 22050702	// the equation gives us the best answer. All other frequencies will703	// also use the equation. JDW704	if (rate == 44100)705		delta = 0x116a;706	else if (rate == 8000)707		delta = 0x6000;708	else if (rate == 48000)709		delta = 0x1000;710	else711		delta = ((48000 << 12) / rate) & 0x0000ffff;712	return delta;713}714 715/*---------------------------------------------------------------------------716   snd_trident_spurious_threshold717 718   Description: This routine converts rate in HZ to spurious threshold.719  720   Parameters:  trident - pointer to target device class for 4DWave.721                rate - Real or Virtual channel number.722  723   Returns:     Delta value.724  725  ---------------------------------------------------------------------------*/726static unsigned int snd_trident_spurious_threshold(unsigned int rate,727						   unsigned int period_size)728{729	unsigned int res = (rate * period_size) / 48000;730	if (res < 64)731		res = res / 2;732	else733		res -= 32;734	return res;735}736 737/*---------------------------------------------------------------------------738   snd_trident_control_mode739 740   Description: This routine returns a control mode for a PCM channel.741  742   Parameters:  trident - pointer to target device class for 4DWave.743                substream  - PCM substream744  745   Returns:     Control value.746  747  ---------------------------------------------------------------------------*/748static unsigned int snd_trident_control_mode(struct snd_pcm_substream *substream)749{750	unsigned int CTRL;751	struct snd_pcm_runtime *runtime = substream->runtime;752 753	/* set ctrl mode754	   CTRL default: 8-bit (unsigned) mono, loop mode enabled755	 */756	CTRL = 0x00000001;757	if (snd_pcm_format_width(runtime->format) == 16)758		CTRL |= 0x00000008;	// 16-bit data759	if (snd_pcm_format_signed(runtime->format))760		CTRL |= 0x00000002;	// signed data761	if (runtime->channels > 1)762		CTRL |= 0x00000004;	// stereo data763	return CTRL;764}765 766/*767 *  PCM part768 */769 770/*---------------------------------------------------------------------------771   snd_trident_allocate_pcm_mem772  773   Description: Allocate PCM ring buffer for given substream774  775   Parameters:  substream  - PCM substream class776		hw_params  - hardware parameters777  778   Returns:     Error status779  780  ---------------------------------------------------------------------------*/781 782static int snd_trident_allocate_pcm_mem(struct snd_pcm_substream *substream,783					struct snd_pcm_hw_params *hw_params)784{785	struct snd_trident *trident = snd_pcm_substream_chip(substream);786	struct snd_pcm_runtime *runtime = substream->runtime;787	struct snd_trident_voice *voice = runtime->private_data;788 789	if (trident->tlb.entries) {790		if (runtime->buffer_changed) {791			if (voice->memblk)792				snd_trident_free_pages(trident, voice->memblk);793			voice->memblk = snd_trident_alloc_pages(trident, substream);794			if (voice->memblk == NULL)795				return -ENOMEM;796		}797	}798	return 0;799}800 801/*---------------------------------------------------------------------------802   snd_trident_allocate_evoice803  804   Description: Allocate extra voice as interrupt generator805  806   Parameters:  substream  - PCM substream class807		hw_params  - hardware parameters808  809   Returns:     Error status810  811  ---------------------------------------------------------------------------*/812 813static int snd_trident_allocate_evoice(struct snd_pcm_substream *substream,814				       struct snd_pcm_hw_params *hw_params)815{816	struct snd_trident *trident = snd_pcm_substream_chip(substream);817	struct snd_pcm_runtime *runtime = substream->runtime;818	struct snd_trident_voice *voice = runtime->private_data;819	struct snd_trident_voice *evoice = voice->extra;820 821	/* voice management */822 823	if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) {824		if (evoice == NULL) {825			evoice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);826			if (evoice == NULL)827				return -ENOMEM;828			voice->extra = evoice;829			evoice->substream = substream;830		}831	} else {832		if (evoice != NULL) {833			snd_trident_free_voice(trident, evoice);834			voice->extra = evoice = NULL;835		}836	}837 838	return 0;839}840 841/*---------------------------------------------------------------------------842   snd_trident_hw_params843  844   Description: Set the hardware parameters for the playback device.845  846   Parameters:  substream  - PCM substream class847		hw_params  - hardware parameters848  849   Returns:     Error status850  851  ---------------------------------------------------------------------------*/852 853static int snd_trident_hw_params(struct snd_pcm_substream *substream,854				 struct snd_pcm_hw_params *hw_params)855{856	int err;857 858	err = snd_trident_allocate_pcm_mem(substream, hw_params);859	if (err >= 0)860		err = snd_trident_allocate_evoice(substream, hw_params);861	return err;862}863 864/*---------------------------------------------------------------------------865   snd_trident_playback_hw_free866  867   Description: Release the hardware resources for the playback device.868  869   Parameters:  substream  - PCM substream class870  871   Returns:     Error status872  873  ---------------------------------------------------------------------------*/874 875static int snd_trident_hw_free(struct snd_pcm_substream *substream)876{877	struct snd_trident *trident = snd_pcm_substream_chip(substream);878	struct snd_pcm_runtime *runtime = substream->runtime;879	struct snd_trident_voice *voice = runtime->private_data;880	struct snd_trident_voice *evoice = voice ? voice->extra : NULL;881 882	if (trident->tlb.entries) {883		if (voice && voice->memblk) {884			snd_trident_free_pages(trident, voice->memblk);885			voice->memblk = NULL;886		}887	}888	if (evoice != NULL) {889		snd_trident_free_voice(trident, evoice);890		voice->extra = NULL;891	}892	return 0;893}894 895/*---------------------------------------------------------------------------896   snd_trident_playback_prepare897  898   Description: Prepare playback device for playback.899  900   Parameters:  substream  - PCM substream class901  902   Returns:     Error status903  904  ---------------------------------------------------------------------------*/905 906static int snd_trident_playback_prepare(struct snd_pcm_substream *substream)907{908	struct snd_trident *trident = snd_pcm_substream_chip(substream);909	struct snd_pcm_runtime *runtime = substream->runtime;910	struct snd_trident_voice *voice = runtime->private_data;911	struct snd_trident_voice *evoice = voice->extra;912	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];913 914	spin_lock_irq(&trident->reg_lock);	915 916	/* set delta (rate) value */917	voice->Delta = snd_trident_convert_rate(runtime->rate);918	voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);919 920	/* set Loop Begin Address */921	if (voice->memblk)922		voice->LBA = voice->memblk->offset;923	else924		voice->LBA = runtime->dma_addr;925 926	voice->CSO = 0;927	voice->ESO = runtime->buffer_size - 1;	/* in samples */928	voice->CTRL = snd_trident_control_mode(substream);929	voice->FMC = 3;930	voice->GVSel = 1;931	voice->EC = 0;932	voice->Alpha = 0;933	voice->FMS = 0;934	voice->Vol = mix->vol;935	voice->RVol = mix->rvol;936	voice->CVol = mix->cvol;937	voice->Pan = mix->pan;938	voice->Attribute = 0;939#if 0940	voice->Attribute = (1<<(30-16))|(2<<(26-16))|941			   (0<<(24-16))|(0x1f<<(19-16));942#else943	voice->Attribute = 0;944#endif945 946	snd_trident_write_voice_regs(trident, voice);947 948	if (evoice != NULL) {949		evoice->Delta = voice->Delta;950		evoice->spurious_threshold = voice->spurious_threshold;951		evoice->LBA = voice->LBA;952		evoice->CSO = 0;953		evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */954		evoice->CTRL = voice->CTRL;955		evoice->FMC = 3;956		evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;957		evoice->EC = 0;958		evoice->Alpha = 0;959		evoice->FMS = 0;960		evoice->Vol = 0x3ff;			/* mute */961		evoice->RVol = evoice->CVol = 0x7f;	/* mute */962		evoice->Pan = 0x7f;			/* mute */963#if 0964		evoice->Attribute = (1<<(30-16))|(2<<(26-16))|965				    (0<<(24-16))|(0x1f<<(19-16));966#else967		evoice->Attribute = 0;968#endif969		snd_trident_write_voice_regs(trident, evoice);970		evoice->isync2 = 1;971		evoice->isync_mark = runtime->period_size;972		evoice->ESO = (runtime->period_size * 2) - 1;973	}974 975	spin_unlock_irq(&trident->reg_lock);976 977	return 0;978}979 980/*---------------------------------------------------------------------------981   snd_trident_capture_hw_params982  983   Description: Set the hardware parameters for the capture device.984  985   Parameters:  substream  - PCM substream class986		hw_params  - hardware parameters987  988   Returns:     Error status989  990  ---------------------------------------------------------------------------*/991 992static int snd_trident_capture_hw_params(struct snd_pcm_substream *substream,993					 struct snd_pcm_hw_params *hw_params)994{995	return snd_trident_allocate_pcm_mem(substream, hw_params);996}997 998/*---------------------------------------------------------------------------999   snd_trident_capture_prepare1000  1001   Description: Prepare capture device for playback.1002  1003   Parameters:  substream  - PCM substream class1004  1005   Returns:     Error status1006  1007  ---------------------------------------------------------------------------*/1008 1009static int snd_trident_capture_prepare(struct snd_pcm_substream *substream)1010{1011	struct snd_trident *trident = snd_pcm_substream_chip(substream);1012	struct snd_pcm_runtime *runtime = substream->runtime;1013	struct snd_trident_voice *voice = runtime->private_data;1014	unsigned int val, ESO_bytes;1015 1016	spin_lock_irq(&trident->reg_lock);1017 1018	// Initialize the channel and set channel Mode1019	outb(0, TRID_REG(trident, LEGACY_DMAR15));1020 1021	// Set DMA channel operation mode register1022	outb(0x54, TRID_REG(trident, LEGACY_DMAR11));1023 1024	// Set channel buffer Address, DMAR0 expects contiguous PCI memory area	1025	voice->LBA = runtime->dma_addr;1026	outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0));1027	if (voice->memblk)1028		voice->LBA = voice->memblk->offset;1029 1030	// set ESO1031	ESO_bytes = snd_pcm_lib_buffer_bytes(substream) - 1;1032	outb((ESO_bytes & 0x00ff0000) >> 16, TRID_REG(trident, LEGACY_DMAR6));1033	outw((ESO_bytes & 0x0000ffff), TRID_REG(trident, LEGACY_DMAR4));1034	ESO_bytes++;1035 1036	// Set channel sample rate, 4.12 format1037	val = DIV_ROUND_CLOSEST(48000U << 12, runtime->rate);1038	outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R));1039 1040	// Set channel interrupt blk length1041	if (snd_pcm_format_width(runtime->format) == 16) {1042		val = (unsigned short) ((ESO_bytes >> 1) - 1);1043	} else {1044		val = (unsigned short) (ESO_bytes - 1);1045	}1046 1047	outl((val << 16) | val, TRID_REG(trident, T4D_SBBL_SBCL));1048 1049	// Right now, set format and start to run captureing, 1050	// continuous run loop enable.1051	trident->bDMAStart = 0x19;	// 0001 1001b1052 1053	if (snd_pcm_format_width(runtime->format) == 16)1054		trident->bDMAStart |= 0x80;1055	if (snd_pcm_format_signed(runtime->format))1056		trident->bDMAStart |= 0x20;1057	if (runtime->channels > 1)1058		trident->bDMAStart |= 0x40;1059 1060	// Prepare capture intr channel1061 1062	voice->Delta = snd_trident_convert_rate(runtime->rate);1063	voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);1064	voice->isync = 1;1065	voice->isync_mark = runtime->period_size;1066	voice->isync_max = runtime->buffer_size;1067 1068	// Set voice parameters1069	voice->CSO = 0;1070	voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;1071	voice->CTRL = snd_trident_control_mode(substream);1072	voice->FMC = 3;1073	voice->RVol = 0x7f;1074	voice->CVol = 0x7f;1075	voice->GVSel = 1;1076	voice->Pan = 0x7f;		/* mute */1077	voice->Vol = 0x3ff;		/* mute */1078	voice->EC = 0;1079	voice->Alpha = 0;1080	voice->FMS = 0;1081	voice->Attribute = 0;1082 1083	snd_trident_write_voice_regs(trident, voice);1084 1085	spin_unlock_irq(&trident->reg_lock);1086	return 0;1087}1088 1089/*---------------------------------------------------------------------------1090   snd_trident_si7018_capture_hw_params1091  1092   Description: Set the hardware parameters for the capture device.1093  1094   Parameters:  substream  - PCM substream class1095		hw_params  - hardware parameters1096  1097   Returns:     Error status1098  1099  ---------------------------------------------------------------------------*/1100 1101static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream *substream,1102						struct snd_pcm_hw_params *hw_params)1103{1104	return snd_trident_allocate_evoice(substream, hw_params);1105}1106 1107/*---------------------------------------------------------------------------1108   snd_trident_si7018_capture_hw_free1109  1110   Description: Release the hardware resources for the capture device.1111  1112   Parameters:  substream  - PCM substream class1113  1114   Returns:     Error status1115  1116  ---------------------------------------------------------------------------*/1117 1118static int snd_trident_si7018_capture_hw_free(struct snd_pcm_substream *substream)1119{1120	struct snd_trident *trident = snd_pcm_substream_chip(substream);1121	struct snd_pcm_runtime *runtime = substream->runtime;1122	struct snd_trident_voice *voice = runtime->private_data;1123	struct snd_trident_voice *evoice = voice ? voice->extra : NULL;1124 1125	if (evoice != NULL) {1126		snd_trident_free_voice(trident, evoice);1127		voice->extra = NULL;1128	}1129	return 0;1130}1131 1132/*---------------------------------------------------------------------------1133   snd_trident_si7018_capture_prepare1134  1135   Description: Prepare capture device for playback.1136  1137   Parameters:  substream  - PCM substream class1138  1139   Returns:     Error status1140  1141  ---------------------------------------------------------------------------*/1142 1143static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream *substream)1144{1145	struct snd_trident *trident = snd_pcm_substream_chip(substream);1146	struct snd_pcm_runtime *runtime = substream->runtime;1147	struct snd_trident_voice *voice = runtime->private_data;1148	struct snd_trident_voice *evoice = voice->extra;1149 1150	spin_lock_irq(&trident->reg_lock);1151 1152	voice->LBA = runtime->dma_addr;1153	voice->Delta = snd_trident_convert_adc_rate(runtime->rate);1154	voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);1155 1156	// Set voice parameters1157	voice->CSO = 0;1158	voice->ESO = runtime->buffer_size - 1;		/* in samples */1159	voice->CTRL = snd_trident_control_mode(substream);1160	voice->FMC = 0;1161	voice->RVol = 0;1162	voice->CVol = 0;1163	voice->GVSel = 1;1164	voice->Pan = T4D_DEFAULT_PCM_PAN;1165	voice->Vol = 0;1166	voice->EC = 0;1167	voice->Alpha = 0;1168	voice->FMS = 0;1169 1170	voice->Attribute = (2 << (30-16)) |1171			   (2 << (26-16)) |1172			   (2 << (24-16)) |1173			   (1 << (23-16));1174 1175	snd_trident_write_voice_regs(trident, voice);1176 1177	if (evoice != NULL) {1178		evoice->Delta = snd_trident_convert_rate(runtime->rate);1179		evoice->spurious_threshold = voice->spurious_threshold;1180		evoice->LBA = voice->LBA;1181		evoice->CSO = 0;1182		evoice->ESO = (runtime->period_size * 2) + 20 - 1; /* in samples, 20 means correction */1183		evoice->CTRL = voice->CTRL;1184		evoice->FMC = 3;1185		evoice->GVSel = 0;1186		evoice->EC = 0;1187		evoice->Alpha = 0;1188		evoice->FMS = 0;1189		evoice->Vol = 0x3ff;			/* mute */1190		evoice->RVol = evoice->CVol = 0x7f;	/* mute */1191		evoice->Pan = 0x7f;			/* mute */1192		evoice->Attribute = 0;1193		snd_trident_write_voice_regs(trident, evoice);1194		evoice->isync2 = 1;1195		evoice->isync_mark = runtime->period_size;1196		evoice->ESO = (runtime->period_size * 2) - 1;1197	}1198	1199	spin_unlock_irq(&trident->reg_lock);1200	return 0;1201}1202 1203/*---------------------------------------------------------------------------1204   snd_trident_foldback_prepare1205  1206   Description: Prepare foldback capture device for playback.1207  1208   Parameters:  substream  - PCM substream class1209  1210   Returns:     Error status1211  1212  ---------------------------------------------------------------------------*/1213 1214static int snd_trident_foldback_prepare(struct snd_pcm_substream *substream)1215{1216	struct snd_trident *trident = snd_pcm_substream_chip(substream);1217	struct snd_pcm_runtime *runtime = substream->runtime;1218	struct snd_trident_voice *voice = runtime->private_data;1219	struct snd_trident_voice *evoice = voice->extra;1220 1221	spin_lock_irq(&trident->reg_lock);1222 1223	/* Set channel buffer Address */1224	if (voice->memblk)1225		voice->LBA = voice->memblk->offset;1226	else1227		voice->LBA = runtime->dma_addr;1228 1229	/* set target ESO for channel */1230	voice->ESO = runtime->buffer_size - 1;	/* in samples */1231 1232	/* set sample rate */1233	voice->Delta = 0x1000;1234	voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);1235 1236	voice->CSO = 0;1237	voice->CTRL = snd_trident_control_mode(substream);1238	voice->FMC = 3;1239	voice->RVol = 0x7f;1240	voice->CVol = 0x7f;1241	voice->GVSel = 1;1242	voice->Pan = 0x7f;	/* mute */1243	voice->Vol = 0x3ff;	/* mute */1244	voice->EC = 0;1245	voice->Alpha = 0;1246	voice->FMS = 0;1247	voice->Attribute = 0;1248 1249	/* set up capture channel */1250	outb(((voice->number & 0x3f) | 0x80), TRID_REG(trident, T4D_RCI + voice->foldback_chan));1251 1252	snd_trident_write_voice_regs(trident, voice);1253 1254	if (evoice != NULL) {1255		evoice->Delta = voice->Delta;1256		evoice->spurious_threshold = voice->spurious_threshold;1257		evoice->LBA = voice->LBA;1258		evoice->CSO = 0;1259		evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */1260		evoice->CTRL = voice->CTRL;1261		evoice->FMC = 3;1262		evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;1263		evoice->EC = 0;1264		evoice->Alpha = 0;1265		evoice->FMS = 0;1266		evoice->Vol = 0x3ff;			/* mute */1267		evoice->RVol = evoice->CVol = 0x7f;	/* mute */1268		evoice->Pan = 0x7f;			/* mute */1269		evoice->Attribute = 0;1270		snd_trident_write_voice_regs(trident, evoice);1271		evoice->isync2 = 1;1272		evoice->isync_mark = runtime->period_size;1273		evoice->ESO = (runtime->period_size * 2) - 1;1274	}1275 1276	spin_unlock_irq(&trident->reg_lock);1277	return 0;1278}1279 1280/*---------------------------------------------------------------------------1281   snd_trident_spdif_hw_params1282  1283   Description: Set the hardware parameters for the spdif device.1284  1285   Parameters:  substream  - PCM substream class1286		hw_params  - hardware parameters1287  1288   Returns:     Error status1289  1290  ---------------------------------------------------------------------------*/1291 1292static int snd_trident_spdif_hw_params(struct snd_pcm_substream *substream,1293				       struct snd_pcm_hw_params *hw_params)1294{1295	struct snd_trident *trident = snd_pcm_substream_chip(substream);1296	unsigned int old_bits = 0, change = 0;1297	int err;1298 1299	err = snd_trident_allocate_pcm_mem(substream, hw_params);1300	if (err < 0)1301		return err;1302 1303	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {1304		err = snd_trident_allocate_evoice(substream, hw_params);1305		if (err < 0)1306			return err;1307	}1308 1309	/* prepare SPDIF channel */1310	spin_lock_irq(&trident->reg_lock);1311	old_bits = trident->spdif_pcm_bits;1312	if (old_bits & IEC958_AES0_PROFESSIONAL)1313		trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS;1314	else1315		trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24);1316	if (params_rate(hw_params) >= 48000) {1317		trident->spdif_pcm_ctrl = 0x3c;	// 48000 Hz1318		trident->spdif_pcm_bits |=1319			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?1320				IEC958_AES0_PRO_FS_48000 :1321				(IEC958_AES3_CON_FS_48000 << 24);1322	}1323	else if (params_rate(hw_params) >= 44100) {1324		trident->spdif_pcm_ctrl = 0x3e;	// 44100 Hz1325		trident->spdif_pcm_bits |=1326			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?1327				IEC958_AES0_PRO_FS_44100 :1328				(IEC958_AES3_CON_FS_44100 << 24);1329	}1330	else {1331		trident->spdif_pcm_ctrl = 0x3d;	// 32000 Hz1332		trident->spdif_pcm_bits |=1333			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?1334				IEC958_AES0_PRO_FS_32000 :1335				(IEC958_AES3_CON_FS_32000 << 24);1336	}1337	change = old_bits != trident->spdif_pcm_bits;1338	spin_unlock_irq(&trident->reg_lock);1339 1340	if (change)1341		snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE, &trident->spdif_pcm_ctl->id);1342 1343	return 0;1344}1345 1346/*---------------------------------------------------------------------------1347   snd_trident_spdif_prepare1348  1349   Description: Prepare SPDIF device for playback.1350  1351   Parameters:  substream  - PCM substream class1352  1353   Returns:     Error status1354  1355  ---------------------------------------------------------------------------*/1356 1357static int snd_trident_spdif_prepare(struct snd_pcm_substream *substream)1358{1359	struct snd_trident *trident = snd_pcm_substream_chip(substream);1360	struct snd_pcm_runtime *runtime = substream->runtime;1361	struct snd_trident_voice *voice = runtime->private_data;1362	struct snd_trident_voice *evoice = voice->extra;1363	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];1364	unsigned int RESO, LBAO;1365	unsigned int temp;1366 1367	spin_lock_irq(&trident->reg_lock);1368 1369	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {1370 1371		/* set delta (rate) value */1372		voice->Delta = snd_trident_convert_rate(runtime->rate);1373		voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);1374 1375		/* set Loop Back Address */1376		LBAO = runtime->dma_addr;1377		if (voice->memblk)1378			voice->LBA = voice->memblk->offset;1379		else1380			voice->LBA = LBAO;1381 1382		voice->isync = 1;1383		voice->isync3 = 1;1384		voice->isync_mark = runtime->period_size;1385		voice->isync_max = runtime->buffer_size;1386 1387		/* set target ESO for channel */1388		RESO = runtime->buffer_size - 1;1389		voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;1390 1391		/* set ctrl mode */1392		voice->CTRL = snd_trident_control_mode(substream);1393 1394		voice->FMC = 3;1395		voice->RVol = 0x7f;1396		voice->CVol = 0x7f;1397		voice->GVSel = 1;1398		voice->Pan = 0x7f;1399		voice->Vol = 0x3ff;1400		voice->EC = 0;1401		voice->CSO = 0;1402		voice->Alpha = 0;1403		voice->FMS = 0;1404		voice->Attribute = 0;1405 1406		/* prepare surrogate IRQ channel */1407		snd_trident_write_voice_regs(trident, voice);1408 1409		outw((RESO & 0xffff), TRID_REG(trident, NX_SPESO));1410		outb((RESO >> 16), TRID_REG(trident, NX_SPESO + 2));1411		outl((LBAO & 0xfffffffc), TRID_REG(trident, NX_SPLBA));1412		outw((voice->CSO & 0xffff), TRID_REG(trident, NX_SPCTRL_SPCSO));1413		outb((voice->CSO >> 16), TRID_REG(trident, NX_SPCTRL_SPCSO + 2));1414 1415		/* set SPDIF setting */1416		outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));1417		outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));1418 1419	} else {	/* SiS */1420	1421		/* set delta (rate) value */1422		voice->Delta = 0x800;1423		voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);1424 1425		/* set Loop Begin Address */1426		if (voice->memblk)1427			voice->LBA = voice->memblk->offset;1428		else1429			voice->LBA = runtime->dma_addr;1430 1431		voice->CSO = 0;1432		voice->ESO = runtime->buffer_size - 1;	/* in samples */1433		voice->CTRL = snd_trident_control_mode(substream);1434		voice->FMC = 3;1435		voice->GVSel = 1;1436		voice->EC = 0;1437		voice->Alpha = 0;1438		voice->FMS = 0;1439		voice->Vol = mix->vol;1440		voice->RVol = mix->rvol;1441		voice->CVol = mix->cvol;1442		voice->Pan = mix->pan;1443		voice->Attribute = (1<<(30-16))|(7<<(26-16))|1444				   (0<<(24-16))|(0<<(19-16));1445 1446		snd_trident_write_voice_regs(trident, voice);1447 1448		if (evoice != NULL) {1449			evoice->Delta = voice->Delta;1450			evoice->spurious_threshold = voice->spurious_threshold;1451			evoice->LBA = voice->LBA;1452			evoice->CSO = 0;1453			evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */1454			evoice->CTRL = voice->CTRL;1455			evoice->FMC = 3;1456			evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;1457			evoice->EC = 0;1458			evoice->Alpha = 0;1459			evoice->FMS = 0;1460			evoice->Vol = 0x3ff;			/* mute */1461			evoice->RVol = evoice->CVol = 0x7f;	/* mute */1462			evoice->Pan = 0x7f;			/* mute */1463			evoice->Attribute = 0;1464			snd_trident_write_voice_regs(trident, evoice);1465			evoice->isync2 = 1;1466			evoice->isync_mark = runtime->period_size;1467			evoice->ESO = (runtime->period_size * 2) - 1;1468		}1469 1470		outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));1471		temp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));1472		temp &= ~(1<<19);1473		outl(temp, TRID_REG(trident, T4D_LFO_GC_CIR));1474		temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));1475		temp |= SPDIF_EN;1476		outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));1477	}1478 1479	spin_unlock_irq(&trident->reg_lock);1480 1481	return 0;1482}1483 1484/*---------------------------------------------------------------------------1485   snd_trident_trigger1486  1487   Description: Start/stop devices1488  1489   Parameters:  substream  - PCM substream class1490   		cmd	- trigger command (STOP, GO)1491  1492   Returns:     Error status1493  1494  ---------------------------------------------------------------------------*/1495 1496static int snd_trident_trigger(struct snd_pcm_substream *substream,1497			       int cmd)1498				    1499{1500	struct snd_trident *trident = snd_pcm_substream_chip(substream);1501	struct snd_pcm_substream *s;1502	unsigned int what, whati, capture_flag, spdif_flag;1503	struct snd_trident_voice *voice, *evoice;1504	unsigned int val, go;1505 1506	switch (cmd) {1507	case SNDRV_PCM_TRIGGER_START:1508	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:1509	case SNDRV_PCM_TRIGGER_RESUME:1510		go = 1;1511		break;1512	case SNDRV_PCM_TRIGGER_STOP:1513	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:1514	case SNDRV_PCM_TRIGGER_SUSPEND:1515		go = 0;1516		break;1517	default:1518		return -EINVAL;1519	}1520	what = whati = capture_flag = spdif_flag = 0;1521	spin_lock(&trident->reg_lock);1522	val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;1523	snd_pcm_group_for_each_entry(s, substream) {1524		if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) {1525			voice = s->runtime->private_data;1526			evoice = voice->extra;1527			what |= 1 << (voice->number & 0x1f);1528			if (evoice == NULL) {1529				whati |= 1 << (voice->number & 0x1f);1530			} else {1531				what |= 1 << (evoice->number & 0x1f);1532				whati |= 1 << (evoice->number & 0x1f);1533				if (go)1534					evoice->stimer = val;1535			}1536			if (go) {1537				voice->running = 1;1538				voice->stimer = val;1539			} else {1540				voice->running = 0;1541			}1542			snd_pcm_trigger_done(s, substream);1543			if (voice->capture)1544				capture_flag = 1;1545			if (voice->spdif)1546				spdif_flag = 1;1547		}1548	}1549	if (spdif_flag) {1550		if (trident->device != TRIDENT_DEVICE_ID_SI7018) {1551			outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));1552			val = trident->spdif_pcm_ctrl;1553			if (!go)1554				val &= ~(0x28);1555			outb(val, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));1556		} else {1557			outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));1558			val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN;1559			outl(val, TRID_REG(trident, SI_SERIAL_INTF_CTRL));1560		}1561	}1562	if (!go)1563		outl(what, TRID_REG(trident, T4D_STOP_B));1564	val = inl(TRID_REG(trident, T4D_AINTEN_B));1565	if (go) {1566		val |= whati;1567	} else {1568		val &= ~whati;1569	}1570	outl(val, TRID_REG(trident, T4D_AINTEN_B));1571	if (go) {1572		outl(what, TRID_REG(trident, T4D_START_B));1573 1574		if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)1575			outb(trident->bDMAStart, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));1576	} else {1577		if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)1578			outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));1579	}1580	spin_unlock(&trident->reg_lock);1581	return 0;1582}1583 1584/*---------------------------------------------------------------------------1585   snd_trident_playback_pointer1586  1587   Description: This routine return the playback position1588                1589   Parameters:	substream  - PCM substream class1590 1591   Returns:     position of buffer1592  1593  ---------------------------------------------------------------------------*/1594 1595static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream *substream)1596{1597	struct snd_trident *trident = snd_pcm_substream_chip(substream);1598	struct snd_pcm_runtime *runtime = substream->runtime;1599	struct snd_trident_voice *voice = runtime->private_data;1600	unsigned int cso;1601 1602	if (!voice->running)1603		return 0;1604 1605	spin_lock(&trident->reg_lock);1606 1607	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));1608 1609	if (trident->device != TRIDENT_DEVICE_ID_NX) {1610		cso = inw(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));1611	} else {		// ID_4DWAVE_NX1612		cso = (unsigned int) inl(TRID_REG(trident, CH_NX_DELTA_CSO)) & 0x00ffffff;1613	}1614 1615	spin_unlock(&trident->reg_lock);1616 1617	if (cso >= runtime->buffer_size)1618		cso = 0;1619 1620	return cso;1621}1622 1623/*---------------------------------------------------------------------------1624   snd_trident_capture_pointer1625  1626   Description: This routine return the capture position1627                1628   Parameters:   pcm1    - PCM device class1629 1630   Returns:     position of buffer1631  1632  ---------------------------------------------------------------------------*/1633 1634static snd_pcm_uframes_t snd_trident_capture_pointer(struct snd_pcm_substream *substream)1635{1636	struct snd_trident *trident = snd_pcm_substream_chip(substream);1637	struct snd_pcm_runtime *runtime = substream->runtime;1638	struct snd_trident_voice *voice = runtime->private_data;1639	unsigned int result;1640 1641	if (!voice->running)1642		return 0;1643 1644	result = inw(TRID_REG(trident, T4D_SBBL_SBCL));1645	if (runtime->channels > 1)1646		result >>= 1;1647	if (result > 0)1648		result = runtime->buffer_size - result;1649 1650	return result;1651}1652 1653/*---------------------------------------------------------------------------1654   snd_trident_spdif_pointer1655  1656   Description: This routine return the SPDIF playback position1657                1658   Parameters:	substream  - PCM substream class1659 1660   Returns:     position of buffer1661  1662  ---------------------------------------------------------------------------*/1663 1664static snd_pcm_uframes_t snd_trident_spdif_pointer(struct snd_pcm_substream *substream)1665{1666	struct snd_trident *trident = snd_pcm_substream_chip(substream);1667	struct snd_pcm_runtime *runtime = substream->runtime;1668	struct snd_trident_voice *voice = runtime->private_data;1669	unsigned int result;1670 1671	if (!voice->running)1672		return 0;1673 1674	result = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;1675 1676	return result;1677}1678 1679/*1680 *  Playback support device description1681 */1682 1683static const struct snd_pcm_hardware snd_trident_playback =1684{1685	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1686				 SNDRV_PCM_INFO_BLOCK_TRANSFER |1687				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |1688				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),1689	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |1690				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),1691	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,1692	.rate_min =		4000,1693	.rate_max =		48000,1694	.channels_min =		1,1695	.channels_max =		2,1696	.buffer_bytes_max =	(256*1024),1697	.period_bytes_min =	64,1698	.period_bytes_max =	(256*1024),1699	.periods_min =		1,1700	.periods_max =		1024,1701	.fifo_size =		0,1702};1703 1704/*1705 *  Capture support device description1706 */1707 1708static const struct snd_pcm_hardware snd_trident_capture =1709{1710	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1711				 SNDRV_PCM_INFO_BLOCK_TRANSFER |1712				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |1713				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),1714	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |1715				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),1716	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,1717	.rate_min =		4000,1718	.rate_max =		48000,1719	.channels_min =		1,1720	.channels_max =		2,1721	.buffer_bytes_max =	(128*1024),1722	.period_bytes_min =	64,1723	.period_bytes_max =	(128*1024),1724	.periods_min =		1,1725	.periods_max =		1024,1726	.fifo_size =		0,1727};1728 1729/*1730 *  Foldback capture support device description1731 */1732 1733static const struct snd_pcm_hardware snd_trident_foldback =1734{1735	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1736				 SNDRV_PCM_INFO_BLOCK_TRANSFER |1737				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |1738				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),1739	.formats =		SNDRV_PCM_FMTBIT_S16_LE,1740	.rates =		SNDRV_PCM_RATE_48000,1741	.rate_min =		48000,1742	.rate_max =		48000,1743	.channels_min =		2,1744	.channels_max =		2,1745	.buffer_bytes_max =	(128*1024),1746	.period_bytes_min =	64,1747	.period_bytes_max =	(128*1024),1748	.periods_min =		1,1749	.periods_max =		1024,1750	.fifo_size =		0,1751};1752 1753/*1754 *  SPDIF playback support device description1755 */1756 1757static const struct snd_pcm_hardware snd_trident_spdif =1758{1759	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1760				 SNDRV_PCM_INFO_BLOCK_TRANSFER |1761				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |1762				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),1763	.formats =		SNDRV_PCM_FMTBIT_S16_LE,1764	.rates =		(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |1765				 SNDRV_PCM_RATE_48000),1766	.rate_min =		32000,1767	.rate_max =		48000,1768	.channels_min =		2,1769	.channels_max =		2,1770	.buffer_bytes_max =	(128*1024),1771	.period_bytes_min =	64,1772	.period_bytes_max =	(128*1024),1773	.periods_min =		1,1774	.periods_max =		1024,1775	.fifo_size =		0,1776};1777 1778static const struct snd_pcm_hardware snd_trident_spdif_7018 =1779{1780	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1781				 SNDRV_PCM_INFO_BLOCK_TRANSFER |1782				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |1783				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),1784	.formats =		SNDRV_PCM_FMTBIT_S16_LE,1785	.rates =		SNDRV_PCM_RATE_48000,1786	.rate_min =		48000,1787	.rate_max =		48000,1788	.channels_min =		2,1789	.channels_max =		2,1790	.buffer_bytes_max =	(128*1024),1791	.period_bytes_min =	64,1792	.period_bytes_max =	(128*1024),1793	.periods_min =		1,1794	.periods_max =		1024,1795	.fifo_size =		0,1796};1797 1798static void snd_trident_pcm_free_substream(struct snd_pcm_runtime *runtime)1799{1800	struct snd_trident_voice *voice = runtime->private_data;1801	struct snd_trident *trident;1802 1803	if (voice) {1804		trident = voice->trident;1805		snd_trident_free_voice(trident, voice);1806	}1807}1808 1809static int snd_trident_playback_open(struct snd_pcm_substream *substream)1810{1811	struct snd_trident *trident = snd_pcm_substream_chip(substream);1812	struct snd_pcm_runtime *runtime = substream->runtime;1813	struct snd_trident_voice *voice;1814 1815	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);1816	if (voice == NULL)1817		return -EAGAIN;1818	snd_trident_pcm_mixer_build(trident, voice, substream);1819	voice->substream = substream;1820	runtime->private_data = voice;1821	runtime->private_free = snd_trident_pcm_free_substream;1822	runtime->hw = snd_trident_playback;1823	snd_pcm_set_sync(substream);1824	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);1825	return 0;1826}1827 1828/*---------------------------------------------------------------------------1829   snd_trident_playback_close1830  1831   Description: This routine will close the 4DWave playback device. For now 1832                we will simply free the dma transfer buffer.1833                1834   Parameters:	substream  - PCM substream class1835 1836  ---------------------------------------------------------------------------*/1837static int snd_trident_playback_close(struct snd_pcm_substream *substream)1838{1839	struct snd_trident *trident = snd_pcm_substream_chip(substream);1840	struct snd_pcm_runtime *runtime = substream->runtime;1841	struct snd_trident_voice *voice = runtime->private_data;1842 1843	snd_trident_pcm_mixer_free(trident, voice, substream);1844	return 0;1845}1846 1847/*---------------------------------------------------------------------------1848   snd_trident_spdif_open1849  1850   Description: This routine will open the 4DWave SPDIF device.1851 1852   Parameters:	substream  - PCM substream class1853 1854   Returns:     status  - success or failure flag1855  1856  ---------------------------------------------------------------------------*/1857 1858static int snd_trident_spdif_open(struct snd_pcm_substream *substream)1859{1860	struct snd_trident *trident = snd_pcm_substream_chip(substream);1861	struct snd_trident_voice *voice;1862	struct snd_pcm_runtime *runtime = substream->runtime;1863	1864	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);1865	if (voice == NULL)1866		return -EAGAIN;1867	voice->spdif = 1;1868	voice->substream = substream;1869	spin_lock_irq(&trident->reg_lock);1870	trident->spdif_pcm_bits = trident->spdif_bits;1871	spin_unlock_irq(&trident->reg_lock);1872 1873	runtime->private_data = voice;1874	runtime->private_free = snd_trident_pcm_free_substream;1875	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {1876		runtime->hw = snd_trident_spdif;1877	} else {1878		runtime->hw = snd_trident_spdif_7018;1879	}1880 1881	trident->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;1882	snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |1883		       SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);1884 1885	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);1886	return 0;1887}1888 1889 1890/*---------------------------------------------------------------------------1891   snd_trident_spdif_close1892  1893   Description: This routine will close the 4DWave SPDIF device.1894                1895   Parameters:	substream  - PCM substream class1896 1897  ---------------------------------------------------------------------------*/1898 1899static int snd_trident_spdif_close(struct snd_pcm_substream *substream)1900{1901	struct snd_trident *trident = snd_pcm_substream_chip(substream);1902	unsigned int temp;1903 1904	spin_lock_irq(&trident->reg_lock);1905	// restore default SPDIF setting1906	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {1907		outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));1908		outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));1909	} else {1910		outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));1911		temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));1912		if (trident->spdif_ctrl) {1913			temp |= SPDIF_EN;1914		} else {1915			temp &= ~SPDIF_EN;1916		}1917		outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));1918	}1919	spin_unlock_irq(&trident->reg_lock);1920	trident->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;1921	snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |1922		       SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);1923	return 0;1924}1925 1926/*---------------------------------------------------------------------------1927   snd_trident_capture_open1928  1929   Description: This routine will open the 4DWave capture device.1930 1931   Parameters:	substream  - PCM substream class1932 1933   Returns:     status  - success or failure flag1934 1935  ---------------------------------------------------------------------------*/1936 1937static int snd_trident_capture_open(struct snd_pcm_substream *substream)1938{1939	struct snd_trident *trident = snd_pcm_substream_chip(substream);1940	struct snd_trident_voice *voice;1941	struct snd_pcm_runtime *runtime = substream->runtime;1942 1943	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);1944	if (voice == NULL)1945		return -EAGAIN;1946	voice->capture = 1;1947	voice->substream = substream;1948	runtime->private_data = voice;1949	runtime->private_free = snd_trident_pcm_free_substream;1950	runtime->hw = snd_trident_capture;1951	snd_pcm_set_sync(substream);1952	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);1953	return 0;1954}1955 1956/*---------------------------------------------------------------------------1957   snd_trident_capture_close1958  1959   Description: This routine will close the 4DWave capture device. For now 1960                we will simply free the dma transfer buffer.1961                1962   Parameters:	substream  - PCM substream class1963 1964  ---------------------------------------------------------------------------*/1965static int snd_trident_capture_close(struct snd_pcm_substream *substream)1966{1967	return 0;1968}1969 1970/*---------------------------------------------------------------------------1971   snd_trident_foldback_open1972  1973   Description: This routine will open the 4DWave foldback capture device.1974 1975   Parameters:	substream  - PCM substream class1976 1977   Returns:     status  - success or failure flag1978 1979  ---------------------------------------------------------------------------*/1980 1981static int snd_trident_foldback_open(struct snd_pcm_substream *substream)1982{1983	struct snd_trident *trident = snd_pcm_substream_chip(substream);1984	struct snd_trident_voice *voice;1985	struct snd_pcm_runtime *runtime = substream->runtime;1986 1987	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);1988	if (voice == NULL)1989		return -EAGAIN;1990	voice->foldback_chan = substream->number;1991	voice->substream = substream;1992	runtime->private_data = voice;1993	runtime->private_free = snd_trident_pcm_free_substream;1994	runtime->hw = snd_trident_foldback;1995	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);1996	return 0;1997}1998 1999/*---------------------------------------------------------------------------2000   snd_trident_foldback_close2001  2002   Description: This routine will close the 4DWave foldback capture device. 2003		For now we will simply free the dma transfer buffer.2004                2005   Parameters:	substream  - PCM substream class2006 2007  ---------------------------------------------------------------------------*/2008static int snd_trident_foldback_close(struct snd_pcm_substream *substream)2009{2010	struct snd_trident *trident = snd_pcm_substream_chip(substream);2011	struct snd_trident_voice *voice;2012	struct snd_pcm_runtime *runtime = substream->runtime;2013	voice = runtime->private_data;2014	2015	/* stop capture channel */2016	spin_lock_irq(&trident->reg_lock);2017	outb(0x00, TRID_REG(trident, T4D_RCI + voice->foldback_chan));2018	spin_unlock_irq(&trident->reg_lock);2019	return 0;2020}2021 2022/*---------------------------------------------------------------------------2023   PCM operations2024  ---------------------------------------------------------------------------*/2025 2026static const struct snd_pcm_ops snd_trident_playback_ops = {2027	.open =		snd_trident_playback_open,2028	.close =	snd_trident_playback_close,2029	.hw_params =	snd_trident_hw_params,2030	.hw_free =	snd_trident_hw_free,2031	.prepare =	snd_trident_playback_prepare,2032	.trigger =	snd_trident_trigger,2033	.pointer =	snd_trident_playback_pointer,2034};2035 2036static const struct snd_pcm_ops snd_trident_nx_playback_ops = {2037	.open =		snd_trident_playback_open,2038	.close =	snd_trident_playback_close,2039	.hw_params =	snd_trident_hw_params,2040	.hw_free =	snd_trident_hw_free,2041	.prepare =	snd_trident_playback_prepare,2042	.trigger =	snd_trident_trigger,2043	.pointer =	snd_trident_playback_pointer,2044};2045 2046static const struct snd_pcm_ops snd_trident_capture_ops = {2047	.open =		snd_trident_capture_open,2048	.close =	snd_trident_capture_close,2049	.hw_params =	snd_trident_capture_hw_params,2050	.hw_free =	snd_trident_hw_free,2051	.prepare =	snd_trident_capture_prepare,2052	.trigger =	snd_trident_trigger,2053	.pointer =	snd_trident_capture_pointer,2054};2055 2056static const struct snd_pcm_ops snd_trident_si7018_capture_ops = {2057	.open =		snd_trident_capture_open,2058	.close =	snd_trident_capture_close,2059	.hw_params =	snd_trident_si7018_capture_hw_params,2060	.hw_free =	snd_trident_si7018_capture_hw_free,2061	.prepare =	snd_trident_si7018_capture_prepare,2062	.trigger =	snd_trident_trigger,2063	.pointer =	snd_trident_playback_pointer,2064};2065 2066static const struct snd_pcm_ops snd_trident_foldback_ops = {2067	.open =		snd_trident_foldback_open,2068	.close =	snd_trident_foldback_close,2069	.hw_params =	snd_trident_hw_params,2070	.hw_free =	snd_trident_hw_free,2071	.prepare =	snd_trident_foldback_prepare,2072	.trigger =	snd_trident_trigger,2073	.pointer =	snd_trident_playback_pointer,2074};2075 2076static const struct snd_pcm_ops snd_trident_nx_foldback_ops = {2077	.open =		snd_trident_foldback_open,2078	.close =	snd_trident_foldback_close,2079	.hw_params =	snd_trident_hw_params,2080	.hw_free =	snd_trident_hw_free,2081	.prepare =	snd_trident_foldback_prepare,2082	.trigger =	snd_trident_trigger,2083	.pointer =	snd_trident_playback_pointer,2084};2085 2086static const struct snd_pcm_ops snd_trident_spdif_ops = {2087	.open =		snd_trident_spdif_open,2088	.close =	snd_trident_spdif_close,2089	.hw_params =	snd_trident_spdif_hw_params,2090	.hw_free =	snd_trident_hw_free,2091	.prepare =	snd_trident_spdif_prepare,2092	.trigger =	snd_trident_trigger,2093	.pointer =	snd_trident_spdif_pointer,2094};2095 2096static const struct snd_pcm_ops snd_trident_spdif_7018_ops = {2097	.open =		snd_trident_spdif_open,2098	.close =	snd_trident_spdif_close,2099	.hw_params =	snd_trident_spdif_hw_params,2100	.hw_free =	snd_trident_hw_free,2101	.prepare =	snd_trident_spdif_prepare,2102	.trigger =	snd_trident_trigger,2103	.pointer =	snd_trident_playback_pointer,2104};2105 2106/*---------------------------------------------------------------------------2107   snd_trident_pcm2108  2109   Description: This routine registers the 4DWave device for PCM support.2110                2111   Parameters:  trident - pointer to target device class for 4DWave.2112 2113   Returns:     None2114  2115  ---------------------------------------------------------------------------*/2116 2117int snd_trident_pcm(struct snd_trident *trident, int device)2118{2119	struct snd_pcm *pcm;2120	int err;2121 2122	err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm);2123	if (err < 0)2124		return err;2125 2126	pcm->private_data = trident;2127 2128	if (trident->tlb.entries) {2129		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_nx_playback_ops);2130	} else {2131		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_playback_ops);2132	}2133	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,2134			trident->device != TRIDENT_DEVICE_ID_SI7018 ?2135			&snd_trident_capture_ops :2136			&snd_trident_si7018_capture_ops);2137 2138	pcm->info_flags = 0;2139	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;2140	strcpy(pcm->name, "Trident 4DWave");2141	trident->pcm = pcm;2142 2143	if (trident->tlb.entries) {2144		struct snd_pcm_substream *substream;2145		for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)2146			snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV_SG,2147						   &trident->pci->dev,2148						   64*1024, 128*1024);2149		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,2150					   SNDRV_DMA_TYPE_DEV,2151					   &trident->pci->dev,2152					   64*1024, 128*1024);2153	} else {2154		snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,2155					       &trident->pci->dev,2156					       64*1024, 128*1024);2157	}2158 2159	return 0;2160}2161 2162/*---------------------------------------------------------------------------2163   snd_trident_foldback_pcm2164  2165   Description: This routine registers the 4DWave device for foldback PCM support.2166                2167   Parameters:  trident - pointer to target device class for 4DWave.2168 2169   Returns:     None2170  2171  ---------------------------------------------------------------------------*/2172 2173int snd_trident_foldback_pcm(struct snd_trident *trident, int device)2174{2175	struct snd_pcm *foldback;2176	int err;2177	int num_chan = 3;2178	struct snd_pcm_substream *substream;2179 2180	if (trident->device == TRIDENT_DEVICE_ID_NX)2181		num_chan = 4;2182	err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback);2183	if (err < 0)2184		return err;2185 2186	foldback->private_data = trident;2187	if (trident->tlb.entries)2188		snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_nx_foldback_ops);2189	else2190		snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_foldback_ops);2191	foldback->info_flags = 0;2192	strcpy(foldback->name, "Trident 4DWave");2193	substream = foldback->streams[SNDRV_PCM_STREAM_CAPTURE].substream;2194	strcpy(substream->name, "Front Mixer");2195	substream = substream->next;2196	strcpy(substream->name, "Reverb Mixer");2197	substream = substream->next;2198	strcpy(substream->name, "Chorus Mixer");2199	if (num_chan == 4) {2200		substream = substream->next;2201		strcpy(substream->name, "Second AC'97 ADC");2202	}2203	trident->foldback = foldback;2204 2205	if (trident->tlb.entries)2206		snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV_SG,2207					       &trident->pci->dev,2208					       0, 128*1024);2209	else2210		snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV,2211					       &trident->pci->dev,2212					       64*1024, 128*1024);2213 2214	return 0;2215}2216 2217/*---------------------------------------------------------------------------2218   snd_trident_spdif2219  2220   Description: This routine registers the 4DWave-NX device for SPDIF support.2221                2222   Parameters:  trident - pointer to target device class for 4DWave-NX.2223 2224   Returns:     None2225  2226  ---------------------------------------------------------------------------*/2227 2228int snd_trident_spdif_pcm(struct snd_trident *trident, int device)2229{2230	struct snd_pcm *spdif;2231	int err;2232 2233	err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif);2234	if (err < 0)2235		return err;2236 2237	spdif->private_data = trident;2238	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {2239		snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_ops);2240	} else {2241		snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_7018_ops);2242	}2243	spdif->info_flags = 0;2244	strcpy(spdif->name, "Trident 4DWave IEC958");2245	trident->spdif = spdif;2246 2247	snd_pcm_set_managed_buffer_all(spdif, SNDRV_DMA_TYPE_DEV,2248				       &trident->pci->dev, 64*1024, 128*1024);2249 2250	return 0;2251}2252 2253/*2254 *  Mixer part2255 */2256 2257 2258/*---------------------------------------------------------------------------2259    snd_trident_spdif_control2260 2261    Description: enable/disable S/PDIF out from ac97 mixer2262  ---------------------------------------------------------------------------*/2263 2264#define snd_trident_spdif_control_info	snd_ctl_boolean_mono_info2265 2266static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol,2267					 struct snd_ctl_elem_value *ucontrol)2268{2269	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2270	unsigned char val;2271 2272	spin_lock_irq(&trident->reg_lock);2273	val = trident->spdif_ctrl;2274	ucontrol->value.integer.value[0] = val == kcontrol->private_value;2275	spin_unlock_irq(&trident->reg_lock);2276	return 0;2277}2278 2279static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol,2280					 struct snd_ctl_elem_value *ucontrol)2281{2282	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2283	unsigned char val;2284	int change;2285 2286	val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00;2287	spin_lock_irq(&trident->reg_lock);2288	/* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */2289	change = trident->spdif_ctrl != val;2290	trident->spdif_ctrl = val;2291	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {2292		if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0) {2293			outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));2294			outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));2295		}2296	} else {2297		if (trident->spdif == NULL) {2298			unsigned int temp;2299			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));2300			temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & ~SPDIF_EN;2301			if (val)2302				temp |= SPDIF_EN;2303			outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));2304		}2305	}2306	spin_unlock_irq(&trident->reg_lock);2307	return change;2308}2309 2310static const struct snd_kcontrol_new snd_trident_spdif_control =2311{2312	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2313	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),2314	.info =		snd_trident_spdif_control_info,2315	.get =		snd_trident_spdif_control_get,2316	.put =		snd_trident_spdif_control_put,2317	.private_value = 0x28,2318};2319 2320/*---------------------------------------------------------------------------2321    snd_trident_spdif_default2322 2323    Description: put/get the S/PDIF default settings2324  ---------------------------------------------------------------------------*/2325 2326static int snd_trident_spdif_default_info(struct snd_kcontrol *kcontrol,2327					  struct snd_ctl_elem_info *uinfo)2328{2329	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;2330	uinfo->count = 1;2331	return 0;2332}2333 2334static int snd_trident_spdif_default_get(struct snd_kcontrol *kcontrol,2335					 struct snd_ctl_elem_value *ucontrol)2336{2337	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2338 2339	spin_lock_irq(&trident->reg_lock);2340	ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;2341	ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff;2342	ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff;2343	ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff;2344	spin_unlock_irq(&trident->reg_lock);2345	return 0;2346}2347 2348static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol,2349					 struct snd_ctl_elem_value *ucontrol)2350{2351	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2352	unsigned int val;2353	int change;2354 2355	val = (ucontrol->value.iec958.status[0] << 0) |2356	      (ucontrol->value.iec958.status[1] << 8) |2357	      (ucontrol->value.iec958.status[2] << 16) |2358	      (ucontrol->value.iec958.status[3] << 24);2359	spin_lock_irq(&trident->reg_lock);2360	change = trident->spdif_bits != val;2361	trident->spdif_bits = val;2362	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {2363		if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0)2364			outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));2365	} else {2366		if (trident->spdif == NULL)2367			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));2368	}2369	spin_unlock_irq(&trident->reg_lock);2370	return change;2371}2372 2373static const struct snd_kcontrol_new snd_trident_spdif_default =2374{2375	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,2376	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),2377	.info =		snd_trident_spdif_default_info,2378	.get =		snd_trident_spdif_default_get,2379	.put =		snd_trident_spdif_default_put2380};2381 2382/*---------------------------------------------------------------------------2383    snd_trident_spdif_mask2384 2385    Description: put/get the S/PDIF mask2386  ---------------------------------------------------------------------------*/2387 2388static int snd_trident_spdif_mask_info(struct snd_kcontrol *kcontrol,2389				       struct snd_ctl_elem_info *uinfo)2390{2391	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;2392	uinfo->count = 1;2393	return 0;2394}2395 2396static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol,2397				      struct snd_ctl_elem_value *ucontrol)2398{2399	ucontrol->value.iec958.status[0] = 0xff;2400	ucontrol->value.iec958.status[1] = 0xff;2401	ucontrol->value.iec958.status[2] = 0xff;2402	ucontrol->value.iec958.status[3] = 0xff;2403	return 0;2404}2405 2406static const struct snd_kcontrol_new snd_trident_spdif_mask =2407{2408	.access =	SNDRV_CTL_ELEM_ACCESS_READ,2409	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,2410	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),2411	.info =		snd_trident_spdif_mask_info,2412	.get =		snd_trident_spdif_mask_get,2413};2414 2415/*---------------------------------------------------------------------------2416    snd_trident_spdif_stream2417 2418    Description: put/get the S/PDIF stream settings2419  ---------------------------------------------------------------------------*/2420 2421static int snd_trident_spdif_stream_info(struct snd_kcontrol *kcontrol,2422					 struct snd_ctl_elem_info *uinfo)2423{2424	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;2425	uinfo->count = 1;2426	return 0;2427}2428 2429static int snd_trident_spdif_stream_get(struct snd_kcontrol *kcontrol,2430					struct snd_ctl_elem_value *ucontrol)2431{2432	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2433 2434	spin_lock_irq(&trident->reg_lock);2435	ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;2436	ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff;2437	ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff;2438	ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff;2439	spin_unlock_irq(&trident->reg_lock);2440	return 0;2441}2442 2443static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol,2444					struct snd_ctl_elem_value *ucontrol)2445{2446	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2447	unsigned int val;2448	int change;2449 2450	val = (ucontrol->value.iec958.status[0] << 0) |2451	      (ucontrol->value.iec958.status[1] << 8) |2452	      (ucontrol->value.iec958.status[2] << 16) |2453	      (ucontrol->value.iec958.status[3] << 24);2454	spin_lock_irq(&trident->reg_lock);2455	change = trident->spdif_pcm_bits != val;2456	trident->spdif_pcm_bits = val;2457	if (trident->spdif != NULL) {2458		if (trident->device != TRIDENT_DEVICE_ID_SI7018) {2459			outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));2460		} else {2461			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));2462		}2463	}2464	spin_unlock_irq(&trident->reg_lock);2465	return change;2466}2467 2468static const struct snd_kcontrol_new snd_trident_spdif_stream =2469{2470	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,2471	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,2472	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),2473	.info =		snd_trident_spdif_stream_info,2474	.get =		snd_trident_spdif_stream_get,2475	.put =		snd_trident_spdif_stream_put2476};2477 2478/*---------------------------------------------------------------------------2479    snd_trident_ac97_control2480 2481    Description: enable/disable rear path for ac972482  ---------------------------------------------------------------------------*/2483 2484#define snd_trident_ac97_control_info	snd_ctl_boolean_mono_info2485 2486static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol,2487					struct snd_ctl_elem_value *ucontrol)2488{2489	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2490	unsigned char val;2491 2492	spin_lock_irq(&trident->reg_lock);2493	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));2494	ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0;2495	spin_unlock_irq(&trident->reg_lock);2496	return 0;2497}2498 2499static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol,2500					struct snd_ctl_elem_value *ucontrol)2501{2502	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2503	unsigned char val;2504	int change = 0;2505 2506	spin_lock_irq(&trident->reg_lock);2507	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));2508	val &= ~(1 << kcontrol->private_value);2509	if (ucontrol->value.integer.value[0])2510		val |= 1 << kcontrol->private_value;2511	change = val != trident->ac97_ctrl;2512	trident->ac97_ctrl = val;2513	outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));2514	spin_unlock_irq(&trident->reg_lock);2515	return change;2516}2517 2518static const struct snd_kcontrol_new snd_trident_ac97_rear_control =2519{2520	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2521	.name =         "Rear Path",2522	.info =		snd_trident_ac97_control_info,2523	.get =		snd_trident_ac97_control_get,2524	.put =		snd_trident_ac97_control_put,2525	.private_value = 4,2526};2527 2528/*---------------------------------------------------------------------------2529    snd_trident_vol_control2530 2531    Description: wave & music volume control2532  ---------------------------------------------------------------------------*/2533 2534static int snd_trident_vol_control_info(struct snd_kcontrol *kcontrol,2535					struct snd_ctl_elem_info *uinfo)2536{2537	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2538	uinfo->count = 2;2539	uinfo->value.integer.min = 0;2540	uinfo->value.integer.max = 255;2541	return 0;2542}2543 2544static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol,2545				       struct snd_ctl_elem_value *ucontrol)2546{2547	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2548	unsigned int val;2549 2550	val = trident->musicvol_wavevol;2551	ucontrol->value.integer.value[0] = 255 - ((val >> kcontrol->private_value) & 0xff);2552	ucontrol->value.integer.value[1] = 255 - ((val >> (kcontrol->private_value + 8)) & 0xff);2553	return 0;2554}2555 2556static const DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0);2557 2558static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,2559				       struct snd_ctl_elem_value *ucontrol)2560{2561	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2562	unsigned int val;2563	int change = 0;2564 2565	spin_lock_irq(&trident->reg_lock);2566	val = trident->musicvol_wavevol;2567	val &= ~(0xffff << kcontrol->private_value);2568	val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) |2569	        ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value;2570	change = val != trident->musicvol_wavevol;2571	outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));2572	spin_unlock_irq(&trident->reg_lock);2573	return change;2574}2575 2576static const struct snd_kcontrol_new snd_trident_vol_music_control =2577{2578	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2579	.name =         "Music Playback Volume",2580	.info =		snd_trident_vol_control_info,2581	.get =		snd_trident_vol_control_get,2582	.put =		snd_trident_vol_control_put,2583	.private_value = 16,2584	.tlv = { .p = db_scale_gvol },2585};2586 2587static const struct snd_kcontrol_new snd_trident_vol_wave_control =2588{2589	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2590	.name =         "Wave Playback Volume",2591	.info =		snd_trident_vol_control_info,2592	.get =		snd_trident_vol_control_get,2593	.put =		snd_trident_vol_control_put,2594	.private_value = 0,2595	.tlv = { .p = db_scale_gvol },2596};2597 2598/*---------------------------------------------------------------------------2599    snd_trident_pcm_vol_control2600 2601    Description: PCM front volume control2602  ---------------------------------------------------------------------------*/2603 2604static int snd_trident_pcm_vol_control_info(struct snd_kcontrol *kcontrol,2605					    struct snd_ctl_elem_info *uinfo)2606{2607	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2608 2609	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2610	uinfo->count = 1;2611	uinfo->value.integer.min = 0;2612	uinfo->value.integer.max = 255;2613	if (trident->device == TRIDENT_DEVICE_ID_SI7018)2614		uinfo->value.integer.max = 1023;2615	return 0;2616}2617 2618static int snd_trident_pcm_vol_control_get(struct snd_kcontrol *kcontrol,2619					   struct snd_ctl_elem_value *ucontrol)2620{2621	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2622	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2623 2624	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {2625		ucontrol->value.integer.value[0] = 1023 - mix->vol;2626	} else {2627		ucontrol->value.integer.value[0] = 255 - (mix->vol>>2);2628	}2629	return 0;2630}2631 2632static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol,2633					   struct snd_ctl_elem_value *ucontrol)2634{2635	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2636	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2637	unsigned int val;2638	int change = 0;2639 2640	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {2641		val = 1023 - (ucontrol->value.integer.value[0] & 1023);2642	} else {2643		val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2;2644	}2645	spin_lock_irq(&trident->reg_lock);2646	change = val != mix->vol;2647	mix->vol = val;2648	if (mix->voice != NULL)2649		snd_trident_write_vol_reg(trident, mix->voice, val);2650	spin_unlock_irq(&trident->reg_lock);2651	return change;2652}2653 2654static const struct snd_kcontrol_new snd_trident_pcm_vol_control =2655{2656	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2657	.name =         "PCM Front Playback Volume",2658	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,2659	.count =	32,2660	.info =		snd_trident_pcm_vol_control_info,2661	.get =		snd_trident_pcm_vol_control_get,2662	.put =		snd_trident_pcm_vol_control_put,2663	/* FIXME: no tlv yet */2664};2665 2666/*---------------------------------------------------------------------------2667    snd_trident_pcm_pan_control2668 2669    Description: PCM front pan control2670  ---------------------------------------------------------------------------*/2671 2672static int snd_trident_pcm_pan_control_info(struct snd_kcontrol *kcontrol,2673					    struct snd_ctl_elem_info *uinfo)2674{2675	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2676	uinfo->count = 1;2677	uinfo->value.integer.min = 0;2678	uinfo->value.integer.max = 127;2679	return 0;2680}2681 2682static int snd_trident_pcm_pan_control_get(struct snd_kcontrol *kcontrol,2683					   struct snd_ctl_elem_value *ucontrol)2684{2685	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2686	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2687 2688	ucontrol->value.integer.value[0] = mix->pan;2689	if (ucontrol->value.integer.value[0] & 0x40) {2690		ucontrol->value.integer.value[0] = (0x3f - (ucontrol->value.integer.value[0] & 0x3f));2691	} else {2692		ucontrol->value.integer.value[0] |= 0x40;2693	}2694	return 0;2695}2696 2697static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol,2698					   struct snd_ctl_elem_value *ucontrol)2699{2700	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2701	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2702	unsigned char val;2703	int change = 0;2704 2705	if (ucontrol->value.integer.value[0] & 0x40)2706		val = ucontrol->value.integer.value[0] & 0x3f;2707	else2708		val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40;2709	spin_lock_irq(&trident->reg_lock);2710	change = val != mix->pan;2711	mix->pan = val;2712	if (mix->voice != NULL)2713		snd_trident_write_pan_reg(trident, mix->voice, val);2714	spin_unlock_irq(&trident->reg_lock);2715	return change;2716}2717 2718static const struct snd_kcontrol_new snd_trident_pcm_pan_control =2719{2720	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2721	.name =         "PCM Pan Playback Control",2722	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,2723	.count =	32,2724	.info =		snd_trident_pcm_pan_control_info,2725	.get =		snd_trident_pcm_pan_control_get,2726	.put =		snd_trident_pcm_pan_control_put,2727};2728 2729/*---------------------------------------------------------------------------2730    snd_trident_pcm_rvol_control2731 2732    Description: PCM reverb volume control2733  ---------------------------------------------------------------------------*/2734 2735static int snd_trident_pcm_rvol_control_info(struct snd_kcontrol *kcontrol,2736					     struct snd_ctl_elem_info *uinfo)2737{2738	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2739	uinfo->count = 1;2740	uinfo->value.integer.min = 0;2741	uinfo->value.integer.max = 127;2742	return 0;2743}2744 2745static int snd_trident_pcm_rvol_control_get(struct snd_kcontrol *kcontrol,2746					    struct snd_ctl_elem_value *ucontrol)2747{2748	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2749	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2750 2751	ucontrol->value.integer.value[0] = 127 - mix->rvol;2752	return 0;2753}2754 2755static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,2756					    struct snd_ctl_elem_value *ucontrol)2757{2758	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2759	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2760	unsigned short val;2761	int change = 0;2762 2763	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);2764	spin_lock_irq(&trident->reg_lock);2765	change = val != mix->rvol;2766	mix->rvol = val;2767	if (mix->voice != NULL)2768		snd_trident_write_rvol_reg(trident, mix->voice, val);2769	spin_unlock_irq(&trident->reg_lock);2770	return change;2771}2772 2773static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);2774 2775static const struct snd_kcontrol_new snd_trident_pcm_rvol_control =2776{2777	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2778	.name =         "PCM Reverb Playback Volume",2779	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,2780	.count = 	32,2781	.info =		snd_trident_pcm_rvol_control_info,2782	.get =		snd_trident_pcm_rvol_control_get,2783	.put =		snd_trident_pcm_rvol_control_put,2784	.tlv = { .p = db_scale_crvol },2785};2786 2787/*---------------------------------------------------------------------------2788    snd_trident_pcm_cvol_control2789 2790    Description: PCM chorus volume control2791  ---------------------------------------------------------------------------*/2792 2793static int snd_trident_pcm_cvol_control_info(struct snd_kcontrol *kcontrol,2794					     struct snd_ctl_elem_info *uinfo)2795{2796	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;2797	uinfo->count = 1;2798	uinfo->value.integer.min = 0;2799	uinfo->value.integer.max = 127;2800	return 0;2801}2802 2803static int snd_trident_pcm_cvol_control_get(struct snd_kcontrol *kcontrol,2804					    struct snd_ctl_elem_value *ucontrol)2805{2806	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2807	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2808 2809	ucontrol->value.integer.value[0] = 127 - mix->cvol;2810	return 0;2811}2812 2813static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol,2814					    struct snd_ctl_elem_value *ucontrol)2815{2816	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);2817	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];2818	unsigned short val;2819	int change = 0;2820 2821	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);2822	spin_lock_irq(&trident->reg_lock);2823	change = val != mix->cvol;2824	mix->cvol = val;2825	if (mix->voice != NULL)2826		snd_trident_write_cvol_reg(trident, mix->voice, val);2827	spin_unlock_irq(&trident->reg_lock);2828	return change;2829}2830 2831static const struct snd_kcontrol_new snd_trident_pcm_cvol_control =2832{2833	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,2834	.name =         "PCM Chorus Playback Volume",2835	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,2836	.count =	32,2837	.info =		snd_trident_pcm_cvol_control_info,2838	.get =		snd_trident_pcm_cvol_control_get,2839	.put =		snd_trident_pcm_cvol_control_put,2840	.tlv = { .p = db_scale_crvol },2841};2842 2843static void snd_trident_notify_pcm_change1(struct snd_card *card,2844					   struct snd_kcontrol *kctl,2845					   int num, int activate)2846{2847	struct snd_ctl_elem_id id;2848 2849	if (! kctl)2850		return;2851	if (activate)2852		kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;2853	else2854		kctl->vd[num].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;2855	snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |2856		       SNDRV_CTL_EVENT_MASK_INFO,2857		       snd_ctl_build_ioff(&id, kctl, num));2858}2859 2860static void snd_trident_notify_pcm_change(struct snd_trident *trident,2861					  struct snd_trident_pcm_mixer *tmix,2862					  int num, int activate)2863{2864	snd_trident_notify_pcm_change1(trident->card, trident->ctl_vol, num, activate);2865	snd_trident_notify_pcm_change1(trident->card, trident->ctl_pan, num, activate);2866	snd_trident_notify_pcm_change1(trident->card, trident->ctl_rvol, num, activate);2867	snd_trident_notify_pcm_change1(trident->card, trident->ctl_cvol, num, activate);2868}2869 2870static int snd_trident_pcm_mixer_build(struct snd_trident *trident,2871				       struct snd_trident_voice *voice,2872				       struct snd_pcm_substream *substream)2873{2874	struct snd_trident_pcm_mixer *tmix;2875 2876	if (snd_BUG_ON(!trident || !voice || !substream))2877		return -EINVAL;2878	tmix = &trident->pcm_mixer[substream->number];2879	tmix->voice = voice;2880	tmix->vol = T4D_DEFAULT_PCM_VOL;2881	tmix->pan = T4D_DEFAULT_PCM_PAN;2882	tmix->rvol = T4D_DEFAULT_PCM_RVOL;2883	tmix->cvol = T4D_DEFAULT_PCM_CVOL;2884	snd_trident_notify_pcm_change(trident, tmix, substream->number, 1);2885	return 0;2886}2887 2888static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_trident_voice *voice, struct snd_pcm_substream *substream)2889{2890	struct snd_trident_pcm_mixer *tmix;2891 2892	if (snd_BUG_ON(!trident || !substream))2893		return -EINVAL;2894	tmix = &trident->pcm_mixer[substream->number];2895	tmix->voice = NULL;2896	snd_trident_notify_pcm_change(trident, tmix, substream->number, 0);2897	return 0;2898}2899 2900/*---------------------------------------------------------------------------2901   snd_trident_mixer2902  2903   Description: This routine registers the 4DWave device for mixer support.2904                2905   Parameters:  trident - pointer to target device class for 4DWave.2906 2907   Returns:     None2908  2909  ---------------------------------------------------------------------------*/2910 2911static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device)2912{2913	struct snd_ac97_template _ac97;2914	struct snd_card *card = trident->card;2915	struct snd_kcontrol *kctl;2916	struct snd_ctl_elem_value *uctl;2917	int idx, err, retries = 2;2918	static const struct snd_ac97_bus_ops ops = {2919		.write = snd_trident_codec_write,2920		.read = snd_trident_codec_read,2921	};2922 2923	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);2924	if (!uctl)2925		return -ENOMEM;2926 2927	err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus);2928	if (err < 0)2929		goto __out;2930 2931	memset(&_ac97, 0, sizeof(_ac97));2932	_ac97.private_data = trident;2933	trident->ac97_detect = 1;2934 2935      __again:2936	err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97);2937	if (err < 0) {2938		if (trident->device == TRIDENT_DEVICE_ID_SI7018) {2939			err = snd_trident_sis_reset(trident);2940			if (err < 0)2941				goto __out;2942			if (retries-- > 0)2943				goto __again;2944			err = -EIO;2945		}2946		goto __out;2947	}2948	2949	/* secondary codec? */2950	if (trident->device == TRIDENT_DEVICE_ID_SI7018 &&2951	    (inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0) {2952		_ac97.num = 1;2953		err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97_sec);2954		if (err < 0)2955			dev_err(trident->card->dev,2956				"SI7018: the secondary codec - invalid access\n");2957#if 0	// only for my testing purpose --jk2958		{2959			struct snd_ac97 *mc97;2960			err = snd_ac97_modem(trident->card, &_ac97, &mc97);2961			if (err < 0)2962				dev_err(trident->card->dev,2963					"snd_ac97_modem returned error %i\n", err);2964		}2965#endif2966	}2967	2968	trident->ac97_detect = 0;2969 2970	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {2971		kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident);2972		err = snd_ctl_add(card, kctl);2973		if (err < 0)2974			goto __out;2975		kctl->put(kctl, uctl);2976		kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident);2977		err = snd_ctl_add(card, kctl);2978		if (err < 0)2979			goto __out;2980		kctl->put(kctl, uctl);2981		outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));2982	} else {2983		outl(trident->musicvol_wavevol = 0xffff0000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));2984	}2985 2986	for (idx = 0; idx < 32; idx++) {2987		struct snd_trident_pcm_mixer *tmix;2988		2989		tmix = &trident->pcm_mixer[idx];2990		tmix->voice = NULL;2991	}2992	trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident);2993	if (!trident->ctl_vol)2994		goto __nomem;2995	err = snd_ctl_add(card, trident->ctl_vol);2996	if (err)2997		goto __out;2998		2999	trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident);3000	if (!trident->ctl_pan)3001		goto __nomem;3002	err = snd_ctl_add(card, trident->ctl_pan);3003	if (err)3004		goto __out;3005 3006	trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident);3007	if (!trident->ctl_rvol)3008		goto __nomem;3009	err = snd_ctl_add(card, trident->ctl_rvol);3010	if (err)3011		goto __out;3012 3013	trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident);3014	if (!trident->ctl_cvol)3015		goto __nomem;3016	err = snd_ctl_add(card, trident->ctl_cvol);3017	if (err)3018		goto __out;3019 3020	if (trident->device == TRIDENT_DEVICE_ID_NX) {3021		kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident);3022		err = snd_ctl_add(card, kctl);3023		if (err < 0)3024			goto __out;3025		kctl->put(kctl, uctl);3026	}3027	if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {3028 3029		kctl = snd_ctl_new1(&snd_trident_spdif_control, trident);3030		if (kctl == NULL) {3031			err = -ENOMEM;3032			goto __out;3033		}3034		if (trident->ac97->ext_id & AC97_EI_SPDIF)3035			kctl->id.index++;3036		if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF))3037			kctl->id.index++;3038		idx = kctl->id.index;3039		err = snd_ctl_add(card, kctl);3040		if (err < 0)3041			goto __out;3042		kctl->put(kctl, uctl);3043 3044		kctl = snd_ctl_new1(&snd_trident_spdif_default, trident);3045		if (kctl == NULL) {3046			err = -ENOMEM;3047			goto __out;3048		}3049		kctl->id.index = idx;3050		kctl->id.device = pcm_spdif_device;3051		err = snd_ctl_add(card, kctl);3052		if (err < 0)3053			goto __out;3054 3055		kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident);3056		if (kctl == NULL) {3057			err = -ENOMEM;3058			goto __out;3059		}3060		kctl->id.index = idx;3061		kctl->id.device = pcm_spdif_device;3062		err = snd_ctl_add(card, kctl);3063		if (err < 0)3064			goto __out;3065 3066		kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident);3067		if (kctl == NULL) {3068			err = -ENOMEM;3069			goto __out;3070		}3071		kctl->id.index = idx;3072		kctl->id.device = pcm_spdif_device;3073		err = snd_ctl_add(card, kctl);3074		if (err < 0)3075			goto __out;3076		trident->spdif_pcm_ctl = kctl;3077	}3078 3079	err = 0;3080	goto __out;3081 3082 __nomem:3083	err = -ENOMEM;3084 3085 __out:3086	kfree(uctl);3087 3088	return err;3089}3090 3091/*3092 * gameport interface3093 */3094 3095#if IS_REACHABLE(CONFIG_GAMEPORT)3096 3097static unsigned char snd_trident_gameport_read(struct gameport *gameport)3098{3099	struct snd_trident *chip = gameport_get_port_data(gameport);3100 3101	if (snd_BUG_ON(!chip))3102		return 0;3103	return inb(TRID_REG(chip, GAMEPORT_LEGACY));3104}3105 3106static void snd_trident_gameport_trigger(struct gameport *gameport)3107{3108	struct snd_trident *chip = gameport_get_port_data(gameport);3109 3110	if (snd_BUG_ON(!chip))3111		return;3112	outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));3113}3114 3115static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)3116{3117	struct snd_trident *chip = gameport_get_port_data(gameport);3118	int i;3119 3120	if (snd_BUG_ON(!chip))3121		return 0;3122 3123	*buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;3124 3125	for (i = 0; i < 4; i++) {3126		axes[i] = inw(TRID_REG(chip, GAMEPORT_AXES + i * 2));3127		if (axes[i] == 0xffff) axes[i] = -1;3128	}3129        3130        return 0;3131}3132 3133static int snd_trident_gameport_open(struct gameport *gameport, int mode)3134{3135	struct snd_trident *chip = gameport_get_port_data(gameport);3136 3137	if (snd_BUG_ON(!chip))3138		return 0;3139 3140	switch (mode) {3141		case GAMEPORT_MODE_COOKED:3142			outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR));3143			msleep(20);3144			return 0;3145		case GAMEPORT_MODE_RAW:3146			outb(0, TRID_REG(chip, GAMEPORT_GCR));3147			return 0;3148		default:3149			return -1;3150	}3151}3152 3153int snd_trident_create_gameport(struct snd_trident *chip)3154{3155	struct gameport *gp;3156 3157	chip->gameport = gp = gameport_allocate_port();3158	if (!gp) {3159		dev_err(chip->card->dev,3160			"cannot allocate memory for gameport\n");3161		return -ENOMEM;3162	}3163 3164	gameport_set_name(gp, "Trident 4DWave");3165	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));3166	gameport_set_dev_parent(gp, &chip->pci->dev);3167 3168	gameport_set_port_data(gp, chip);3169	gp->fuzz = 64;3170	gp->read = snd_trident_gameport_read;3171	gp->trigger = snd_trident_gameport_trigger;3172	gp->cooked_read = snd_trident_gameport_cooked_read;3173	gp->open = snd_trident_gameport_open;3174 3175	gameport_register_port(gp);3176 3177	return 0;3178}3179 3180static inline void snd_trident_free_gameport(struct snd_trident *chip)3181{3182	if (chip->gameport) {3183		gameport_unregister_port(chip->gameport);3184		chip->gameport = NULL;3185	}3186}3187#else3188int snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }3189static inline void snd_trident_free_gameport(struct snd_trident *chip) { }3190#endif /* CONFIG_GAMEPORT */3191 3192/*3193 * delay for 1 tick3194 */3195static inline void do_delay(struct snd_trident *chip)3196{3197	schedule_timeout_uninterruptible(1);3198}3199 3200/*3201 *  SiS reset routine3202 */3203 3204static int snd_trident_sis_reset(struct snd_trident *trident)3205{3206	unsigned long end_time;3207	unsigned int i;3208	int r;3209 3210	r = trident->in_suspend ? 0 : 2;	/* count of retries */3211      __si7018_retry:3212	pci_write_config_byte(trident->pci, 0x46, 0x04);	/* SOFTWARE RESET */3213	udelay(100);3214	pci_write_config_byte(trident->pci, 0x46, 0x00);3215	udelay(100);3216	/* disable AC97 GPIO interrupt */3217	outb(0x00, TRID_REG(trident, SI_AC97_GPIO));3218	/* initialize serial interface, force cold reset */3219	i = PCMOUT|SURROUT|CENTEROUT|LFEOUT|SECONDARY_ID|COLD_RESET;3220	outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));3221	udelay(1000);3222	/* remove cold reset */3223	i &= ~COLD_RESET;3224	outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));3225	udelay(2000);3226	/* wait, until the codec is ready */3227	end_time = (jiffies + (HZ * 3) / 4) + 1;3228	do {3229		if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0)3230			goto __si7018_ok;3231		do_delay(trident);3232	} while (time_after_eq(end_time, jiffies));3233	dev_err(trident->card->dev, "AC'97 codec ready error [0x%x]\n",3234		inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)));3235	if (r-- > 0) {3236		end_time = jiffies + HZ;3237		do {3238			do_delay(trident);3239		} while (time_after_eq(end_time, jiffies));3240		goto __si7018_retry;3241	}3242      __si7018_ok:3243	/* wait for the second codec */3244	do {3245		if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_SECONDARY_READY) != 0)3246			break;3247		do_delay(trident);3248	} while (time_after_eq(end_time, jiffies));3249	/* enable 64 channel mode */3250	outl(BANK_B_EN, TRID_REG(trident, T4D_LFO_GC_CIR));3251	return 0;3252}3253 3254/*  3255 *  /proc interface3256 */3257 3258static void snd_trident_proc_read(struct snd_info_entry *entry, 3259				  struct snd_info_buffer *buffer)3260{3261	struct snd_trident *trident = entry->private_data;3262	char *s;3263 3264	switch (trident->device) {3265	case TRIDENT_DEVICE_ID_SI7018:3266		s = "SiS 7018 Audio";3267		break;3268	case TRIDENT_DEVICE_ID_DX:3269		s = "Trident 4DWave PCI DX";3270		break;3271	case TRIDENT_DEVICE_ID_NX:3272		s = "Trident 4DWave PCI NX";3273		break;3274	default:3275		s = "???";3276	}3277	snd_iprintf(buffer, "%s\n\n", s);3278	snd_iprintf(buffer, "Spurious IRQs    : %d\n", trident->spurious_irq_count);3279	snd_iprintf(buffer, "Spurious IRQ dlta: %d\n", trident->spurious_irq_max_delta);3280	if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018)3281		snd_iprintf(buffer, "IEC958 Mixer Out : %s\n", trident->spdif_ctrl == 0x28 ? "on" : "off");3282	if (trident->device == TRIDENT_DEVICE_ID_NX) {3283		snd_iprintf(buffer, "Rear Speakers    : %s\n", trident->ac97_ctrl & 0x00000010 ? "on" : "off");3284		if (trident->tlb.entries) {3285			snd_iprintf(buffer,"\nVirtual Memory\n");3286			snd_iprintf(buffer, "Memory Maximum : %d\n", trident->tlb.memhdr->size);3287			snd_iprintf(buffer, "Memory Used    : %d\n", trident->tlb.memhdr->used);3288			snd_iprintf(buffer, "Memory Free    : %d\n", snd_util_mem_avail(trident->tlb.memhdr));3289		}3290	}3291}3292 3293static void snd_trident_proc_init(struct snd_trident *trident)3294{3295	const char *s = "trident";3296	3297	if (trident->device == TRIDENT_DEVICE_ID_SI7018)3298		s = "sis7018";3299	snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read);3300}3301 3302/*---------------------------------------------------------------------------3303   snd_trident_tlb_alloc3304  3305   Description: Allocate and set up the TLB page table on 4D NX.3306		Each entry has 4 bytes (physical PCI address).3307                3308   Parameters:  trident - pointer to target device class for 4DWave.3309 3310   Returns:     0 or negative error code3311  3312  ---------------------------------------------------------------------------*/3313 3314static int snd_trident_tlb_alloc(struct snd_trident *trident)3315{3316	int i;3317 3318	/* TLB array must be aligned to 16kB !!! so we allocate3319	   32kB region and correct offset when necessary */3320 3321	trident->tlb.buffer =3322		snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,3323				     2 * SNDRV_TRIDENT_MAX_PAGES * 4);3324	if (!trident->tlb.buffer) {3325		dev_err(trident->card->dev, "unable to allocate TLB buffer\n");3326		return -ENOMEM;3327	}3328	trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer->area, SNDRV_TRIDENT_MAX_PAGES * 4);3329	trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer->addr, SNDRV_TRIDENT_MAX_PAGES * 4);3330 3331	/* allocate and setup silent page and initialise TLB entries */3332	trident->tlb.silent_page =3333		snd_devm_alloc_pages(&trident->pci->dev, SNDRV_DMA_TYPE_DEV,3334				     SNDRV_TRIDENT_PAGE_SIZE);3335	if (!trident->tlb.silent_page) {3336		dev_err(trident->card->dev, "unable to allocate silent page\n");3337		return -ENOMEM;3338	}3339	memset(trident->tlb.silent_page->area, 0, SNDRV_TRIDENT_PAGE_SIZE);3340	for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++)3341		trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page->addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));3342 3343	/* use emu memory block manager code to manage tlb page allocation */3344	trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);3345	if (trident->tlb.memhdr == NULL)3346		return -ENOMEM;3347 3348	trident->tlb.memhdr->block_extra_size = sizeof(struct snd_trident_memblk_arg);3349	return 0;3350}3351 3352/*3353 * initialize 4D DX chip3354 */3355 3356static void snd_trident_stop_all_voices(struct snd_trident *trident)3357{3358	outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));3359	outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));3360	outl(0, TRID_REG(trident, T4D_AINTEN_A));3361	outl(0, TRID_REG(trident, T4D_AINTEN_B));3362}3363 3364static int snd_trident_4d_dx_init(struct snd_trident *trident)3365{3366	struct pci_dev *pci = trident->pci;3367	unsigned long end_time;3368 3369	/* reset the legacy configuration and whole audio/wavetable block */3370	pci_write_config_dword(pci, 0x40, 0);	/* DDMA */3371	pci_write_config_byte(pci, 0x44, 0);	/* ports */3372	pci_write_config_byte(pci, 0x45, 0);	/* Legacy DMA */3373	pci_write_config_byte(pci, 0x46, 4); /* reset */3374	udelay(100);3375	pci_write_config_byte(pci, 0x46, 0); /* release reset */3376	udelay(100);3377	3378	/* warm reset of the AC'97 codec */3379	outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));3380	udelay(100);3381	outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));3382	/* DAC on, disable SB IRQ and try to force ADC valid signal */3383	trident->ac97_ctrl = 0x0000004a;3384	outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));3385	/* wait, until the codec is ready */3386	end_time = (jiffies + (HZ * 3) / 4) + 1;3387	do {3388		if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010) != 0)3389			goto __dx_ok;3390		do_delay(trident);3391	} while (time_after_eq(end_time, jiffies));3392	dev_err(trident->card->dev, "AC'97 codec ready error\n");3393	return -EIO;3394 3395 __dx_ok:3396	snd_trident_stop_all_voices(trident);3397 3398	return 0;3399}3400 3401/*3402 * initialize 4D NX chip3403 */3404static int snd_trident_4d_nx_init(struct snd_trident *trident)3405{3406	struct pci_dev *pci = trident->pci;3407	unsigned long end_time;3408 3409	/* reset the legacy configuration and whole audio/wavetable block */3410	pci_write_config_dword(pci, 0x40, 0);	/* DDMA */3411	pci_write_config_byte(pci, 0x44, 0);	/* ports */3412	pci_write_config_byte(pci, 0x45, 0);	/* Legacy DMA */3413 3414	pci_write_config_byte(pci, 0x46, 1); /* reset */3415	udelay(100);3416	pci_write_config_byte(pci, 0x46, 0); /* release reset */3417	udelay(100);3418 3419	/* warm reset of the AC'97 codec */3420	outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));3421	udelay(100);3422	outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));3423	/* wait, until the codec is ready */3424	end_time = (jiffies + (HZ * 3) / 4) + 1;3425	do {3426		if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008) != 0)3427			goto __nx_ok;3428		do_delay(trident);3429	} while (time_after_eq(end_time, jiffies));3430	dev_err(trident->card->dev, "AC'97 codec ready error [0x%x]\n",3431		inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)));3432	return -EIO;3433 3434 __nx_ok:3435	/* DAC on */3436	trident->ac97_ctrl = 0x00000002;3437	outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));3438	/* disable SB IRQ */3439	outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT));3440 3441	snd_trident_stop_all_voices(trident);3442 3443	if (trident->tlb.entries != NULL) {3444		unsigned int i;3445		/* enable virtual addressing via TLB */3446		i = trident->tlb.entries_dmaaddr;3447		i |= 0x00000001;3448		outl(i, TRID_REG(trident, NX_TLBC));3449	} else {3450		outl(0, TRID_REG(trident, NX_TLBC));3451	}3452	/* initialize S/PDIF */3453	outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));3454	outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));3455 3456	return 0;3457}3458 3459/*3460 * initialize sis7018 chip3461 */3462static int snd_trident_sis_init(struct snd_trident *trident)3463{3464	int err;3465 3466	err = snd_trident_sis_reset(trident);3467	if (err < 0)3468		return err;3469 3470	snd_trident_stop_all_voices(trident);3471 3472	/* initialize S/PDIF */3473	outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));3474 3475	return 0;3476}3477 3478/*---------------------------------------------------------------------------3479   snd_trident_create3480  3481   Description: This routine will create the device specific class for3482                the 4DWave card. It will also perform basic initialization.3483                3484   Parameters:  card  - which card to create3485                pci   - interface to PCI bus resource info3486                dma1ptr - playback dma buffer3487                dma2ptr - capture dma buffer3488                irqptr  -  interrupt resource info3489 3490   Returns:     4DWave device class private data3491  3492  ---------------------------------------------------------------------------*/3493 3494int snd_trident_create(struct snd_card *card,3495		       struct pci_dev *pci,3496		       int pcm_streams,3497		       int pcm_spdif_device,3498		       int max_wavetable_size)3499{3500	struct snd_trident *trident = card->private_data;3501	int i, err;3502	struct snd_trident_voice *voice;3503	struct snd_trident_pcm_mixer *tmix;3504 3505	/* enable PCI device */3506	err = pcim_enable_device(pci);3507	if (err < 0)3508		return err;3509	/* check, if we can restrict PCI DMA transfers to 30 bits */3510	if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) {3511		dev_err(card->dev,3512			"architecture does not support 30bit PCI busmaster DMA\n");3513		return -ENXIO;3514	}3515	3516	trident->device = (pci->vendor << 16) | pci->device;3517	trident->card = card;3518	trident->pci = pci;3519	spin_lock_init(&trident->reg_lock);3520	spin_lock_init(&trident->event_lock);3521	spin_lock_init(&trident->voice_alloc);3522	if (pcm_streams < 1)3523		pcm_streams = 1;3524	if (pcm_streams > 32)3525		pcm_streams = 32;3526	trident->ChanPCM = pcm_streams;3527	if (max_wavetable_size < 0 )3528		max_wavetable_size = 0;3529	trident->synth.max_size = max_wavetable_size * 1024;3530	trident->irq = -1;3531	card->private_free = snd_trident_free;3532 3533	trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);3534	pci_set_master(pci);3535 3536	err = pci_request_regions(pci, "Trident Audio");3537	if (err < 0)3538		return err;3539	trident->port = pci_resource_start(pci, 0);3540 3541	if (devm_request_irq(&pci->dev, pci->irq, snd_trident_interrupt,3542			     IRQF_SHARED, KBUILD_MODNAME, trident)) {3543		dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);3544		return -EBUSY;3545	}3546	trident->irq = pci->irq;3547	card->sync_irq = trident->irq;3548 3549	/* allocate 16k-aligned TLB for NX cards */3550	trident->tlb.entries = NULL;3551	if (trident->device == TRIDENT_DEVICE_ID_NX) {3552		err = snd_trident_tlb_alloc(trident);3553		if (err < 0)3554			return err;3555	}3556 3557	trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;3558 3559	/* initialize chip */3560	switch (trident->device) {3561	case TRIDENT_DEVICE_ID_DX:3562		err = snd_trident_4d_dx_init(trident);3563		break;3564	case TRIDENT_DEVICE_ID_NX:3565		err = snd_trident_4d_nx_init(trident);3566		break;3567	case TRIDENT_DEVICE_ID_SI7018:3568		err = snd_trident_sis_init(trident);3569		break;3570	default:3571		snd_BUG();3572		break;3573	}3574	if (err < 0)3575		return err;3576 3577	err = snd_trident_mixer(trident, pcm_spdif_device);3578	if (err < 0)3579		return err;3580	3581	/* initialise synth voices */3582	for (i = 0; i < 64; i++) {3583		voice = &trident->synth.voices[i];3584		voice->number = i;3585		voice->trident = trident;3586	}3587	/* initialize pcm mixer entries */3588	for (i = 0; i < 32; i++) {3589		tmix = &trident->pcm_mixer[i];3590		tmix->vol = T4D_DEFAULT_PCM_VOL;3591		tmix->pan = T4D_DEFAULT_PCM_PAN;3592		tmix->rvol = T4D_DEFAULT_PCM_RVOL;3593		tmix->cvol = T4D_DEFAULT_PCM_CVOL;3594	}3595 3596	snd_trident_enable_eso(trident);3597 3598	snd_trident_proc_init(trident);3599	return 0;3600}3601 3602/*---------------------------------------------------------------------------3603   snd_trident_free3604  3605   Description: This routine will free the device specific class for3606                the 4DWave card. 3607                3608   Parameters:  card - card to release3609 3610   Returns:     None.3611  3612  ---------------------------------------------------------------------------*/3613 3614static void snd_trident_free(struct snd_card *card)3615{3616	struct snd_trident *trident = card->private_data;3617 3618	snd_trident_free_gameport(trident);3619	snd_trident_disable_eso(trident);3620	// Disable S/PDIF out3621	if (trident->device == TRIDENT_DEVICE_ID_NX)3622		outb(0x00, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));3623	else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {3624		outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));3625	}3626	if (trident->tlb.buffer) {3627		outl(0, TRID_REG(trident, NX_TLBC));3628		snd_util_memhdr_free(trident->tlb.memhdr);3629	}3630}3631 3632/*---------------------------------------------------------------------------3633   snd_trident_interrupt3634  3635   Description: ISR for Trident 4DWave device3636                3637   Parameters:  trident  - device specific private data for 4DWave card3638 3639   Problems:    It seems that Trident chips generates interrupts more than3640                one time in special cases. The spurious interrupts are3641                detected via sample timer (T4D_STIMER) and computing3642                corresponding delta value. The limits are detected with3643                the method try & fail so it is possible that it won't3644                work on all computers. [jaroslav]3645 3646   Returns:     None.3647  3648  ---------------------------------------------------------------------------*/3649 3650static irqreturn_t snd_trident_interrupt(int irq, void *dev_id)3651{3652	struct snd_trident *trident = dev_id;3653	unsigned int audio_int, chn_int, stimer, channel, mask, tmp;3654	int delta;3655	struct snd_trident_voice *voice;3656 3657	audio_int = inl(TRID_REG(trident, T4D_MISCINT));3658	if ((audio_int & (ADDRESS_IRQ|MPU401_IRQ)) == 0)3659		return IRQ_NONE;3660	if (audio_int & ADDRESS_IRQ) {3661		// get interrupt status for all channels3662		spin_lock(&trident->reg_lock);3663		stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;3664		chn_int = inl(TRID_REG(trident, T4D_AINT_A));3665		if (chn_int == 0)3666			goto __skip1;3667		outl(chn_int, TRID_REG(trident, T4D_AINT_A));	/* ack */3668	      __skip1:3669		chn_int = inl(TRID_REG(trident, T4D_AINT_B));3670		if (chn_int == 0)3671			goto __skip2;3672		for (channel = 63; channel >= 32; channel--) {3673			mask = 1 << (channel&0x1f);3674			if ((chn_int & mask) == 0)3675				continue;3676			voice = &trident->synth.voices[channel];3677			if (!voice->pcm || voice->substream == NULL) {3678				outl(mask, TRID_REG(trident, T4D_STOP_B));3679				continue;3680			}3681			delta = (int)stimer - (int)voice->stimer;3682			if (delta < 0)3683				delta = -delta;3684			if ((unsigned int)delta < voice->spurious_threshold) {3685				/* do some statistics here */3686				trident->spurious_irq_count++;3687				if (trident->spurious_irq_max_delta < (unsigned int)delta)3688					trident->spurious_irq_max_delta = delta;3689				continue;3690			}3691			voice->stimer = stimer;3692			if (voice->isync) {3693				if (!voice->isync3) {3694					tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL));3695					if (trident->bDMAStart & 0x40)3696						tmp >>= 1;3697					if (tmp > 0)3698						tmp = voice->isync_max - tmp;3699				} else {3700					tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;3701				}3702				if (tmp < voice->isync_mark) {3703					if (tmp > 0x10)3704						tmp = voice->isync_ESO - 7;3705					else3706						tmp = voice->isync_ESO + 2;3707					/* update ESO for IRQ voice to preserve sync */3708					snd_trident_stop_voice(trident, voice->number);3709					snd_trident_write_eso_reg(trident, voice, tmp);3710					snd_trident_start_voice(trident, voice->number);3711				}3712			} else if (voice->isync2) {3713				voice->isync2 = 0;3714				/* write original ESO and update CSO for IRQ voice to preserve sync */3715				snd_trident_stop_voice(trident, voice->number);3716				snd_trident_write_cso_reg(trident, voice, voice->isync_mark);3717				snd_trident_write_eso_reg(trident, voice, voice->ESO);3718				snd_trident_start_voice(trident, voice->number);3719			}3720#if 03721			if (voice->extra) {3722				/* update CSO for extra voice to preserve sync */3723				snd_trident_stop_voice(trident, voice->extra->number);3724				snd_trident_write_cso_reg(trident, voice->extra, 0);3725				snd_trident_start_voice(trident, voice->extra->number);3726			}3727#endif3728			spin_unlock(&trident->reg_lock);3729			snd_pcm_period_elapsed(voice->substream);3730			spin_lock(&trident->reg_lock);3731		}3732		outl(chn_int, TRID_REG(trident, T4D_AINT_B));	/* ack */3733	      __skip2:3734		spin_unlock(&trident->reg_lock);3735	}3736	if (audio_int & MPU401_IRQ) {3737		if (trident->rmidi) {3738			snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data);3739		} else {3740			inb(TRID_REG(trident, T4D_MPUR0));3741		}3742	}3743	// outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(trident, T4D_MISCINT));3744	return IRQ_HANDLED;3745}3746 3747struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port)3748{3749	struct snd_trident_voice *pvoice;3750	unsigned long flags;3751	int idx;3752 3753	spin_lock_irqsave(&trident->voice_alloc, flags);3754	if (type == SNDRV_TRIDENT_VOICE_TYPE_PCM) {3755		idx = snd_trident_allocate_pcm_channel(trident);3756		if(idx < 0) {3757			spin_unlock_irqrestore(&trident->voice_alloc, flags);3758			return NULL;3759		}3760		pvoice = &trident->synth.voices[idx];3761		pvoice->use = 1;3762		pvoice->pcm = 1;3763		pvoice->capture = 0;3764		pvoice->spdif = 0;3765		pvoice->memblk = NULL;3766		pvoice->substream = NULL;3767		spin_unlock_irqrestore(&trident->voice_alloc, flags);3768		return pvoice;3769	}3770	if (type == SNDRV_TRIDENT_VOICE_TYPE_SYNTH) {3771		idx = snd_trident_allocate_synth_channel(trident);3772		if(idx < 0) {3773			spin_unlock_irqrestore(&trident->voice_alloc, flags);3774			return NULL;3775		}3776		pvoice = &trident->synth.voices[idx];3777		pvoice->use = 1;3778		pvoice->synth = 1;3779		pvoice->client = client;3780		pvoice->port = port;3781		pvoice->memblk = NULL;3782		spin_unlock_irqrestore(&trident->voice_alloc, flags);3783		return pvoice;3784	}3785	if (type == SNDRV_TRIDENT_VOICE_TYPE_MIDI) {3786	}3787	spin_unlock_irqrestore(&trident->voice_alloc, flags);3788	return NULL;3789}3790 3791EXPORT_SYMBOL(snd_trident_alloc_voice);3792 3793void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice)3794{3795	unsigned long flags;3796	void (*private_free)(struct snd_trident_voice *);3797 3798	if (voice == NULL || !voice->use)3799		return;3800	snd_trident_clear_voices(trident, voice->number, voice->number);3801	spin_lock_irqsave(&trident->voice_alloc, flags);3802	private_free = voice->private_free;3803	voice->private_free = NULL;3804	voice->private_data = NULL;3805	if (voice->pcm)3806		snd_trident_free_pcm_channel(trident, voice->number);3807	if (voice->synth)3808		snd_trident_free_synth_channel(trident, voice->number);3809	voice->use = voice->pcm = voice->synth = voice->midi = 0;3810	voice->capture = voice->spdif = 0;3811	voice->sample_ops = NULL;3812	voice->substream = NULL;3813	voice->extra = NULL;3814	spin_unlock_irqrestore(&trident->voice_alloc, flags);3815	if (private_free)3816		private_free(voice);3817}3818 3819EXPORT_SYMBOL(snd_trident_free_voice);3820 3821static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max)3822{3823	unsigned int i, val, mask[2] = { 0, 0 };3824 3825	if (snd_BUG_ON(v_min > 63 || v_max > 63))3826		return;3827	for (i = v_min; i <= v_max; i++)3828		mask[i >> 5] |= 1 << (i & 0x1f);3829	if (mask[0]) {3830		outl(mask[0], TRID_REG(trident, T4D_STOP_A));3831		val = inl(TRID_REG(trident, T4D_AINTEN_A));3832		outl(val & ~mask[0], TRID_REG(trident, T4D_AINTEN_A));3833	}3834	if (mask[1]) {3835		outl(mask[1], TRID_REG(trident, T4D_STOP_B));3836		val = inl(TRID_REG(trident, T4D_AINTEN_B));3837		outl(val & ~mask[1], TRID_REG(trident, T4D_AINTEN_B));3838	}3839}3840 3841#ifdef CONFIG_PM_SLEEP3842static int snd_trident_suspend(struct device *dev)3843{3844	struct snd_card *card = dev_get_drvdata(dev);3845	struct snd_trident *trident = card->private_data;3846 3847	trident->in_suspend = 1;3848	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);3849	snd_ac97_suspend(trident->ac97);3850	snd_ac97_suspend(trident->ac97_sec);3851	return 0;3852}3853 3854static int snd_trident_resume(struct device *dev)3855{3856	struct snd_card *card = dev_get_drvdata(dev);3857	struct snd_trident *trident = card->private_data;3858 3859	switch (trident->device) {3860	case TRIDENT_DEVICE_ID_DX:3861		snd_trident_4d_dx_init(trident);3862		break;3863	case TRIDENT_DEVICE_ID_NX:3864		snd_trident_4d_nx_init(trident);3865		break;3866	case TRIDENT_DEVICE_ID_SI7018:3867		snd_trident_sis_init(trident);3868		break;3869	}3870 3871	snd_ac97_resume(trident->ac97);3872	snd_ac97_resume(trident->ac97_sec);3873 3874	/* restore some registers */3875	outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));3876 3877	snd_trident_enable_eso(trident);3878 3879	snd_power_change_state(card, SNDRV_CTL_POWER_D0);3880	trident->in_suspend = 0;3881	return 0;3882}3883 3884SIMPLE_DEV_PM_OPS(snd_trident_pm, snd_trident_suspend, snd_trident_resume);3885#endif /* CONFIG_PM_SLEEP */3886