^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 */