Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *  Maintained by Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *  Originated by audio@tridentmicro.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *  Fri Feb 19 15:55:28 MST 1999
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *  Routines for control of Trident 4DWave (DX and NX) chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *  BUGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *  TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *    ---
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *  SiS7018 S/PDIF support by Thomas Winischhofer <thomas@winischhofer.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/gameport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include "trident.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 				       struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 				       struct snd_pcm_substream *substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) static int snd_trident_pcm_mixer_free(struct snd_trident *trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 				      struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 				      struct snd_pcm_substream *substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) static irqreturn_t snd_trident_interrupt(int irq, void *dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) static int snd_trident_sis_reset(struct snd_trident *trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) static void snd_trident_clear_voices(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 				     unsigned short v_min, unsigned short v_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) static int snd_trident_free(struct snd_trident *trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48)  *  common I/O routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	unsigned int val, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	dev_dbg(trident->card->dev, "Trident voice %i:\n", voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 	outb(voice, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	val = inl(TRID_REG(trident, CH_LBA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	dev_dbg(trident->card->dev, "LBA: 0x%x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	val = inl(TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	dev_dbg(trident->card->dev, "GVSel: %i\n", val >> 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	dev_dbg(trident->card->dev, "Pan: 0x%x\n", (val >> 24) & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	dev_dbg(trident->card->dev, "Vol: 0x%x\n", (val >> 16) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	dev_dbg(trident->card->dev, "CTRL: 0x%x\n", (val >> 12) & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	dev_dbg(trident->card->dev, "EC: 0x%x\n", val & 0x0fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	if (trident->device != TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 		val = inl(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 		dev_dbg(trident->card->dev, "CSO: 0x%x\n", val >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 		dev_dbg(trident->card->dev, "Alpha: 0x%x\n", (val >> 4) & 0x0fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 		dev_dbg(trident->card->dev, "FMS: 0x%x\n", val & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 		val = inl(TRID_REG(trident, CH_DX_ESO_DELTA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 		dev_dbg(trident->card->dev, "ESO: 0x%x\n", val >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 		dev_dbg(trident->card->dev, "Delta: 0x%x\n", val & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 		val = inl(TRID_REG(trident, CH_DX_FMC_RVOL_CVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	} else {		// TRIDENT_DEVICE_ID_NX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 		val = inl(TRID_REG(trident, CH_NX_DELTA_CSO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 		tmp = (val >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 		dev_dbg(trident->card->dev, "CSO: 0x%x\n", val & 0x00ffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 		val = inl(TRID_REG(trident, CH_NX_DELTA_ESO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 		tmp |= (val >> 16) & 0xff00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 		dev_dbg(trident->card->dev, "Delta: 0x%x\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 		dev_dbg(trident->card->dev, "ESO: 0x%x\n", val & 0x00ffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 		val = inl(TRID_REG(trident, CH_NX_ALPHA_FMS_FMC_RVOL_CVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 		dev_dbg(trident->card->dev, "Alpha: 0x%x\n", val >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 		dev_dbg(trident->card->dev, "FMS: 0x%x\n", (val >> 16) & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	dev_dbg(trident->card->dev, "FMC: 0x%x\n", (val >> 14) & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	dev_dbg(trident->card->dev, "RVol: 0x%x\n", (val >> 7) & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	dev_dbg(trident->card->dev, "CVol: 0x%x\n", val & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)    unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97)    Description: This routine will do all of the reading from the external
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98)                 CODEC (AC97).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)    Parameters:  ac97 - ac97 codec structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)                 reg - CODEC register index, from AC97 Hal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102)  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103)    returns:     16 bit value read from the AC97.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 	unsigned int data = 0, treg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 	unsigned short count = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	struct snd_trident *trident = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	spin_lock_irqsave(&trident->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	if (trident->device == TRIDENT_DEVICE_ID_DX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 		data = (DX_AC97_BUSY_READ | (reg & 0x000000ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 		outl(data, TRID_REG(trident, DX_ACR1_AC97_R));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 			data = inl(TRID_REG(trident, DX_ACR1_AC97_R));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 			if ((data & DX_AC97_BUSY_READ) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 		} while (--count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	} else if (trident->device == TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		data = (NX_AC97_BUSY_READ | (reg & 0x000000ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 		treg = ac97->num == 0 ? NX_ACR2_AC97_R_PRIMARY : NX_ACR3_AC97_R_SECONDARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 		outl(data, TRID_REG(trident, treg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 			data = inl(TRID_REG(trident, treg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 			if ((data & 0x00000C00) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 		} while (--count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	} else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		data = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 		if (ac97->num == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 			data |= SI_AC97_SECONDARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 		outl(data, TRID_REG(trident, SI_AC97_READ));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 			data = inl(TRID_REG(trident, SI_AC97_READ));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 			if ((data & (SI_AC97_BUSY_READ)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 		} while (--count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	if (count == 0 && !trident->ac97_detect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 		dev_err(trident->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 			"ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 			   reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	spin_unlock_irqrestore(&trident->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	return ((unsigned short) (data >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155)    void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156)    unsigned short wdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158)    Description: This routine will do all of the writing to the external
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159)                 CODEC (AC97).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161)    Parameters:	ac97 - ac97 codec structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162)    	        reg - CODEC register index, from AC97 Hal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163)                 data  - Lower 16 bits are the data to write to CODEC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165)    returns:     TRUE if everything went ok, else FALSE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) static void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 				    unsigned short wdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	unsigned int address, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	unsigned short count = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	struct snd_trident *trident = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	data = ((unsigned long) wdata) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	spin_lock_irqsave(&trident->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	if (trident->device == TRIDENT_DEVICE_ID_DX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 		address = DX_ACR0_AC97_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 		/* read AC-97 write register status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 			if ((inw(TRID_REG(trident, address)) & DX_AC97_BUSY_WRITE) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 		} while (--count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 		data |= (DX_AC97_BUSY_WRITE | (reg & 0x000000ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	} else if (trident->device == TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 		address = NX_ACR1_AC97_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 		/* read AC-97 write register status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 			if ((inw(TRID_REG(trident, address)) & NX_AC97_BUSY_WRITE) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 		} while (--count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		data |= (NX_AC97_BUSY_WRITE | (ac97->num << 8) | (reg & 0x000000ff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	} else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 		address = SI_AC97_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 		/* read AC-97 write register status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 			if ((inw(TRID_REG(trident, address)) & (SI_AC97_BUSY_WRITE)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 		} while (--count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		data |= SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY | (reg & 0x000000ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		if (ac97->num == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 			data |= SI_AC97_SECONDARY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 		address = 0;	/* keep GCC happy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 		count = 0;	/* return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	if (count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 		spin_unlock_irqrestore(&trident->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	outl(data, TRID_REG(trident, address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	spin_unlock_irqrestore(&trident->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225)    void snd_trident_enable_eso(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227)    Description: This routine will enable end of loop interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228)                 End of loop interrupts will occur when a running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229)                 channel reaches ESO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230)                 Also enables middle of loop interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) static void snd_trident_enable_eso(struct snd_trident * trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	val = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	val |= ENDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	val |= MIDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 		val |= BANK_B_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	outl(val, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249)    void snd_trident_disable_eso(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251)    Description: This routine will disable end of loop interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)                 End of loop interrupts will occur when a running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253)                 channel reaches ESO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254)                 Also disables middle of loop interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256)    Parameters:  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257)                 trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259)    returns:     TRUE if everything went ok, else FALSE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) static void snd_trident_disable_eso(struct snd_trident * trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	tmp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	tmp &= ~ENDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	tmp &= ~MIDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	outl(tmp, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274)    void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276)     Description: Start a voice, any channel 0 thru 63.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277)                  This routine automatically handles the fact that there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278)                  more than 32 channels available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280)     Parameters : voice - Voice number 0 thru n.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281)                  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283)     Return Value: None.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	unsigned int mask = 1 << (voice & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	unsigned int reg = (voice & 0x20) ? T4D_START_B : T4D_START_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	outl(mask, TRID_REG(trident, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) EXPORT_SYMBOL(snd_trident_start_voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298)    void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300)     Description: Stop a voice, any channel 0 thru 63.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301)                  This routine automatically handles the fact that there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302)                  more than 32 channels available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304)     Parameters : voice - Voice number 0 thru n.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305)                  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307)     Return Value: None.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	unsigned int mask = 1 << (voice & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	unsigned int reg = (voice & 0x20) ? T4D_STOP_B : T4D_STOP_A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	outl(mask, TRID_REG(trident, reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) EXPORT_SYMBOL(snd_trident_stop_voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322)     int snd_trident_allocate_pcm_channel(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324)     Description: Allocate hardware channel in Bank B (32-63).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326)     Parameters :  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328)     Return Value: hardware channel - 32-63 or -1 when no channel is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) static int snd_trident_allocate_pcm_channel(struct snd_trident * trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	if (trident->ChanPCMcnt >= trident->ChanPCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	for (idx = 31; idx >= 0; idx--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 		if (!(trident->ChanMap[T4D_BANK_B] & (1 << idx))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 			trident->ChanMap[T4D_BANK_B] |= 1 << idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 			trident->ChanPCMcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 			return idx + 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349)     void snd_trident_free_pcm_channel(int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351)     Description: Free hardware channel in Bank B (32-63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353)     Parameters :  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	          channel - hardware channel number 0-63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356)     Return Value: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) static void snd_trident_free_pcm_channel(struct snd_trident *trident, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	if (channel < 32 || channel > 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	channel &= 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	if (trident->ChanMap[T4D_BANK_B] & (1 << channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		trident->ChanMap[T4D_BANK_B] &= ~(1 << channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		trident->ChanPCMcnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)     unsigned int snd_trident_allocate_synth_channel(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374)     Description: Allocate hardware channel in Bank A (0-31).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376)     Parameters :  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378)     Return Value: hardware channel - 0-31 or -1 when no channel is available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) static int snd_trident_allocate_synth_channel(struct snd_trident * trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	for (idx = 31; idx >= 0; idx--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 		if (!(trident->ChanMap[T4D_BANK_A] & (1 << idx))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 			trident->ChanMap[T4D_BANK_A] |= 1 << idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 			trident->synth.ChanSynthCount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 			return idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)     void snd_trident_free_synth_channel( int channel )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)     Description: Free hardware channel in Bank B (0-31).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)     Parameters :  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	          channel - hardware channel number 0-63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404)     Return Value: none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) static void snd_trident_free_synth_channel(struct snd_trident *trident, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	if (channel < 0 || channel > 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	channel &= 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	if (trident->ChanMap[T4D_BANK_A] & (1 << channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		trident->ChanMap[T4D_BANK_A] &= ~(1 << channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		trident->synth.ChanSynthCount--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420)    snd_trident_write_voice_regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422)    Description: This routine will complete and write the 5 hardware channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423)                 registers to hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426)                 voice - synthesizer voice structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427)                 Each register field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) void snd_trident_write_voice_regs(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 				  struct snd_trident_voice * voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	unsigned int FmcRvolCvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	unsigned int regs[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	regs[1] = voice->LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	regs[4] = (voice->GVSel << 31) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		  ((voice->Pan & 0x0000007f) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		  ((voice->CTRL & 0x0000000f) << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	FmcRvolCvol = ((voice->FMC & 3) << 14) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	              ((voice->RVol & 0x7f) << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	              (voice->CVol & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	switch (trident->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	case TRIDENT_DEVICE_ID_SI7018:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		regs[4] |= voice->number > 31 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 				(voice->Vol & 0x000003ff) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 				((voice->Vol & 0x00003fc) << (16-2)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 				(voice->EC & 0x00000fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 			(voice->FMS & 0x0000000f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		regs[3] = (voice->Attribute << 16) | FmcRvolCvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	case TRIDENT_DEVICE_ID_DX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 			   (voice->EC & 0x00000fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 			(voice->FMS & 0x0000000f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		regs[3] = FmcRvolCvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	case TRIDENT_DEVICE_ID_NX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 			   (voice->EC & 0x00000fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		regs[2] = ((voice->Delta << 16) & 0xff000000) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 			(voice->ESO & 0x00ffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 		regs[3] = (voice->Alpha << 20) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 			((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		snd_BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 	outl(regs[0], TRID_REG(trident, CH_START + 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	outl(regs[1], TRID_REG(trident, CH_START + 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	outl(regs[2], TRID_REG(trident, CH_START + 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	outl(regs[3], TRID_REG(trident, CH_START + 12));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	outl(regs[4], TRID_REG(trident, CH_START + 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	dev_dbg(trident->card->dev, "written %i channel:\n", voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	dev_dbg(trident->card->dev, "  regs[0] = 0x%x/0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	       regs[0], inl(TRID_REG(trident, CH_START + 0)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	dev_dbg(trident->card->dev, "  regs[1] = 0x%x/0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	       regs[1], inl(TRID_REG(trident, CH_START + 4)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	dev_dbg(trident->card->dev, "  regs[2] = 0x%x/0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	       regs[2], inl(TRID_REG(trident, CH_START + 8)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	dev_dbg(trident->card->dev, "  regs[3] = 0x%x/0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	       regs[3], inl(TRID_REG(trident, CH_START + 12)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	dev_dbg(trident->card->dev, "  regs[4] = 0x%x/0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	       regs[4], inl(TRID_REG(trident, CH_START + 16)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) EXPORT_SYMBOL(snd_trident_write_voice_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)    snd_trident_write_cso_reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505)    Description: This routine will write the new CSO offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506)                 register to hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509)                 voice - synthesizer voice structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510)                 CSO - new CSO value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) static void snd_trident_write_cso_reg(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 				      struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 				      unsigned int CSO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	voice->CSO = CSO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	if (trident->device != TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 		outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		outl((voice->Delta << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		     (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529)    snd_trident_write_eso_reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531)    Description: This routine will write the new ESO offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532)                 register to hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535)                 voice - synthesizer voice structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536)                 ESO - new ESO value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) static void snd_trident_write_eso_reg(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 				      struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 				      unsigned int ESO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	voice->ESO = ESO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	if (trident->device != TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 		     TRID_REG(trident, CH_NX_DELTA_ESO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555)    snd_trident_write_vol_reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)    Description: This routine will write the new voice volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)                 register to hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)                 voice - synthesizer voice structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)                 Vol - new voice volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) static void snd_trident_write_vol_reg(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 				      struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 				      unsigned int Vol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 	voice->Vol = Vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	switch (trident->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	case TRIDENT_DEVICE_ID_DX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	case TRIDENT_DEVICE_ID_NX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 		outb(voice->Vol >> 2, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	case TRIDENT_DEVICE_ID_SI7018:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		/* dev_dbg(trident->card->dev, "voice->Vol = 0x%x\n", voice->Vol); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		outw((voice->CTRL << 12) | voice->Vol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		     TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586)    snd_trident_write_pan_reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588)    Description: This routine will write the new voice pan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589)                 register to hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592)                 voice - synthesizer voice structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593)                 Pan - new pan value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) static void snd_trident_write_pan_reg(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 				      struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 				      unsigned int Pan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	voice->Pan = Pan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	     TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608)    snd_trident_write_rvol_reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610)    Description: This routine will write the new reverb volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611)                 register to hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614)                 voice - synthesizer voice structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615)                 RVol - new reverb volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) static void snd_trident_write_rvol_reg(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 				       struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 				       unsigned int RVol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	voice->RVol = RVol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 	outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	     (voice->CVol & 0x007f),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	     TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		      CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632)    snd_trident_write_cvol_reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634)    Description: This routine will write the new chorus volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635)                 register to hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638)                 voice - synthesizer voice structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639)                 CVol - new chorus volume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) static void snd_trident_write_cvol_reg(struct snd_trident * trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 				       struct snd_trident_voice * voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 				       unsigned int CVol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	voice->CVol = CVol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	     (voice->CVol & 0x007f),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	     TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		      CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656)    snd_trident_convert_rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658)    Description: This routine converts rate in HZ to hardware delta value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661)                 rate - Real or Virtual channel number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663)    Returns:     Delta value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) static unsigned int snd_trident_convert_rate(unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	unsigned int delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	// We special case 44100 and 8000 since rounding with the equation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	// does not give us an accurate enough value. For 11025 and 22050
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 	// the equation gives us the best answer. All other frequencies will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 	// also use the equation. JDW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	if (rate == 44100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		delta = 0xeb3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	else if (rate == 8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		delta = 0x2ab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	else if (rate == 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		delta = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	return delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)    snd_trident_convert_adc_rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688)    Description: This routine converts rate in HZ to hardware delta value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691)                 rate - Real or Virtual channel number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693)    Returns:     Delta value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) static unsigned int snd_trident_convert_adc_rate(unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	unsigned int delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	// We special case 44100 and 8000 since rounding with the equation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	// does not give us an accurate enough value. For 11025 and 22050
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	// the equation gives us the best answer. All other frequencies will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	// also use the equation. JDW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	if (rate == 44100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		delta = 0x116a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	else if (rate == 8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		delta = 0x6000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	else if (rate == 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		delta = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		delta = ((48000 << 12) / rate) & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	return delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716)    snd_trident_spurious_threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718)    Description: This routine converts rate in HZ to spurious threshold.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721)                 rate - Real or Virtual channel number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723)    Returns:     Delta value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) static unsigned int snd_trident_spurious_threshold(unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 						   unsigned int period_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	unsigned int res = (rate * period_size) / 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	if (res < 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		res = res / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		res -= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738)    snd_trident_control_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740)    Description: This routine returns a control mode for a PCM channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743)                 substream  - PCM substream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745)    Returns:     Control value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) static unsigned int snd_trident_control_mode(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	unsigned int CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	/* set ctrl mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	   CTRL default: 8-bit (unsigned) mono, loop mode enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	CTRL = 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	if (snd_pcm_format_width(runtime->format) == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		CTRL |= 0x00000008;	// 16-bit data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	if (snd_pcm_format_signed(runtime->format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 		CTRL |= 0x00000002;	// signed data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	if (runtime->channels > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		CTRL |= 0x00000004;	// stereo data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	return CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767)  *  PCM part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771)    snd_trident_allocate_pcm_mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773)    Description: Allocate PCM ring buffer for given substream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		hw_params  - hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) static int snd_trident_allocate_pcm_mem(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 					struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	if (trident->tlb.entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		if (runtime->buffer_changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 			if (voice->memblk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 				snd_trident_free_pages(trident, voice->memblk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 			voice->memblk = snd_trident_alloc_pages(trident, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 			if (voice->memblk == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 				return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802)    snd_trident_allocate_evoice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804)    Description: Allocate extra voice as interrupt generator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		hw_params  - hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) static int snd_trident_allocate_evoice(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 				       struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	struct snd_trident_voice *evoice = voice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	/* voice management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		if (evoice == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 			evoice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			if (evoice == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 				return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 			voice->extra = evoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 			evoice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 		if (evoice != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 			snd_trident_free_voice(trident, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 			voice->extra = evoice = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842)    snd_trident_hw_params
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844)    Description: Set the hardware parameters for the playback device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 		hw_params  - hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) static int snd_trident_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 				 struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	err = snd_trident_allocate_pcm_mem(substream, hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		err = snd_trident_allocate_evoice(substream, hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865)    snd_trident_playback_hw_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867)    Description: Release the hardware resources for the playback device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) static int snd_trident_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	struct snd_trident_voice *evoice = voice ? voice->extra : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	if (trident->tlb.entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		if (voice && voice->memblk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			snd_trident_free_pages(trident, voice->memblk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 			voice->memblk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	if (evoice != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		snd_trident_free_voice(trident, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		voice->extra = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896)    snd_trident_playback_prepare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898)    Description: Prepare playback device for playback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) static int snd_trident_playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	struct snd_trident_voice *evoice = voice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	spin_lock_irq(&trident->reg_lock);	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	/* set delta (rate) value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	voice->Delta = snd_trident_convert_rate(runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	/* set Loop Begin Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	if (voice->memblk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		voice->LBA = voice->memblk->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		voice->LBA = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925)  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	voice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	voice->ESO = runtime->buffer_size - 1;	/* in samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	voice->CTRL = snd_trident_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	voice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	voice->GVSel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	voice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	voice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	voice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	voice->Vol = mix->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	voice->RVol = mix->rvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	voice->CVol = mix->cvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	voice->Pan = mix->pan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	voice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	voice->Attribute = (1<<(30-16))|(2<<(26-16))|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 			   (0<<(24-16))|(0x1f<<(19-16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	voice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	snd_trident_write_voice_regs(trident, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	if (evoice != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		evoice->Delta = voice->Delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		evoice->spurious_threshold = voice->spurious_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		evoice->LBA = voice->LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		evoice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 		evoice->CTRL = voice->CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		evoice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		evoice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		evoice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 		evoice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		evoice->Vol = 0x3ff;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 		evoice->RVol = evoice->CVol = 0x7f;	/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		evoice->Pan = 0x7f;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 		evoice->Attribute = (1<<(30-16))|(2<<(26-16))|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 				    (0<<(24-16))|(0x1f<<(19-16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		evoice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		snd_trident_write_voice_regs(trident, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		evoice->isync2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		evoice->isync_mark = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		evoice->ESO = (runtime->period_size * 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981)    snd_trident_capture_hw_params
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983)    Description: Set the hardware parameters for the capture device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		hw_params  - hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) static int snd_trident_capture_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 					 struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	return snd_trident_allocate_pcm_mem(substream, hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999)    snd_trident_capture_prepare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)    Description: Prepare capture device for playback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static int snd_trident_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	unsigned int val, ESO_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	// Initialize the channel and set channel Mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	outb(0, TRID_REG(trident, LEGACY_DMAR15));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	// Set DMA channel operation mode register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	outb(0x54, TRID_REG(trident, LEGACY_DMAR11));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	// Set channel buffer Address, DMAR0 expects contiguous PCI memory area	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	voice->LBA = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 	if (voice->memblk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		voice->LBA = voice->memblk->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	// set ESO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	ESO_bytes = snd_pcm_lib_buffer_bytes(substream) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	outb((ESO_bytes & 0x00ff0000) >> 16, TRID_REG(trident, LEGACY_DMAR6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	outw((ESO_bytes & 0x0000ffff), TRID_REG(trident, LEGACY_DMAR4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	ESO_bytes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	// Set channel sample rate, 4.12 format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	// Set channel interrupt blk length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	if (snd_pcm_format_width(runtime->format) == 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 		val = (unsigned short) ((ESO_bytes >> 1) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		val = (unsigned short) (ESO_bytes - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	outl((val << 16) | val, TRID_REG(trident, T4D_SBBL_SBCL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 	// Right now, set format and start to run captureing, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	// continuous run loop enable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	trident->bDMAStart = 0x19;	// 0001 1001b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	if (snd_pcm_format_width(runtime->format) == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		trident->bDMAStart |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	if (snd_pcm_format_signed(runtime->format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 		trident->bDMAStart |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	if (runtime->channels > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		trident->bDMAStart |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	// Prepare capture intr channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	voice->Delta = snd_trident_convert_rate(runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	voice->isync = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	voice->isync_mark = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 	voice->isync_max = runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	// Set voice parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	voice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 	voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	voice->CTRL = snd_trident_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	voice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	voice->RVol = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	voice->CVol = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	voice->GVSel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	voice->Pan = 0x7f;		/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	voice->Vol = 0x3ff;		/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	voice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	voice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	voice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	voice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	snd_trident_write_voice_regs(trident, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)    snd_trident_si7018_capture_hw_params
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)    Description: Set the hardware parameters for the capture device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		hw_params  - hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 						struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	return snd_trident_allocate_evoice(substream, hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)    snd_trident_si7018_capture_hw_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)    Description: Release the hardware resources for the capture device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) static int snd_trident_si7018_capture_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	struct snd_trident_voice *evoice = voice ? voice->extra : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	if (evoice != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 		snd_trident_free_voice(trident, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		voice->extra = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)    snd_trident_si7018_capture_prepare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)    Description: Prepare capture device for playback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	struct snd_trident_voice *evoice = voice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	voice->LBA = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	voice->Delta = snd_trident_convert_adc_rate(runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 	voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	// Set voice parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	voice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	voice->ESO = runtime->buffer_size - 1;		/* in samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	voice->CTRL = snd_trident_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	voice->FMC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	voice->RVol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	voice->CVol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	voice->GVSel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	voice->Pan = T4D_DEFAULT_PCM_PAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	voice->Vol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	voice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	voice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	voice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	voice->Attribute = (2 << (30-16)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 			   (2 << (26-16)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 			   (2 << (24-16)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 			   (1 << (23-16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	snd_trident_write_voice_regs(trident, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	if (evoice != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		evoice->Delta = snd_trident_convert_rate(runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 		evoice->spurious_threshold = voice->spurious_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		evoice->LBA = voice->LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 		evoice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		evoice->ESO = (runtime->period_size * 2) + 20 - 1; /* in samples, 20 means correction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 		evoice->CTRL = voice->CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 		evoice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 		evoice->GVSel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 		evoice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 		evoice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		evoice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 		evoice->Vol = 0x3ff;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		evoice->RVol = evoice->CVol = 0x7f;	/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 		evoice->Pan = 0x7f;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		evoice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 		snd_trident_write_voice_regs(trident, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		evoice->isync2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		evoice->isync_mark = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		evoice->ESO = (runtime->period_size * 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)    snd_trident_foldback_prepare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)    Description: Prepare foldback capture device for playback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) static int snd_trident_foldback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	struct snd_trident_voice *evoice = voice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	/* Set channel buffer Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	if (voice->memblk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 		voice->LBA = voice->memblk->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 		voice->LBA = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	/* set target ESO for channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	voice->ESO = runtime->buffer_size - 1;	/* in samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	/* set sample rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	voice->Delta = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	voice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 	voice->CTRL = snd_trident_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	voice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	voice->RVol = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	voice->CVol = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	voice->GVSel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	voice->Pan = 0x7f;	/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 	voice->Vol = 0x3ff;	/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	voice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 	voice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	voice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	voice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	/* set up capture channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	outb(((voice->number & 0x3f) | 0x80), TRID_REG(trident, T4D_RCI + voice->foldback_chan));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	snd_trident_write_voice_regs(trident, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	if (evoice != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		evoice->Delta = voice->Delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		evoice->spurious_threshold = voice->spurious_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 		evoice->LBA = voice->LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		evoice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 		evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 		evoice->CTRL = voice->CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 		evoice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 		evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 		evoice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 		evoice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 		evoice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 		evoice->Vol = 0x3ff;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 		evoice->RVol = evoice->CVol = 0x7f;	/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 		evoice->Pan = 0x7f;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 		evoice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 		snd_trident_write_voice_regs(trident, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 		evoice->isync2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 		evoice->isync_mark = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 		evoice->ESO = (runtime->period_size * 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)    snd_trident_spdif_hw_params
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)    Description: Set the hardware parameters for the spdif device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 		hw_params  - hardware parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) static int snd_trident_spdif_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 				       struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	unsigned int old_bits = 0, change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 	err = snd_trident_allocate_pcm_mem(substream, hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 		err = snd_trident_allocate_evoice(substream, hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	/* prepare SPDIF channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	old_bits = trident->spdif_pcm_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	if (old_bits & IEC958_AES0_PROFESSIONAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 		trident->spdif_pcm_bits &= ~IEC958_AES0_PRO_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 		trident->spdif_pcm_bits &= ~(IEC958_AES3_CON_FS << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 	if (params_rate(hw_params) >= 48000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		trident->spdif_pcm_ctrl = 0x3c;	// 48000 Hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		trident->spdif_pcm_bits |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 				IEC958_AES0_PRO_FS_48000 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 				(IEC958_AES3_CON_FS_48000 << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	else if (params_rate(hw_params) >= 44100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 		trident->spdif_pcm_ctrl = 0x3e;	// 44100 Hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 		trident->spdif_pcm_bits |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 				IEC958_AES0_PRO_FS_44100 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 				(IEC958_AES3_CON_FS_44100 << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 		trident->spdif_pcm_ctrl = 0x3d;	// 32000 Hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 		trident->spdif_pcm_bits |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 			trident->spdif_bits & IEC958_AES0_PROFESSIONAL ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 				IEC958_AES0_PRO_FS_32000 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 				(IEC958_AES3_CON_FS_32000 << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	change = old_bits != trident->spdif_pcm_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	if (change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 		snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE, &trident->spdif_pcm_ctl->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)    snd_trident_spdif_prepare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)    Description: Prepare SPDIF device for playback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) static int snd_trident_spdif_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	struct snd_trident_voice *evoice = voice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 	unsigned int RESO, LBAO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 		/* set delta (rate) value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 		voice->Delta = snd_trident_convert_rate(runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 		voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 		/* set Loop Back Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 		LBAO = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 		if (voice->memblk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 			voice->LBA = voice->memblk->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 			voice->LBA = LBAO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) 		voice->isync = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 		voice->isync3 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 		voice->isync_mark = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 		voice->isync_max = runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 		/* set target ESO for channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 		RESO = runtime->buffer_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 		voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 6 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 		/* set ctrl mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 		voice->CTRL = snd_trident_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 		voice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 		voice->RVol = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 		voice->CVol = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 		voice->GVSel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 		voice->Pan = 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) 		voice->Vol = 0x3ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 		voice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) 		voice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) 		voice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 		voice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 		voice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 		/* prepare surrogate IRQ channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 		snd_trident_write_voice_regs(trident, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 		outw((RESO & 0xffff), TRID_REG(trident, NX_SPESO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 		outb((RESO >> 16), TRID_REG(trident, NX_SPESO + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 		outl((LBAO & 0xfffffffc), TRID_REG(trident, NX_SPLBA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 		outw((voice->CSO & 0xffff), TRID_REG(trident, NX_SPCTRL_SPCSO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 		outb((voice->CSO >> 16), TRID_REG(trident, NX_SPCTRL_SPCSO + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 		/* set SPDIF setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 		outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 		outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	} else {	/* SiS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 		/* set delta (rate) value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 		voice->Delta = 0x800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 		voice->spurious_threshold = snd_trident_spurious_threshold(48000, runtime->period_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 		/* set Loop Begin Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 		if (voice->memblk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 			voice->LBA = voice->memblk->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 			voice->LBA = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 		voice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 		voice->ESO = runtime->buffer_size - 1;	/* in samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 		voice->CTRL = snd_trident_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 		voice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 		voice->GVSel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 		voice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 		voice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 		voice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 		voice->Vol = mix->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 		voice->RVol = mix->rvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 		voice->CVol = mix->cvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 		voice->Pan = mix->pan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 		voice->Attribute = (1<<(30-16))|(7<<(26-16))|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 				   (0<<(24-16))|(0<<(19-16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 		snd_trident_write_voice_regs(trident, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		if (evoice != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 			evoice->Delta = voice->Delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 			evoice->spurious_threshold = voice->spurious_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 			evoice->LBA = voice->LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 			evoice->CSO = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 			evoice->ESO = (runtime->period_size * 2) + 4 - 1; /* in samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 			evoice->CTRL = voice->CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 			evoice->FMC = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 			evoice->GVSel = trident->device == TRIDENT_DEVICE_ID_SI7018 ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 			evoice->EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 			evoice->Alpha = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 			evoice->FMS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 			evoice->Vol = 0x3ff;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 			evoice->RVol = evoice->CVol = 0x7f;	/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 			evoice->Pan = 0x7f;			/* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 			evoice->Attribute = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 			snd_trident_write_voice_regs(trident, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 			evoice->isync2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 			evoice->isync_mark = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 			evoice->ESO = (runtime->period_size * 2) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 		outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 		temp = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 		temp &= ~(1<<19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 		outl(temp, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 		temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 		temp |= SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 		outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)    snd_trident_trigger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)    Description: Start/stop devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)    Parameters:  substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)    		cmd	- trigger command (STOP, GO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)    Returns:     Error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) static int snd_trident_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 			       int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 				    
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	struct snd_pcm_substream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	unsigned int what, whati, capture_flag, spdif_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 	struct snd_trident_voice *voice, *evoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	unsigned int val, go;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 		go = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 	case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 	case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 		go = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 	what = whati = capture_flag = spdif_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 	spin_lock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 	val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 	snd_pcm_group_for_each_entry(s, substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 		if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 			voice = s->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 			evoice = voice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 			what |= 1 << (voice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 			if (evoice == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 				whati |= 1 << (voice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 				what |= 1 << (evoice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 				whati |= 1 << (evoice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 				if (go)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 					evoice->stimer = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 			if (go) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 				voice->running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 				voice->stimer = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 				voice->running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 			snd_pcm_trigger_done(s, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 			if (voice->capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) 				capture_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 			if (voice->spdif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 				spdif_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	if (spdif_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 		if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 			outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 			val = trident->spdif_pcm_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 			if (!go)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 				val &= ~(0x28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 			outb(val, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 			outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 			val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 			outl(val, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 	if (!go)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 		outl(what, TRID_REG(trident, T4D_STOP_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 	val = inl(TRID_REG(trident, T4D_AINTEN_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 	if (go) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 		val |= whati;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 		val &= ~whati;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 	outl(val, TRID_REG(trident, T4D_AINTEN_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 	if (go) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 		outl(what, TRID_REG(trident, T4D_START_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 		if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 			outb(trident->bDMAStart, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 		if (capture_flag && trident->device != TRIDENT_DEVICE_ID_SI7018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 			outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 	spin_unlock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)    snd_trident_playback_pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)    Description: This routine return the playback position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)    Returns:     position of buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 	unsigned int cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 	if (!voice->running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 	spin_lock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 	outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	if (trident->device != TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 		cso = inw(TRID_REG(trident, CH_DX_CSO_ALPHA_FMS + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	} else {		// ID_4DWAVE_NX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 		cso = (unsigned int) inl(TRID_REG(trident, CH_NX_DELTA_CSO)) & 0x00ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 	spin_unlock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 	if (cso >= runtime->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 		cso = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 	return cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)    snd_trident_capture_pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)    Description: This routine return the capture position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)    Parameters:   pcm1    - PCM device class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)    Returns:     position of buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) static snd_pcm_uframes_t snd_trident_capture_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 	unsigned int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	if (!voice->running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 	result = inw(TRID_REG(trident, T4D_SBBL_SBCL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	if (runtime->channels > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 		result >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 	if (result > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 		result = runtime->buffer_size - result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)    snd_trident_spdif_pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)    Description: This routine return the SPDIF playback position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)    Returns:     position of buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) static snd_pcm_uframes_t snd_trident_spdif_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 	unsigned int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 	if (!voice->running)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	result = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)  *  Playback support device description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) static const struct snd_pcm_hardware snd_trident_playback =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 	.rate_min =		4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 	.rate_max =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 	.channels_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 	.channels_max =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 	.buffer_bytes_max =	(256*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 	.period_bytes_max =	(256*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)  *  Capture support device description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) static const struct snd_pcm_hardware snd_trident_capture =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 	.rate_min =		4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 	.rate_max =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 	.channels_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 	.channels_max =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 	.buffer_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 	.period_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)  *  Foldback capture support device description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) static const struct snd_pcm_hardware snd_trident_foldback =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 	.rates =		SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 	.rate_min =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 	.rate_max =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 	.channels_min =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 	.channels_max =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 	.buffer_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) 	.period_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)  *  SPDIF playback support device description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) static const struct snd_pcm_hardware snd_trident_spdif =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 	.rates =		(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 				 SNDRV_PCM_RATE_48000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 	.rate_min =		32000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 	.rate_max =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 	.channels_min =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 	.channels_max =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 	.buffer_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	.period_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) static const struct snd_pcm_hardware snd_trident_spdif_7018 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 				 SNDRV_PCM_INFO_PAUSE /* | SNDRV_PCM_INFO_RESUME */),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 	.rates =		SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 	.rate_min =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 	.rate_max =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 	.channels_min =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 	.channels_max =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 	.buffer_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 	.period_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) static void snd_trident_pcm_free_substream(struct snd_pcm_runtime *runtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	struct snd_trident *trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 	if (voice) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 		trident = voice->trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 		snd_trident_free_voice(trident, voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) static int snd_trident_playback_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 	struct snd_trident_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 	if (voice == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 	snd_trident_pcm_mixer_build(trident, voice, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 	voice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 	runtime->private_data = voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 	runtime->private_free = snd_trident_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 	runtime->hw = snd_trident_playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 	snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)    snd_trident_playback_close
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)    Description: This routine will close the 4DWave playback device. For now 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)                 we will simply free the dma transfer buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) static int snd_trident_playback_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 	struct snd_trident_voice *voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 	snd_trident_pcm_mixer_free(trident, voice, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848)    snd_trident_spdif_open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)    Description: This routine will open the 4DWave SPDIF device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)    Returns:     status  - success or failure flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) static int snd_trident_spdif_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 	struct snd_trident_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 	if (voice == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 	voice->spdif = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 	voice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 	trident->spdif_pcm_bits = trident->spdif_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) 	runtime->private_data = voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 	runtime->private_free = snd_trident_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 		runtime->hw = snd_trident_spdif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 		runtime->hw = snd_trident_spdif_7018;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 	trident->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 	snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 		       SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)    snd_trident_spdif_close
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)    Description: This routine will close the 4DWave SPDIF device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) static int snd_trident_spdif_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) 	unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) 	// restore default SPDIF setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) 		outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) 		outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) 		outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) 		temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) 		if (trident->spdif_ctrl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) 			temp |= SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) 			temp &= ~SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) 		outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 	trident->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) 	snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) 		       SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)    snd_trident_capture_open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)    Description: This routine will open the 4DWave capture device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)    Returns:     status  - success or failure flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) static int snd_trident_capture_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) 	struct snd_trident_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) 	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) 	if (voice == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) 	voice->capture = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) 	voice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) 	runtime->private_data = voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) 	runtime->private_free = snd_trident_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) 	runtime->hw = snd_trident_capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) 	snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)    snd_trident_capture_close
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)    Description: This routine will close the 4DWave capture device. For now 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)                 we will simply free the dma transfer buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) static int snd_trident_capture_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)    snd_trident_foldback_open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)    Description: This routine will open the 4DWave foldback capture device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)    Returns:     status  - success or failure flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) static int snd_trident_foldback_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) 	struct snd_trident_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) 	voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) 	if (voice == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) 	voice->foldback_chan = substream->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) 	voice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) 	runtime->private_data = voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) 	runtime->private_free = snd_trident_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) 	runtime->hw = snd_trident_foldback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)    snd_trident_foldback_close
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)    Description: This routine will close the 4DWave foldback capture device. 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) 		For now we will simply free the dma transfer buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)    Parameters:	substream  - PCM substream class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) static int snd_trident_foldback_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) 	struct snd_trident_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) 	voice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) 	/* stop capture channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) 	outb(0x00, TRID_REG(trident, T4D_RCI + voice->foldback_chan));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)    PCM operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) static const struct snd_pcm_ops snd_trident_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) 	.open =		snd_trident_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) 	.close =	snd_trident_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) 	.hw_params =	snd_trident_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) 	.hw_free =	snd_trident_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) 	.prepare =	snd_trident_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) 	.pointer =	snd_trident_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) static const struct snd_pcm_ops snd_trident_nx_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) 	.open =		snd_trident_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) 	.close =	snd_trident_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) 	.hw_params =	snd_trident_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) 	.hw_free =	snd_trident_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) 	.prepare =	snd_trident_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) 	.pointer =	snd_trident_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) static const struct snd_pcm_ops snd_trident_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) 	.open =		snd_trident_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) 	.close =	snd_trident_capture_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) 	.hw_params =	snd_trident_capture_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) 	.hw_free =	snd_trident_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) 	.prepare =	snd_trident_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) 	.pointer =	snd_trident_capture_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) static const struct snd_pcm_ops snd_trident_si7018_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) 	.open =		snd_trident_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) 	.close =	snd_trident_capture_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) 	.hw_params =	snd_trident_si7018_capture_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) 	.hw_free =	snd_trident_si7018_capture_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) 	.prepare =	snd_trident_si7018_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) 	.pointer =	snd_trident_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) static const struct snd_pcm_ops snd_trident_foldback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) 	.open =		snd_trident_foldback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) 	.close =	snd_trident_foldback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) 	.hw_params =	snd_trident_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) 	.hw_free =	snd_trident_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) 	.prepare =	snd_trident_foldback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) 	.pointer =	snd_trident_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) static const struct snd_pcm_ops snd_trident_nx_foldback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) 	.open =		snd_trident_foldback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) 	.close =	snd_trident_foldback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) 	.hw_params =	snd_trident_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) 	.hw_free =	snd_trident_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) 	.prepare =	snd_trident_foldback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) 	.pointer =	snd_trident_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) static const struct snd_pcm_ops snd_trident_spdif_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) 	.open =		snd_trident_spdif_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) 	.close =	snd_trident_spdif_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) 	.hw_params =	snd_trident_spdif_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) 	.hw_free =	snd_trident_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) 	.prepare =	snd_trident_spdif_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) 	.pointer =	snd_trident_spdif_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) static const struct snd_pcm_ops snd_trident_spdif_7018_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) 	.open =		snd_trident_spdif_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) 	.close =	snd_trident_spdif_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) 	.hw_params =	snd_trident_spdif_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) 	.hw_free =	snd_trident_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) 	.prepare =	snd_trident_spdif_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) 	.trigger =	snd_trident_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) 	.pointer =	snd_trident_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107)    snd_trident_pcm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)    Description: This routine registers the 4DWave device for PCM support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113)    Returns:     None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) int snd_trident_pcm(struct snd_trident *trident, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) 	struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) 	if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) 	pcm->private_data = trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) 	if (trident->tlb.entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_nx_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) 			trident->device != TRIDENT_DEVICE_ID_SI7018 ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) 			&snd_trident_capture_ops :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) 			&snd_trident_si7018_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) 	pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) 	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) 	strcpy(pcm->name, "Trident 4DWave");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) 	trident->pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) 	if (trident->tlb.entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) 		struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) 		for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) 			snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV_SG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) 						   &trident->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) 						   64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) 		snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) 					   SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) 					   &trident->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) 					   64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) 		snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) 					       &trident->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) 					       64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162)    snd_trident_foldback_pcm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)    Description: This routine registers the 4DWave device for foldback PCM support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168)    Returns:     None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) int snd_trident_foldback_pcm(struct snd_trident *trident, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) 	struct snd_pcm *foldback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) 	int num_chan = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) 	struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) 	if (trident->device == TRIDENT_DEVICE_ID_NX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) 		num_chan = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) 	if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) 	foldback->private_data = trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) 	if (trident->tlb.entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) 		snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_nx_foldback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) 		snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_foldback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) 	foldback->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) 	strcpy(foldback->name, "Trident 4DWave");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) 	substream = foldback->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) 	strcpy(substream->name, "Front Mixer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) 	substream = substream->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) 	strcpy(substream->name, "Reverb Mixer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) 	substream = substream->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) 	strcpy(substream->name, "Chorus Mixer");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) 	if (num_chan == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) 		substream = substream->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) 		strcpy(substream->name, "Second AC'97 ADC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) 	trident->foldback = foldback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) 	if (trident->tlb.entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) 		snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV_SG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) 					       &trident->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) 					       0, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) 		snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) 					       &trident->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) 					       64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216)    snd_trident_spdif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218)    Description: This routine registers the 4DWave-NX device for SPDIF support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220)    Parameters:  trident - pointer to target device class for 4DWave-NX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222)    Returns:     None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) int snd_trident_spdif_pcm(struct snd_trident *trident, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) 	struct snd_pcm *spdif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) 	if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) 	spdif->private_data = trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) 		snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) 		snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_7018_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) 	spdif->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) 	strcpy(spdif->name, "Trident 4DWave IEC958");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) 	trident->spdif = spdif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) 	snd_pcm_set_managed_buffer_all(spdif, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) 				       &trident->pci->dev, 64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)  *  Mixer part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256)     snd_trident_spdif_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258)     Description: enable/disable S/PDIF out from ac97 mixer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) #define snd_trident_spdif_control_info	snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) 					 struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) 	unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) 	val = trident->spdif_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) 	ucontrol->value.integer.value[0] = val == kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) 					 struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) 	unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) 	int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) 	val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) 	/* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) 	change = trident->spdif_ctrl != val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) 	trident->spdif_ctrl = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) 		if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) 			outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) 			outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) 		if (trident->spdif == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) 			unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) 			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) 			temp = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & ~SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) 			if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) 				temp |= SPDIF_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) 			outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) static const struct snd_kcontrol_new snd_trident_spdif_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) 	.info =		snd_trident_spdif_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) 	.get =		snd_trident_spdif_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) 	.put =		snd_trident_spdif_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) 	.private_value = 0x28,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318)     snd_trident_spdif_default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320)     Description: put/get the S/PDIF default settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) static int snd_trident_spdif_default_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) 					  struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) 	uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) static int snd_trident_spdif_default_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) 					 struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) 	ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) 	ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) 	ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) 	ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) 					 struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) 	int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) 	val = (ucontrol->value.iec958.status[0] << 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) 	      (ucontrol->value.iec958.status[1] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) 	      (ucontrol->value.iec958.status[2] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) 	      (ucontrol->value.iec958.status[3] << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) 	change = trident->spdif_bits != val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) 	trident->spdif_bits = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) 		if ((inb(TRID_REG(trident, NX_SPCTRL_SPCSO + 3)) & 0x10) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) 			outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) 		if (trident->spdif == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) 			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) static const struct snd_kcontrol_new snd_trident_spdif_default =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) 	.info =		snd_trident_spdif_default_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) 	.get =		snd_trident_spdif_default_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) 	.put =		snd_trident_spdif_default_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380)     snd_trident_spdif_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382)     Description: put/get the S/PDIF mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) static int snd_trident_spdif_mask_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) 				       struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) 	uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) 				      struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) 	ucontrol->value.iec958.status[0] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) 	ucontrol->value.iec958.status[1] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) 	ucontrol->value.iec958.status[2] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) 	ucontrol->value.iec958.status[3] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) static const struct snd_kcontrol_new snd_trident_spdif_mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) 	.info =		snd_trident_spdif_mask_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) 	.get =		snd_trident_spdif_mask_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413)     snd_trident_spdif_stream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415)     Description: put/get the S/PDIF stream settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) static int snd_trident_spdif_stream_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) 					 struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) 	uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) static int snd_trident_spdif_stream_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) 					struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) 	ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) 	ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) 	ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) 	ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) 					struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) 	int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) 	val = (ucontrol->value.iec958.status[0] << 0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) 	      (ucontrol->value.iec958.status[1] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) 	      (ucontrol->value.iec958.status[2] << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) 	      (ucontrol->value.iec958.status[3] << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) 	change = trident->spdif_pcm_bits != val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) 	trident->spdif_pcm_bits = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) 	if (trident->spdif != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) 		if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) 			outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) 			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) static const struct snd_kcontrol_new snd_trident_spdif_stream =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) 	.info =		snd_trident_spdif_stream_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) 	.get =		snd_trident_spdif_stream_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) 	.put =		snd_trident_spdif_stream_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476)     snd_trident_ac97_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478)     Description: enable/disable rear path for ac97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) #define snd_trident_ac97_control_info	snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) 					struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) 	unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) 	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) 	ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) 					struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) 	unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) 	int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) 	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) 	val &= ~(1 << kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) 	if (ucontrol->value.integer.value[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) 		val |= 1 << kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) 	change = val != trident->ac97_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) 	trident->ac97_ctrl = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) 	outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) static const struct snd_kcontrol_new snd_trident_ac97_rear_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) 	.name =         "Rear Path",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) 	.info =		snd_trident_ac97_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) 	.get =		snd_trident_ac97_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) 	.put =		snd_trident_ac97_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) 	.private_value = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526)     snd_trident_vol_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528)     Description: wave & music volume control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) static int snd_trident_vol_control_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) 					struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) 	uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) 	uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) 	uinfo->value.integer.max = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) 				       struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) 	val = trident->musicvol_wavevol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) 	ucontrol->value.integer.value[0] = 255 - ((val >> kcontrol->private_value) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) 	ucontrol->value.integer.value[1] = 255 - ((val >> (kcontrol->private_value + 8)) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) static const DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) 				       struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) 	int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) 	val = trident->musicvol_wavevol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) 	val &= ~(0xffff << kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) 	val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) 	        ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) 	change = val != trident->musicvol_wavevol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) 	outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) static const struct snd_kcontrol_new snd_trident_vol_music_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) 	.name =         "Music Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) 	.info =		snd_trident_vol_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) 	.get =		snd_trident_vol_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) 	.put =		snd_trident_vol_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) 	.private_value = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) 	.tlv = { .p = db_scale_gvol },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) static const struct snd_kcontrol_new snd_trident_vol_wave_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) 	.name =         "Wave Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) 	.info =		snd_trident_vol_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) 	.get =		snd_trident_vol_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) 	.put =		snd_trident_vol_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) 	.private_value = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) 	.tlv = { .p = db_scale_gvol },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596)     snd_trident_pcm_vol_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598)     Description: PCM front volume control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) static int snd_trident_pcm_vol_control_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) 					    struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) 	uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) 	uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) 	uinfo->value.integer.max = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) 		uinfo->value.integer.max = 1023;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) static int snd_trident_pcm_vol_control_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) 					   struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) 		ucontrol->value.integer.value[0] = 1023 - mix->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) 		ucontrol->value.integer.value[0] = 255 - (mix->vol>>2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) 					   struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) 	int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) 		val = 1023 - (ucontrol->value.integer.value[0] & 1023);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) 		val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) 	change = val != mix->vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) 	mix->vol = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) 	if (mix->voice != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) 		snd_trident_write_vol_reg(trident, mix->voice, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) static const struct snd_kcontrol_new snd_trident_pcm_vol_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) 	.name =         "PCM Front Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) 	.count =	32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) 	.info =		snd_trident_pcm_vol_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) 	.get =		snd_trident_pcm_vol_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) 	.put =		snd_trident_pcm_vol_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) 	/* FIXME: no tlv yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664)     snd_trident_pcm_pan_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666)     Description: PCM front pan control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) static int snd_trident_pcm_pan_control_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) 					    struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) 	uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) 	uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) 	uinfo->value.integer.max = 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) static int snd_trident_pcm_pan_control_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) 					   struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) 	ucontrol->value.integer.value[0] = mix->pan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) 	if (ucontrol->value.integer.value[0] & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) 		ucontrol->value.integer.value[0] = (0x3f - (ucontrol->value.integer.value[0] & 0x3f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) 		ucontrol->value.integer.value[0] |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) 					   struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) 	unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) 	int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) 	if (ucontrol->value.integer.value[0] & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) 		val = ucontrol->value.integer.value[0] & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) 		val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) 	change = val != mix->pan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) 	mix->pan = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) 	if (mix->voice != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) 		snd_trident_write_pan_reg(trident, mix->voice, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) static const struct snd_kcontrol_new snd_trident_pcm_pan_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) 	.name =         "PCM Pan Playback Control",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) 	.count =	32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) 	.info =		snd_trident_pcm_pan_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) 	.get =		snd_trident_pcm_pan_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) 	.put =		snd_trident_pcm_pan_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727)     snd_trident_pcm_rvol_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729)     Description: PCM reverb volume control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) static int snd_trident_pcm_rvol_control_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) 					     struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) 	uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) 	uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) 	uinfo->value.integer.max = 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) static int snd_trident_pcm_rvol_control_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) 					    struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) 	ucontrol->value.integer.value[0] = 127 - mix->rvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) 					    struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) 	unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) 	int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) 	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) 	change = val != mix->rvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) 	mix->rvol = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) 	if (mix->voice != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) 		snd_trident_write_rvol_reg(trident, mix->voice, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) static const struct snd_kcontrol_new snd_trident_pcm_rvol_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) 	.name =         "PCM Reverb Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) 	.count = 	32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) 	.info =		snd_trident_pcm_rvol_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) 	.get =		snd_trident_pcm_rvol_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) 	.put =		snd_trident_pcm_rvol_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) 	.tlv = { .p = db_scale_crvol },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785)     snd_trident_pcm_cvol_control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787)     Description: PCM chorus volume control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) static int snd_trident_pcm_cvol_control_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) 					     struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) 	uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) 	uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) 	uinfo->value.integer.max = 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) static int snd_trident_pcm_cvol_control_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) 					    struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) 	ucontrol->value.integer.value[0] = 127 - mix->cvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) 					    struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) 	struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) 	struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) 	unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) 	int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) 	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) 	spin_lock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) 	change = val != mix->cvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) 	mix->cvol = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) 	if (mix->voice != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) 		snd_trident_write_cvol_reg(trident, mix->voice, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) 	spin_unlock_irq(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) static const struct snd_kcontrol_new snd_trident_pcm_cvol_control =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) 	.name =         "PCM Chorus Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) 	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) 	.count =	32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) 	.info =		snd_trident_pcm_cvol_control_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) 	.get =		snd_trident_pcm_cvol_control_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) 	.put =		snd_trident_pcm_cvol_control_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) 	.tlv = { .p = db_scale_crvol },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) static void snd_trident_notify_pcm_change1(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) 					   struct snd_kcontrol *kctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) 					   int num, int activate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) 	struct snd_ctl_elem_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) 	if (! kctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) 	if (activate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) 		kctl->vd[num].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) 		kctl->vd[num].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) 	snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) 		       SNDRV_CTL_EVENT_MASK_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) 		       snd_ctl_build_ioff(&id, kctl, num));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) static void snd_trident_notify_pcm_change(struct snd_trident *trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) 					  struct snd_trident_pcm_mixer *tmix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) 					  int num, int activate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) 	snd_trident_notify_pcm_change1(trident->card, trident->ctl_vol, num, activate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) 	snd_trident_notify_pcm_change1(trident->card, trident->ctl_pan, num, activate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) 	snd_trident_notify_pcm_change1(trident->card, trident->ctl_rvol, num, activate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) 	snd_trident_notify_pcm_change1(trident->card, trident->ctl_cvol, num, activate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) 				       struct snd_trident_voice *voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) 				       struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) 	struct snd_trident_pcm_mixer *tmix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) 	if (snd_BUG_ON(!trident || !voice || !substream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) 	tmix = &trident->pcm_mixer[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) 	tmix->voice = voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) 	tmix->vol = T4D_DEFAULT_PCM_VOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) 	tmix->pan = T4D_DEFAULT_PCM_PAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) 	tmix->rvol = T4D_DEFAULT_PCM_RVOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) 	tmix->cvol = T4D_DEFAULT_PCM_CVOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) 	snd_trident_notify_pcm_change(trident, tmix, substream->number, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_trident_voice *voice, struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) 	struct snd_trident_pcm_mixer *tmix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) 	if (snd_BUG_ON(!trident || !substream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) 	tmix = &trident->pcm_mixer[substream->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) 	tmix->voice = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) 	snd_trident_notify_pcm_change(trident, tmix, substream->number, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898)    snd_trident_mixer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900)    Description: This routine registers the 4DWave device for mixer support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904)    Returns:     None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) 	struct snd_ac97_template _ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) 	struct snd_card *card = trident->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) 	struct snd_kcontrol *kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) 	struct snd_ctl_elem_value *uctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) 	int idx, err, retries = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) 	static const struct snd_ac97_bus_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) 		.write = snd_trident_codec_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) 		.read = snd_trident_codec_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) 	uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) 	if (!uctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) 	if ((err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) 		goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) 	memset(&_ac97, 0, sizeof(_ac97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) 	_ac97.private_data = trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) 	trident->ac97_detect = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931)       __again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) 	if ((err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) 		if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) 			if ((err = snd_trident_sis_reset(trident)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) 				goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) 			if (retries-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) 				goto __again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) 			err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) 		goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) 	/* secondary codec? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) 	    (inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) 		_ac97.num = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) 		err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) 			dev_err(trident->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) 				"SI7018: the secondary codec - invalid access\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) #if 0	// only for my testing purpose --jk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) 			struct snd_ac97 *mc97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) 			err = snd_ac97_modem(trident->card, &_ac97, &mc97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) 			if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) 				dev_err(trident->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) 					"snd_ac97_modem returned error %i\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) 	trident->ac97_detect = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) 		kctl->put(kctl, uctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) 		kctl->put(kctl, uctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) 		outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) 		outl(trident->musicvol_wavevol = 0xffff0000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) 	for (idx = 0; idx < 32; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) 		struct snd_trident_pcm_mixer *tmix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) 		tmix = &trident->pcm_mixer[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) 		tmix->voice = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) 	if ((trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) 		goto __nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) 	if ((err = snd_ctl_add(card, trident->ctl_vol)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) 		goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) 	if ((trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) 		goto __nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) 	if ((err = snd_ctl_add(card, trident->ctl_pan)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) 		goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) 	if ((trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) 		goto __nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) 	if ((err = snd_ctl_add(card, trident->ctl_rvol)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) 		goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) 	if ((trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident)) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) 		goto __nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) 	if ((err = snd_ctl_add(card, trident->ctl_cvol)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) 		goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) 	if (trident->device == TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) 		kctl->put(kctl, uctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) 	if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) 		kctl = snd_ctl_new1(&snd_trident_spdif_control, trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) 		if (kctl == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) 			err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) 		if (trident->ac97->ext_id & AC97_EI_SPDIF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) 			kctl->id.index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) 		if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) 			kctl->id.index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) 		idx = kctl->id.index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) 		if ((err = snd_ctl_add(card, kctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) 		kctl->put(kctl, uctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) 		kctl = snd_ctl_new1(&snd_trident_spdif_default, trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) 		if (kctl == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) 			err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) 		kctl->id.index = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) 		kctl->id.device = pcm_spdif_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) 		if ((err = snd_ctl_add(card, kctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) 		kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) 		if (kctl == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) 			err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) 		kctl->id.index = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) 		kctl->id.device = pcm_spdif_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) 		if ((err = snd_ctl_add(card, kctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) 		kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) 		if (kctl == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) 			err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) 		kctl->id.index = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) 		kctl->id.device = pcm_spdif_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) 		if ((err = snd_ctl_add(card, kctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) 			goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) 		trident->spdif_pcm_ctl = kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) 	goto __out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058)  __nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) 	err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061)  __out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) 	kfree(uctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068)  * gameport interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) #if IS_REACHABLE(CONFIG_GAMEPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) static unsigned char snd_trident_gameport_read(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) 	struct snd_trident *chip = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) 	if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) 	return inb(TRID_REG(chip, GAMEPORT_LEGACY));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) static void snd_trident_gameport_trigger(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) 	struct snd_trident *chip = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) 	if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) 	outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) 	struct snd_trident *chip = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) 	if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) 	*buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) 	for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) 		axes[i] = inw(TRID_REG(chip, GAMEPORT_AXES + i * 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) 		if (axes[i] == 0xffff) axes[i] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105)         
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106)         return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) static int snd_trident_gameport_open(struct gameport *gameport, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) 	struct snd_trident *chip = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) 	if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) 		case GAMEPORT_MODE_COOKED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) 			outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) 			msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) 		case GAMEPORT_MODE_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) 			outb(0, TRID_REG(chip, GAMEPORT_GCR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) int snd_trident_create_gameport(struct snd_trident *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) 	struct gameport *gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) 	chip->gameport = gp = gameport_allocate_port();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) 	if (!gp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) 		dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) 			"cannot allocate memory for gameport\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) 	gameport_set_name(gp, "Trident 4DWave");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) 	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) 	gameport_set_dev_parent(gp, &chip->pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) 	gameport_set_port_data(gp, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) 	gp->fuzz = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) 	gp->read = snd_trident_gameport_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) 	gp->trigger = snd_trident_gameport_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) 	gp->cooked_read = snd_trident_gameport_cooked_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) 	gp->open = snd_trident_gameport_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) 	gameport_register_port(gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) static inline void snd_trident_free_gameport(struct snd_trident *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) 	if (chip->gameport) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) 		gameport_unregister_port(chip->gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) 		chip->gameport = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) int snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) static inline void snd_trident_free_gameport(struct snd_trident *chip) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) #endif /* CONFIG_GAMEPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169)  * delay for 1 tick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) static inline void do_delay(struct snd_trident *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) 	schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177)  *  SiS reset routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) static int snd_trident_sis_reset(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) 	unsigned long end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) 	int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) 	r = trident->in_suspend ? 0 : 2;	/* count of retries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187)       __si7018_retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) 	pci_write_config_byte(trident->pci, 0x46, 0x04);	/* SOFTWARE RESET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) 	pci_write_config_byte(trident->pci, 0x46, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) 	/* disable AC97 GPIO interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) 	outb(0x00, TRID_REG(trident, SI_AC97_GPIO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) 	/* initialize serial interface, force cold reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) 	i = PCMOUT|SURROUT|CENTEROUT|LFEOUT|SECONDARY_ID|COLD_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) 	outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) 	udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) 	/* remove cold reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) 	i &= ~COLD_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) 	outl(i, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) 	udelay(2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) 	/* wait, until the codec is ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) 	end_time = (jiffies + (HZ * 3) / 4) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) 		if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_PRIMARY_READY) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) 			goto __si7018_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) 		do_delay(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) 	} while (time_after_eq(end_time, jiffies));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) 	dev_err(trident->card->dev, "AC'97 codec ready error [0x%x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) 		inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) 	if (r-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) 		end_time = jiffies + HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) 		do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) 			do_delay(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) 		} while (time_after_eq(end_time, jiffies));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) 		goto __si7018_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218)       __si7018_ok:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) 	/* wait for the second codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) 		if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) & SI_AC97_SECONDARY_READY) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) 		do_delay(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) 	} while (time_after_eq(end_time, jiffies));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) 	/* enable 64 channel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) 	outl(BANK_B_EN, TRID_REG(trident, T4D_LFO_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) /*  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231)  *  /proc interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) static void snd_trident_proc_read(struct snd_info_entry *entry, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) 				  struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) 	struct snd_trident *trident = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) 	char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) 	switch (trident->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) 	case TRIDENT_DEVICE_ID_SI7018:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) 		s = "SiS 7018 Audio";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) 	case TRIDENT_DEVICE_ID_DX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) 		s = "Trident 4DWave PCI DX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) 	case TRIDENT_DEVICE_ID_NX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) 		s = "Trident 4DWave PCI NX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) 		s = "???";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) 	snd_iprintf(buffer, "%s\n\n", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) 	snd_iprintf(buffer, "Spurious IRQs    : %d\n", trident->spurious_irq_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) 	snd_iprintf(buffer, "Spurious IRQ dlta: %d\n", trident->spurious_irq_max_delta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) 	if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) 		snd_iprintf(buffer, "IEC958 Mixer Out : %s\n", trident->spdif_ctrl == 0x28 ? "on" : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) 	if (trident->device == TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) 		snd_iprintf(buffer, "Rear Speakers    : %s\n", trident->ac97_ctrl & 0x00000010 ? "on" : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) 		if (trident->tlb.entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) 			snd_iprintf(buffer,"\nVirtual Memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) 			snd_iprintf(buffer, "Memory Maximum : %d\n", trident->tlb.memhdr->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) 			snd_iprintf(buffer, "Memory Used    : %d\n", trident->tlb.memhdr->used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) 			snd_iprintf(buffer, "Memory Free    : %d\n", snd_util_mem_avail(trident->tlb.memhdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) static void snd_trident_proc_init(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) 	const char *s = "trident";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) 	if (trident->device == TRIDENT_DEVICE_ID_SI7018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) 		s = "sis7018";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) 	snd_card_ro_proc_new(trident->card, s, trident, snd_trident_proc_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) static int snd_trident_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) 	struct snd_trident *trident = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) 	return snd_trident_free(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285)    snd_trident_tlb_alloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287)    Description: Allocate and set up the TLB page table on 4D NX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) 		Each entry has 4 bytes (physical PCI address).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290)    Parameters:  trident - pointer to target device class for 4DWave.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292)    Returns:     0 or negative error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) static int snd_trident_tlb_alloc(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) 	/* TLB array must be aligned to 16kB !!! so we allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) 	   32kB region and correct offset when necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) 				2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) 		dev_err(trident->card->dev, "unable to allocate TLB buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) 	trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) 	trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) 	/* allocate shadow TLB page table (virtual addresses) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) 	trident->tlb.shadow_entries =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) 		vmalloc(array_size(SNDRV_TRIDENT_MAX_PAGES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) 				   sizeof(unsigned long)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) 	if (!trident->tlb.shadow_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) 	/* allocate and setup silent page and initialise TLB entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) 				SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) 		dev_err(trident->card->dev, "unable to allocate silent page\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) 	memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) 	for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) 		trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) 		trident->tlb.shadow_entries[i] = (unsigned long)trident->tlb.silent_page.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) 	/* use emu memory block manager code to manage tlb page allocation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) 	trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) 	if (trident->tlb.memhdr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) 	trident->tlb.memhdr->block_extra_size = sizeof(struct snd_trident_memblk_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339)  * initialize 4D DX chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) static void snd_trident_stop_all_voices(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) 	outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) 	outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) 	outl(0, TRID_REG(trident, T4D_AINTEN_A));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) 	outl(0, TRID_REG(trident, T4D_AINTEN_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) static int snd_trident_4d_dx_init(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) 	struct pci_dev *pci = trident->pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) 	unsigned long end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) 	/* reset the legacy configuration and whole audio/wavetable block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) 	pci_write_config_dword(pci, 0x40, 0);	/* DDMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) 	pci_write_config_byte(pci, 0x44, 0);	/* ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) 	pci_write_config_byte(pci, 0x45, 0);	/* Legacy DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) 	pci_write_config_byte(pci, 0x46, 4); /* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) 	pci_write_config_byte(pci, 0x46, 0); /* release reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) 	/* warm reset of the AC'97 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) 	outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) 	outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) 	/* DAC on, disable SB IRQ and try to force ADC valid signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) 	trident->ac97_ctrl = 0x0000004a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) 	outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) 	/* wait, until the codec is ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) 	end_time = (jiffies + (HZ * 3) / 4) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) 		if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) 			goto __dx_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) 		do_delay(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) 	} while (time_after_eq(end_time, jiffies));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) 	dev_err(trident->card->dev, "AC'97 codec ready error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381)  __dx_ok:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) 	snd_trident_stop_all_voices(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388)  * initialize 4D NX chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) static int snd_trident_4d_nx_init(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) 	struct pci_dev *pci = trident->pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) 	unsigned long end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) 	/* reset the legacy configuration and whole audio/wavetable block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) 	pci_write_config_dword(pci, 0x40, 0);	/* DDMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) 	pci_write_config_byte(pci, 0x44, 0);	/* ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) 	pci_write_config_byte(pci, 0x45, 0);	/* Legacy DMA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) 	pci_write_config_byte(pci, 0x46, 1); /* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) 	pci_write_config_byte(pci, 0x46, 0); /* release reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) 	/* warm reset of the AC'97 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) 	outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) 	outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) 	/* wait, until the codec is ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) 	end_time = (jiffies + (HZ * 3) / 4) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) 		if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) 			goto __nx_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) 		do_delay(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) 	} while (time_after_eq(end_time, jiffies));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) 	dev_err(trident->card->dev, "AC'97 codec ready error [0x%x]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) 		inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420)  __nx_ok:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) 	/* DAC on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) 	trident->ac97_ctrl = 0x00000002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) 	outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) 	/* disable SB IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) 	outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) 	snd_trident_stop_all_voices(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) 	if (trident->tlb.entries != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) 		unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) 		/* enable virtual addressing via TLB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) 		i = trident->tlb.entries_dmaaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) 		i |= 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) 		outl(i, TRID_REG(trident, NX_TLBC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) 		outl(0, TRID_REG(trident, NX_TLBC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) 	/* initialize S/PDIF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) 	outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) 	outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446)  * initialize sis7018 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) static int snd_trident_sis_init(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) 	if ((err = snd_trident_sis_reset(trident)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) 	snd_trident_stop_all_voices(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) 	/* initialize S/PDIF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) 	outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464)    snd_trident_create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466)    Description: This routine will create the device specific class for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467)                 the 4DWave card. It will also perform basic initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469)    Parameters:  card  - which card to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470)                 pci   - interface to PCI bus resource info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471)                 dma1ptr - playback dma buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472)                 dma2ptr - capture dma buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473)                 irqptr  -  interrupt resource info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475)    Returns:     4DWave device class private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) int snd_trident_create(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) 		       struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) 		       int pcm_streams,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) 		       int pcm_spdif_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) 		       int max_wavetable_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) 		       struct snd_trident ** rtrident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) 	struct snd_trident *trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) 	int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) 	struct snd_trident_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) 	struct snd_trident_pcm_mixer *tmix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) 	static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) 		.dev_free =	snd_trident_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) 	*rtrident = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) 	/* enable PCI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) 	if ((err = pci_enable_device(pci)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) 	/* check, if we can restrict PCI DMA transfers to 30 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) 	if (dma_set_mask(&pci->dev, DMA_BIT_MASK(30)) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) 	    dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(30)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) 		dev_err(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) 			"architecture does not support 30bit PCI busmaster DMA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) 		pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) 	trident = kzalloc(sizeof(*trident), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) 	if (trident == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) 		pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) 	trident->device = (pci->vendor << 16) | pci->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) 	trident->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) 	trident->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) 	spin_lock_init(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) 	spin_lock_init(&trident->event_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) 	spin_lock_init(&trident->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) 	if (pcm_streams < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) 		pcm_streams = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) 	if (pcm_streams > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) 		pcm_streams = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) 	trident->ChanPCM = pcm_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) 	if (max_wavetable_size < 0 )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) 		max_wavetable_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) 	trident->synth.max_size = max_wavetable_size * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) 	trident->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) 	trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) 	pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) 	if ((err = pci_request_regions(pci, "Trident Audio")) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) 		kfree(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) 		pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) 	trident->port = pci_resource_start(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) 	if (request_irq(pci->irq, snd_trident_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) 			KBUILD_MODNAME, trident)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) 		dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) 		snd_trident_free(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) 	trident->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) 	card->sync_irq = trident->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) 	/* allocate 16k-aligned TLB for NX cards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) 	trident->tlb.entries = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) 	trident->tlb.buffer.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) 	if (trident->device == TRIDENT_DEVICE_ID_NX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) 		if ((err = snd_trident_tlb_alloc(trident)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) 			snd_trident_free(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) 	trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) 	/* initialize chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) 	switch (trident->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) 	case TRIDENT_DEVICE_ID_DX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) 		err = snd_trident_4d_dx_init(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) 	case TRIDENT_DEVICE_ID_NX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) 		err = snd_trident_4d_nx_init(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) 	case TRIDENT_DEVICE_ID_SI7018:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) 		err = snd_trident_sis_init(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) 		snd_BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) 		snd_trident_free(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) 		snd_trident_free(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) 	if ((err = snd_trident_mixer(trident, pcm_spdif_device)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) 	/* initialise synth voices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) 	for (i = 0; i < 64; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) 		voice = &trident->synth.voices[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) 		voice->number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) 		voice->trident = trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) 	/* initialize pcm mixer entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) 	for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) 		tmix = &trident->pcm_mixer[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) 		tmix->vol = T4D_DEFAULT_PCM_VOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) 		tmix->pan = T4D_DEFAULT_PCM_PAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) 		tmix->rvol = T4D_DEFAULT_PCM_RVOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) 		tmix->cvol = T4D_DEFAULT_PCM_CVOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) 	snd_trident_enable_eso(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) 	snd_trident_proc_init(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) 	*rtrident = trident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611)    snd_trident_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613)    Description: This routine will free the device specific class for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614)                 the 4DWave card. 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616)    Parameters:  trident  - device specific private data for 4DWave card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618)    Returns:     None.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) static int snd_trident_free(struct snd_trident *trident)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) 	snd_trident_free_gameport(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) 	snd_trident_disable_eso(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) 	// Disable S/PDIF out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) 	if (trident->device == TRIDENT_DEVICE_ID_NX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) 		outb(0x00, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) 	else if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) 		outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) 	if (trident->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) 		free_irq(trident->irq, trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) 	if (trident->tlb.buffer.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) 		outl(0, TRID_REG(trident, NX_TLBC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) 		snd_util_memhdr_free(trident->tlb.memhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) 		if (trident->tlb.silent_page.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) 			snd_dma_free_pages(&trident->tlb.silent_page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) 		vfree(trident->tlb.shadow_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) 		snd_dma_free_pages(&trident->tlb.buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) 	pci_release_regions(trident->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) 	pci_disable_device(trident->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) 	kfree(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) /*---------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649)    snd_trident_interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651)    Description: ISR for Trident 4DWave device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652)                 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653)    Parameters:  trident  - device specific private data for 4DWave card
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655)    Problems:    It seems that Trident chips generates interrupts more than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656)                 one time in special cases. The spurious interrupts are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657)                 detected via sample timer (T4D_STIMER) and computing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658)                 corresponding delta value. The limits are detected with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659)                 the method try & fail so it is possible that it won't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660)                 work on all computers. [jaroslav]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662)    Returns:     None.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664)   ---------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) static irqreturn_t snd_trident_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) 	struct snd_trident *trident = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) 	unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) 	int delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) 	struct snd_trident_voice *voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) 	audio_int = inl(TRID_REG(trident, T4D_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) 	if ((audio_int & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) 	if (audio_int & ADDRESS_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) 		// get interrupt status for all channels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) 		spin_lock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) 		stimer = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) 		chn_int = inl(TRID_REG(trident, T4D_AINT_A));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) 		if (chn_int == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) 			goto __skip1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) 		outl(chn_int, TRID_REG(trident, T4D_AINT_A));	/* ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) 	      __skip1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) 		chn_int = inl(TRID_REG(trident, T4D_AINT_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) 		if (chn_int == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) 			goto __skip2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) 		for (channel = 63; channel >= 32; channel--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) 			mask = 1 << (channel&0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) 			if ((chn_int & mask) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) 			voice = &trident->synth.voices[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) 			if (!voice->pcm || voice->substream == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) 				outl(mask, TRID_REG(trident, T4D_STOP_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) 			delta = (int)stimer - (int)voice->stimer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) 			if (delta < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) 				delta = -delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) 			if ((unsigned int)delta < voice->spurious_threshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) 				/* do some statistics here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) 				trident->spurious_irq_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) 				if (trident->spurious_irq_max_delta < (unsigned int)delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) 					trident->spurious_irq_max_delta = delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) 			voice->stimer = stimer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) 			if (voice->isync) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) 				if (!voice->isync3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) 					tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) 					if (trident->bDMAStart & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) 						tmp >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) 					if (tmp > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) 						tmp = voice->isync_max - tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) 					tmp = inl(TRID_REG(trident, NX_SPCTRL_SPCSO)) & 0x00ffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) 				if (tmp < voice->isync_mark) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) 					if (tmp > 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) 						tmp = voice->isync_ESO - 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) 					else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) 						tmp = voice->isync_ESO + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) 					/* update ESO for IRQ voice to preserve sync */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) 					snd_trident_stop_voice(trident, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) 					snd_trident_write_eso_reg(trident, voice, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) 					snd_trident_start_voice(trident, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) 			} else if (voice->isync2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) 				voice->isync2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) 				/* write original ESO and update CSO for IRQ voice to preserve sync */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) 				snd_trident_stop_voice(trident, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) 				snd_trident_write_cso_reg(trident, voice, voice->isync_mark);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) 				snd_trident_write_eso_reg(trident, voice, voice->ESO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) 				snd_trident_start_voice(trident, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) 			if (voice->extra) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) 				/* update CSO for extra voice to preserve sync */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) 				snd_trident_stop_voice(trident, voice->extra->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) 				snd_trident_write_cso_reg(trident, voice->extra, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) 				snd_trident_start_voice(trident, voice->extra->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) 			spin_unlock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) 			snd_pcm_period_elapsed(voice->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) 			spin_lock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) 		outl(chn_int, TRID_REG(trident, T4D_AINT_B));	/* ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) 	      __skip2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) 		spin_unlock(&trident->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) 	if (audio_int & MPU401_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) 		if (trident->rmidi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) 			snd_mpu401_uart_interrupt(irq, trident->rmidi->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) 			inb(TRID_REG(trident, T4D_MPUR0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) 	// outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(trident, T4D_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) 	struct snd_trident_voice *pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) 	spin_lock_irqsave(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) 	if (type == SNDRV_TRIDENT_VOICE_TYPE_PCM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) 		idx = snd_trident_allocate_pcm_channel(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) 		if(idx < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) 			spin_unlock_irqrestore(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) 		pvoice = &trident->synth.voices[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) 		pvoice->use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) 		pvoice->pcm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) 		pvoice->capture = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) 		pvoice->spdif = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) 		pvoice->memblk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) 		pvoice->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) 		spin_unlock_irqrestore(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) 		return pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) 	if (type == SNDRV_TRIDENT_VOICE_TYPE_SYNTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) 		idx = snd_trident_allocate_synth_channel(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) 		if(idx < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) 			spin_unlock_irqrestore(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) 		pvoice = &trident->synth.voices[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) 		pvoice->use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) 		pvoice->synth = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) 		pvoice->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) 		pvoice->port = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) 		pvoice->memblk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) 		spin_unlock_irqrestore(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) 		return pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) 	if (type == SNDRV_TRIDENT_VOICE_TYPE_MIDI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) 	spin_unlock_irqrestore(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) EXPORT_SYMBOL(snd_trident_alloc_voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) 	void (*private_free)(struct snd_trident_voice *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) 	if (voice == NULL || !voice->use)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) 	snd_trident_clear_voices(trident, voice->number, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) 	spin_lock_irqsave(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) 	private_free = voice->private_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) 	voice->private_free = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) 	voice->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) 	if (voice->pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) 		snd_trident_free_pcm_channel(trident, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) 	if (voice->synth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) 		snd_trident_free_synth_channel(trident, voice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) 	voice->use = voice->pcm = voice->synth = voice->midi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) 	voice->capture = voice->spdif = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) 	voice->sample_ops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) 	voice->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) 	voice->extra = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) 	spin_unlock_irqrestore(&trident->voice_alloc, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) 	if (private_free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) 		private_free(voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) EXPORT_SYMBOL(snd_trident_free_voice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) 	unsigned int i, val, mask[2] = { 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) 	if (snd_BUG_ON(v_min > 63 || v_max > 63))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) 	for (i = v_min; i <= v_max; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) 		mask[i >> 5] |= 1 << (i & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) 	if (mask[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) 		outl(mask[0], TRID_REG(trident, T4D_STOP_A));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) 		val = inl(TRID_REG(trident, T4D_AINTEN_A));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) 		outl(val & ~mask[0], TRID_REG(trident, T4D_AINTEN_A));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) 	if (mask[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) 		outl(mask[1], TRID_REG(trident, T4D_STOP_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) 		val = inl(TRID_REG(trident, T4D_AINTEN_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) 		outl(val & ~mask[1], TRID_REG(trident, T4D_AINTEN_B));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) static int snd_trident_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) 	struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) 	struct snd_trident *trident = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) 	trident->in_suspend = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) 	snd_ac97_suspend(trident->ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) 	snd_ac97_suspend(trident->ac97_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) static int snd_trident_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) 	struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) 	struct snd_trident *trident = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) 	switch (trident->device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) 	case TRIDENT_DEVICE_ID_DX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) 		snd_trident_4d_dx_init(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) 	case TRIDENT_DEVICE_ID_NX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) 		snd_trident_4d_nx_init(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) 	case TRIDENT_DEVICE_ID_SI7018:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) 		snd_trident_sis_init(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) 	snd_ac97_resume(trident->ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) 	snd_ac97_resume(trident->ac97_sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) 	/* restore some registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) 	outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) 	snd_trident_enable_eso(trident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) 	trident->in_suspend = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) SIMPLE_DEV_PM_OPS(snd_trident_pm, snd_trident_suspend, snd_trident_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) #endif /* CONFIG_PM_SLEEP */