diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/pci/emu10k1')
22 files changed, 0 insertions, 15875 deletions
diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/Makefile b/ANDROID_3.4.5/sound/pci/emu10k1/Makefile deleted file mode 100644 index fc5591e7..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-emu10k1-objs := emu10k1.o emu10k1_main.o \ - irq.o memory.o voice.o emumpu401.o emupcm.o io.o \ - emuproc.o emumixer.o emufx.o timer.o p16v.o -snd-emu10k1-synth-objs := emu10k1_synth.o emu10k1_callback.o emu10k1_patch.o -snd-emu10k1x-objs := emu10k1x.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_EMU10K1) += snd-emu10k1.o -obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-emu10k1-synth.o -obj-$(CONFIG_SND_EMU10K1X) += snd-emu10k1x.o diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c deleted file mode 100644 index 790c65d9..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * The driver for the EMU10K1 (SB Live!) based soundcards - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> - * Added support for Audigy 2 Value. - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - */ - -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/time.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/emu10k1.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("EMU10K1"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," - "{Creative Labs,SB Audigy}}"); - -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) -#define ENABLE_SYNTH -#include <sound/emu10k1_synth.h> -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ -static int extin[SNDRV_CARDS]; -static int extout[SNDRV_CARDS]; -static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; -static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; -static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; -static bool enable_ir[SNDRV_CARDS]; -static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ -static uint delay_pcm_irq[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the EMU10K1 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the EMU10K1 soundcard."); -module_param_array(extin, int, NULL, 0444); -MODULE_PARM_DESC(extin, "Available external inputs for FX8010. Zero=default."); -module_param_array(extout, int, NULL, 0444); -MODULE_PARM_DESC(extout, "Available external outputs for FX8010. Zero=default."); -module_param_array(seq_ports, int, NULL, 0444); -MODULE_PARM_DESC(seq_ports, "Allocated sequencer ports for internal synthesizer."); -module_param_array(max_synth_voices, int, NULL, 0444); -MODULE_PARM_DESC(max_synth_voices, "Maximum number of voices for WaveTable."); -module_param_array(max_buffer_size, int, NULL, 0444); -MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); -module_param_array(enable_ir, bool, NULL, 0444); -MODULE_PARM_DESC(enable_ir, "Enable IR."); -module_param_array(subsystem, uint, NULL, 0444); -MODULE_PARM_DESC(subsystem, "Force card subsystem model."); -module_param_array(delay_pcm_irq, uint, NULL, 0444); -MODULE_PARM_DESC(delay_pcm_irq, "Delay PCM interrupt by specified number of samples (default 0)."); -/* - * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 - */ -static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1_ids) = { - { PCI_VDEVICE(CREATIVE, 0x0002), 0 }, /* EMU10K1 */ - { PCI_VDEVICE(CREATIVE, 0x0004), 1 }, /* Audigy */ - { PCI_VDEVICE(CREATIVE, 0x0008), 1 }, /* Audigy 2 Value SB0400 */ - { 0, } -}; - -/* - * Audigy 2 Value notes: - * A_IOCFG Input (GPIO) - * 0x400 = Front analog jack plugged in. (Green socket) - * 0x1000 = Read analog jack plugged in. (Black socket) - * 0x2000 = Center/LFE analog jack plugged in. (Orange socket) - * A_IOCFG Output (GPIO) - * 0x60 = Sound out of front Left. - * Win sets it to 0xXX61 - */ - -MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); - -static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct snd_emu10k1 *emu; -#ifdef ENABLE_SYNTH - struct snd_seq_device *wave = NULL; -#endif - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - if (max_buffer_size[dev] < 32) - max_buffer_size[dev] = 32; - else if (max_buffer_size[dev] > 1024) - max_buffer_size[dev] = 1024; - if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], - (long)max_buffer_size[dev] * 1024 * 1024, - enable_ir[dev], subsystem[dev], - &emu)) < 0) - goto error; - card->private_data = emu; - emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; - if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) - goto error; - if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) - goto error; - if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) - goto error; - /* This stores the periods table. */ - if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 1024, &emu->p16v_buffer)) < 0) - goto error; - } - - if ((err = snd_emu10k1_mixer(emu, 0, 3)) < 0) - goto error; - - if ((err = snd_emu10k1_timer(emu, 0)) < 0) - goto error; - - if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) - goto error; - if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) - goto error; - } - if (emu->audigy) { - if ((err = snd_emu10k1_audigy_midi(emu)) < 0) - goto error; - } else { - if ((err = snd_emu10k1_midi(emu)) < 0) - goto error; - } - if ((err = snd_emu10k1_fx8010_new(emu, 0, NULL)) < 0) - goto error; -#ifdef ENABLE_SYNTH - if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, - sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 || - wave == NULL) { - snd_printk(KERN_WARNING "can't initialize Emu10k1 wavetable synth\n"); - } else { - struct snd_emu10k1_synth_arg *arg; - arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); - strcpy(wave->name, "Emu-10k1 Synth"); - arg->hwptr = emu; - arg->index = 1; - arg->seq_ports = seq_ports[dev]; - arg->max_voices = max_synth_voices[dev]; - } -#endif - - strcpy(card->driver, emu->card_capabilities->driver); - strcpy(card->shortname, emu->card_capabilities->name); - snprintf(card->longname, sizeof(card->longname), - "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", - card->shortname, emu->revision, emu->serial, emu->port, emu->irq); - - if ((err = snd_card_register(card)) < 0) - goto error; - - pci_set_drvdata(pci, card); - dev++; - return 0; - - error: - snd_card_free(card); - return err; -} - -static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - - -#ifdef CONFIG_PM -static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_emu10k1 *emu = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(emu->pcm); - snd_pcm_suspend_all(emu->pcm_mic); - snd_pcm_suspend_all(emu->pcm_efx); - snd_pcm_suspend_all(emu->pcm_multi); - snd_pcm_suspend_all(emu->pcm_p16v); - - snd_ac97_suspend(emu->ac97); - - snd_emu10k1_efx_suspend(emu); - snd_emu10k1_suspend_regs(emu); - if (emu->card_capabilities->ca0151_chip) - snd_p16v_suspend(emu); - - snd_emu10k1_done(emu); - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} - -static int snd_emu10k1_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct snd_emu10k1 *emu = card->private_data; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "emu10k1: pci_enable_device failed, " - "disabling device\n"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - snd_emu10k1_resume_init(emu); - snd_emu10k1_efx_resume(emu); - snd_ac97_resume(emu->ac97); - snd_emu10k1_resume_regs(emu); - - if (emu->card_capabilities->ca0151_chip) - snd_p16v_resume(emu); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_emu10k1_ids, - .probe = snd_card_emu10k1_probe, - .remove = __devexit_p(snd_card_emu10k1_remove), -#ifdef CONFIG_PM - .suspend = snd_emu10k1_suspend, - .resume = snd_emu10k1_resume, -#endif -}; - -static int __init alsa_card_emu10k1_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_emu10k1_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_emu10k1_init) -module_exit(alsa_card_emu10k1_exit) diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c deleted file mode 100644 index a0afa505..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * synth callback routines for Emu10k1 - * - * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/export.h> -#include "emu10k1_synth_local.h" -#include <sound/asoundef.h> - -/* voice status */ -enum { - V_FREE=0, V_OFF, V_RELEASED, V_PLAYING, V_END -}; - -/* Keeps track of what we are finding */ -struct best_voice { - unsigned int time; - int voice; -}; - -/* - * prototypes - */ -static void lookup_voices(struct snd_emux *emux, struct snd_emu10k1 *hw, - struct best_voice *best, int active_only); -static struct snd_emux_voice *get_voice(struct snd_emux *emux, - struct snd_emux_port *port); -static int start_voice(struct snd_emux_voice *vp); -static void trigger_voice(struct snd_emux_voice *vp); -static void release_voice(struct snd_emux_voice *vp); -static void update_voice(struct snd_emux_voice *vp, int update); -static void terminate_voice(struct snd_emux_voice *vp); -static void free_voice(struct snd_emux_voice *vp); -static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); -static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); -static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp); - -/* - * Ensure a value is between two points - * macro evaluates its args more than once, so changed to upper-case. - */ -#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0) -#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0) - - -/* - * set up operators - */ -static struct snd_emux_operators emu10k1_ops = { - .owner = THIS_MODULE, - .get_voice = get_voice, - .prepare = start_voice, - .trigger = trigger_voice, - .release = release_voice, - .update = update_voice, - .terminate = terminate_voice, - .free_voice = free_voice, - .sample_new = snd_emu10k1_sample_new, - .sample_free = snd_emu10k1_sample_free, -}; - -void -snd_emu10k1_ops_setup(struct snd_emux *emux) -{ - emux->ops = emu10k1_ops; -} - - -/* - * get more voice for pcm - * - * terminate most inactive voice and give it as a pcm voice. - */ -int -snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) -{ - struct snd_emux *emu; - struct snd_emux_voice *vp; - struct best_voice best[V_END]; - unsigned long flags; - int i; - - emu = hw->synth; - - spin_lock_irqsave(&emu->voice_lock, flags); - lookup_voices(emu, hw, best, 1); /* no OFF voices */ - for (i = 0; i < V_END; i++) { - if (best[i].voice >= 0) { - int ch; - vp = &emu->voices[best[i].voice]; - if ((ch = vp->ch) < 0) { - /* - printk(KERN_WARNING - "synth_get_voice: ch < 0 (%d) ??", i); - */ - continue; - } - vp->emu->num_voices--; - vp->ch = -1; - vp->state = SNDRV_EMUX_ST_OFF; - spin_unlock_irqrestore(&emu->voice_lock, flags); - return ch; - } - } - spin_unlock_irqrestore(&emu->voice_lock, flags); - - /* not found */ - return -ENOMEM; -} - - -/* - * turn off the voice (not terminated) - */ -static void -release_voice(struct snd_emux_voice *vp) -{ - int dcysusv; - struct snd_emu10k1 *hw; - - hw = vp->hw; - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease; - snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv); - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK; - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, dcysusv); -} - - -/* - * terminate the voice - */ -static void -terminate_voice(struct snd_emux_voice *vp) -{ - struct snd_emu10k1 *hw; - - if (snd_BUG_ON(!vp)) - return; - hw = vp->hw; - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); - if (vp->block) { - struct snd_emu10k1_memblk *emem; - emem = (struct snd_emu10k1_memblk *)vp->block; - if (emem->map_locked > 0) - emem->map_locked--; - } -} - -/* - * release the voice to system - */ -static void -free_voice(struct snd_emux_voice *vp) -{ - struct snd_emu10k1 *hw; - - hw = vp->hw; - /* FIXME: emu10k1_synth is broken. */ - /* This can get called with hw == 0 */ - /* Problem apparent on plug, unplug then plug */ - /* on the Audigy 2 ZS Notebook. */ - if (hw && (vp->ch >= 0)) { - snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00); - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK); - // snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0); - snd_emu10k1_ptr_write(hw, VTFT, vp->ch, 0xffff); - snd_emu10k1_ptr_write(hw, CVCF, vp->ch, 0xffff); - snd_emu10k1_voice_free(hw, &hw->voices[vp->ch]); - vp->emu->num_voices--; - vp->ch = -1; - } -} - - -/* - * update registers - */ -static void -update_voice(struct snd_emux_voice *vp, int update) -{ - struct snd_emu10k1 *hw; - - hw = vp->hw; - if (update & SNDRV_EMUX_UPDATE_VOLUME) - snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol); - if (update & SNDRV_EMUX_UPDATE_PITCH) - snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch); - if (update & SNDRV_EMUX_UPDATE_PAN) { - snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_A, vp->ch, vp->apan); - snd_emu10k1_ptr_write(hw, PTRX_FXSENDAMOUNT_B, vp->ch, vp->aaux); - } - if (update & SNDRV_EMUX_UPDATE_FMMOD) - set_fmmod(hw, vp); - if (update & SNDRV_EMUX_UPDATE_TREMFREQ) - snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq); - if (update & SNDRV_EMUX_UPDATE_FM2FRQ2) - set_fm2frq2(hw, vp); - if (update & SNDRV_EMUX_UPDATE_Q) - set_filterQ(hw, vp); -} - - -/* - * look up voice table - get the best voice in order of preference - */ -/* spinlock held! */ -static void -lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw, - struct best_voice *best, int active_only) -{ - struct snd_emux_voice *vp; - struct best_voice *bp; - int i; - - for (i = 0; i < V_END; i++) { - best[i].time = (unsigned int)-1; /* XXX MAX_?INT really */; - best[i].voice = -1; - } - - /* - * Go through them all and get a best one to use. - * NOTE: could also look at volume and pick the quietest one. - */ - for (i = 0; i < emu->max_voices; i++) { - int state, val; - - vp = &emu->voices[i]; - state = vp->state; - if (state == SNDRV_EMUX_ST_OFF) { - if (vp->ch < 0) { - if (active_only) - continue; - bp = best + V_FREE; - } else - bp = best + V_OFF; - } - else if (state == SNDRV_EMUX_ST_RELEASED || - state == SNDRV_EMUX_ST_PENDING) { - bp = best + V_RELEASED; -#if 1 - val = snd_emu10k1_ptr_read(hw, CVCF_CURRENTVOL, vp->ch); - if (! val) - bp = best + V_OFF; -#endif - } - else if (state == SNDRV_EMUX_ST_STANDBY) - continue; - else if (state & SNDRV_EMUX_ST_ON) - bp = best + V_PLAYING; - else - continue; - - /* check if sample is finished playing (non-looping only) */ - if (bp != best + V_OFF && bp != best + V_FREE && - (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) { - val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch); - if (val >= vp->reg.loopstart) - bp = best + V_OFF; - } - - if (vp->time < bp->time) { - bp->time = vp->time; - bp->voice = i; - } - } -} - -/* - * get an empty voice - * - * emu->voice_lock is already held. - */ -static struct snd_emux_voice * -get_voice(struct snd_emux *emu, struct snd_emux_port *port) -{ - struct snd_emu10k1 *hw; - struct snd_emux_voice *vp; - struct best_voice best[V_END]; - int i; - - hw = emu->hw; - - lookup_voices(emu, hw, best, 0); - for (i = 0; i < V_END; i++) { - if (best[i].voice >= 0) { - vp = &emu->voices[best[i].voice]; - if (vp->ch < 0) { - /* allocate a voice */ - struct snd_emu10k1_voice *hwvoice; - if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL) - continue; - vp->ch = hwvoice->number; - emu->num_voices++; - } - return vp; - } - } - - /* not found */ - return NULL; -} - -/* - * prepare envelopes and LFOs - */ -static int -start_voice(struct snd_emux_voice *vp) -{ - unsigned int temp; - int ch; - unsigned int addr, mapped_offset; - struct snd_midi_channel *chan; - struct snd_emu10k1 *hw; - struct snd_emu10k1_memblk *emem; - - hw = vp->hw; - ch = vp->ch; - if (snd_BUG_ON(ch < 0)) - return -EINVAL; - chan = vp->chan; - - emem = (struct snd_emu10k1_memblk *)vp->block; - if (emem == NULL) - return -EINVAL; - emem->map_locked++; - if (snd_emu10k1_memblk_map(hw, emem) < 0) { - /* printk(KERN_ERR "emu: cannot map!\n"); */ - return -ENOMEM; - } - mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1; - vp->reg.start += mapped_offset; - vp->reg.end += mapped_offset; - vp->reg.loopstart += mapped_offset; - vp->reg.loopend += mapped_offset; - - /* set channel routing */ - /* A = left(0), B = right(1), C = reverb(c), D = chorus(d) */ - if (hw->audigy) { - temp = FXBUS_MIDI_LEFT | (FXBUS_MIDI_RIGHT << 8) | - (FXBUS_MIDI_REVERB << 16) | (FXBUS_MIDI_CHORUS << 24); - snd_emu10k1_ptr_write(hw, A_FXRT1, ch, temp); - } else { - temp = (FXBUS_MIDI_LEFT << 16) | (FXBUS_MIDI_RIGHT << 20) | - (FXBUS_MIDI_REVERB << 24) | (FXBUS_MIDI_CHORUS << 28); - snd_emu10k1_ptr_write(hw, FXRT, ch, temp); - } - - /* channel to be silent and idle */ - snd_emu10k1_ptr_write(hw, DCYSUSV, ch, 0x0000); - snd_emu10k1_ptr_write(hw, VTFT, ch, 0x0000FFFF); - snd_emu10k1_ptr_write(hw, CVCF, ch, 0x0000FFFF); - snd_emu10k1_ptr_write(hw, PTRX, ch, 0); - snd_emu10k1_ptr_write(hw, CPF, ch, 0); - - /* set pitch offset */ - snd_emu10k1_ptr_write(hw, IP, vp->ch, vp->apitch); - - /* set envelope parameters */ - snd_emu10k1_ptr_write(hw, ENVVAL, ch, vp->reg.parm.moddelay); - snd_emu10k1_ptr_write(hw, ATKHLDM, ch, vp->reg.parm.modatkhld); - snd_emu10k1_ptr_write(hw, DCYSUSM, ch, vp->reg.parm.moddcysus); - snd_emu10k1_ptr_write(hw, ENVVOL, ch, vp->reg.parm.voldelay); - snd_emu10k1_ptr_write(hw, ATKHLDV, ch, vp->reg.parm.volatkhld); - /* decay/sustain parameter for volume envelope is used - for triggerg the voice */ - - /* cutoff and volume */ - temp = (unsigned int)vp->acutoff << 8 | (unsigned char)vp->avol; - snd_emu10k1_ptr_write(hw, IFATN, vp->ch, temp); - - /* modulation envelope heights */ - snd_emu10k1_ptr_write(hw, PEFE, ch, vp->reg.parm.pefe); - - /* lfo1/2 delay */ - snd_emu10k1_ptr_write(hw, LFOVAL1, ch, vp->reg.parm.lfo1delay); - snd_emu10k1_ptr_write(hw, LFOVAL2, ch, vp->reg.parm.lfo2delay); - - /* lfo1 pitch & cutoff shift */ - set_fmmod(hw, vp); - /* lfo1 volume & freq */ - snd_emu10k1_ptr_write(hw, TREMFRQ, vp->ch, vp->reg.parm.tremfrq); - /* lfo2 pitch & freq */ - set_fm2frq2(hw, vp); - - /* reverb and loop start (reverb 8bit, MSB) */ - temp = vp->reg.parm.reverb; - temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - addr = vp->reg.loopstart; - snd_emu10k1_ptr_write(hw, PSST, vp->ch, (temp << 24) | addr); - - /* chorus & loop end (chorus 8bit, MSB) */ - addr = vp->reg.loopend; - temp = vp->reg.parm.chorus; - temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - temp = (temp <<24) | addr; - snd_emu10k1_ptr_write(hw, DSL, ch, temp); - - /* clear filter delay memory */ - snd_emu10k1_ptr_write(hw, Z1, ch, 0); - snd_emu10k1_ptr_write(hw, Z2, ch, 0); - - /* invalidate maps */ - temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK; - snd_emu10k1_ptr_write(hw, MAPA, ch, temp); - snd_emu10k1_ptr_write(hw, MAPB, ch, temp); -#if 0 - /* cache */ - { - unsigned int val, sample; - val = 32; - if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS) - sample = 0x80808080; - else { - sample = 0; - val *= 2; - } - - /* cache */ - snd_emu10k1_ptr_write(hw, CCR, ch, 0x1c << 16); - snd_emu10k1_ptr_write(hw, CDE, ch, sample); - snd_emu10k1_ptr_write(hw, CDF, ch, sample); - - /* invalidate maps */ - temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK; - snd_emu10k1_ptr_write(hw, MAPA, ch, temp); - snd_emu10k1_ptr_write(hw, MAPB, ch, temp); - - /* fill cache */ - val -= 4; - val <<= 25; - val |= 0x1c << 16; - snd_emu10k1_ptr_write(hw, CCR, ch, val); - } -#endif - - /* Q & current address (Q 4bit value, MSB) */ - addr = vp->reg.start; - temp = vp->reg.parm.filterQ; - temp = (temp<<28) | addr; - if (vp->apitch < 0xe400) - temp |= CCCA_INTERPROM_0; - else { - unsigned int shift = (vp->apitch - 0xe000) >> 10; - temp |= shift << 25; - } - if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS) - temp |= CCCA_8BITSELECT; - snd_emu10k1_ptr_write(hw, CCCA, ch, temp); - - /* reset volume */ - temp = (unsigned int)vp->vtarget << 16; - snd_emu10k1_ptr_write(hw, VTFT, ch, temp | vp->ftarget); - snd_emu10k1_ptr_write(hw, CVCF, ch, temp | 0xff00); - return 0; -} - -/* - * Start envelope - */ -static void -trigger_voice(struct snd_emux_voice *vp) -{ - unsigned int temp, ptarget; - struct snd_emu10k1 *hw; - struct snd_emu10k1_memblk *emem; - - hw = vp->hw; - - emem = (struct snd_emu10k1_memblk *)vp->block; - if (! emem || emem->mapped_page < 0) - return; /* not mapped */ - -#if 0 - ptarget = (unsigned int)vp->ptarget << 16; -#else - ptarget = IP_TO_CP(vp->apitch); -#endif - /* set pitch target and pan (volume) */ - temp = ptarget | (vp->apan << 8) | vp->aaux; - snd_emu10k1_ptr_write(hw, PTRX, vp->ch, temp); - - /* pitch target */ - snd_emu10k1_ptr_write(hw, CPF, vp->ch, ptarget); - - /* trigger voice */ - snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, vp->reg.parm.voldcysus|DCYSUSV_CHANNELENABLE_MASK); -} - -#define MOD_SENSE 18 - -/* set lfo1 modulation height and cutoff */ -static void -set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) -{ - unsigned short fmmod; - short pitch; - unsigned char cutoff; - int modulation; - - pitch = (char)(vp->reg.parm.fmmod>>8); - cutoff = (vp->reg.parm.fmmod & 0xff); - modulation = vp->chan->gm_modulation + vp->chan->midi_pressure; - pitch += (MOD_SENSE * modulation) / 1200; - LIMITVALUE(pitch, -128, 127); - fmmod = ((unsigned char)pitch<<8) | cutoff; - snd_emu10k1_ptr_write(hw, FMMOD, vp->ch, fmmod); -} - -/* set lfo2 pitch & frequency */ -static void -set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) -{ - unsigned short fm2frq2; - short pitch; - unsigned char freq; - int modulation; - - pitch = (char)(vp->reg.parm.fm2frq2>>8); - freq = vp->reg.parm.fm2frq2 & 0xff; - modulation = vp->chan->gm_modulation + vp->chan->midi_pressure; - pitch += (MOD_SENSE * modulation) / 1200; - LIMITVALUE(pitch, -128, 127); - fm2frq2 = ((unsigned char)pitch<<8) | freq; - snd_emu10k1_ptr_write(hw, FM2FRQ2, vp->ch, fm2frq2); -} - -/* set filterQ */ -static void -set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp) -{ - unsigned int val; - val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE; - val |= (vp->reg.parm.filterQ << 28); - snd_emu10k1_ptr_write(hw, CCCA, vp->ch, val); -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c deleted file mode 100644 index 75492408..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c +++ /dev/null @@ -1,2101 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips - * - * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> - * Added support for Audigy 2 Value. - * Added EMU 1010 support. - * General bug fixes and enhancements. - * - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/sched.h> -#include <linux/kthread.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/mutex.h> - - -#include <sound/core.h> -#include <sound/emu10k1.h> -#include <linux/firmware.h> -#include "p16v.h" -#include "tina2.h" -#include "p17v.h" - - -#define HANA_FILENAME "emu/hana.fw" -#define DOCK_FILENAME "emu/audio_dock.fw" -#define EMU1010B_FILENAME "emu/emu1010b.fw" -#define MICRO_DOCK_FILENAME "emu/micro_dock.fw" -#define EMU0404_FILENAME "emu/emu0404.fw" -#define EMU1010_NOTEBOOK_FILENAME "emu/emu1010_notebook.fw" - -MODULE_FIRMWARE(HANA_FILENAME); -MODULE_FIRMWARE(DOCK_FILENAME); -MODULE_FIRMWARE(EMU1010B_FILENAME); -MODULE_FIRMWARE(MICRO_DOCK_FILENAME); -MODULE_FIRMWARE(EMU0404_FILENAME); -MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME); - - -/************************************************************************* - * EMU10K1 init / done - *************************************************************************/ - -void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch) -{ - snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0); - snd_emu10k1_ptr_write(emu, IP, ch, 0); - snd_emu10k1_ptr_write(emu, VTFT, ch, 0xffff); - snd_emu10k1_ptr_write(emu, CVCF, ch, 0xffff); - snd_emu10k1_ptr_write(emu, PTRX, ch, 0); - snd_emu10k1_ptr_write(emu, CPF, ch, 0); - snd_emu10k1_ptr_write(emu, CCR, ch, 0); - - snd_emu10k1_ptr_write(emu, PSST, ch, 0); - snd_emu10k1_ptr_write(emu, DSL, ch, 0x10); - snd_emu10k1_ptr_write(emu, CCCA, ch, 0); - snd_emu10k1_ptr_write(emu, Z1, ch, 0); - snd_emu10k1_ptr_write(emu, Z2, ch, 0); - snd_emu10k1_ptr_write(emu, FXRT, ch, 0x32100000); - - snd_emu10k1_ptr_write(emu, ATKHLDM, ch, 0); - snd_emu10k1_ptr_write(emu, DCYSUSM, ch, 0); - snd_emu10k1_ptr_write(emu, IFATN, ch, 0xffff); - snd_emu10k1_ptr_write(emu, PEFE, ch, 0); - snd_emu10k1_ptr_write(emu, FMMOD, ch, 0); - snd_emu10k1_ptr_write(emu, TREMFRQ, ch, 24); /* 1 Hz */ - snd_emu10k1_ptr_write(emu, FM2FRQ2, ch, 24); /* 1 Hz */ - snd_emu10k1_ptr_write(emu, TEMPENV, ch, 0); - - /*** these are last so OFF prevents writing ***/ - snd_emu10k1_ptr_write(emu, LFOVAL2, ch, 0); - snd_emu10k1_ptr_write(emu, LFOVAL1, ch, 0); - snd_emu10k1_ptr_write(emu, ATKHLDV, ch, 0); - snd_emu10k1_ptr_write(emu, ENVVOL, ch, 0); - snd_emu10k1_ptr_write(emu, ENVVAL, ch, 0); - - /* Audigy extra stuffs */ - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, 0x4c, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, 0x4d, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, 0x4e, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, 0x4f, ch, 0); /* ?? */ - snd_emu10k1_ptr_write(emu, A_FXRT1, ch, 0x03020100); - snd_emu10k1_ptr_write(emu, A_FXRT2, ch, 0x3f3f3f3f); - snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, ch, 0); - } -} - -static unsigned int spi_dac_init[] = { - 0x00ff, - 0x02ff, - 0x0400, - 0x0520, - 0x0600, - 0x08ff, - 0x0aff, - 0x0cff, - 0x0eff, - 0x10ff, - 0x1200, - 0x1400, - 0x1480, - 0x1800, - 0x1aff, - 0x1cff, - 0x1e00, - 0x0530, - 0x0602, - 0x0622, - 0x1400, -}; - -static unsigned int i2c_adc_init[][2] = { - { 0x17, 0x00 }, /* Reset */ - { 0x07, 0x00 }, /* Timeout */ - { 0x0b, 0x22 }, /* Interface control */ - { 0x0c, 0x22 }, /* Master mode control */ - { 0x0d, 0x08 }, /* Powerdown control */ - { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */ - { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */ - { 0x10, 0x7b }, /* ALC Control 1 */ - { 0x11, 0x00 }, /* ALC Control 2 */ - { 0x12, 0x32 }, /* ALC Control 3 */ - { 0x13, 0x00 }, /* Noise gate control */ - { 0x14, 0xa6 }, /* Limiter control */ - { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */ -}; - -static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) -{ - unsigned int silent_page; - int ch; - u32 tmp; - - /* disable audio and lock cache */ - outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | - HCFG_MUTEBUTTONENABLE, emu->port + HCFG); - - /* reset recording buffers */ - snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, MICBA, 0, 0); - snd_emu10k1_ptr_write(emu, FXBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, FXBA, 0, 0); - snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, ADCBA, 0, 0); - - /* disable channel interrupt */ - outl(0, emu->port + INTE); - snd_emu10k1_ptr_write(emu, CLIEL, 0, 0); - snd_emu10k1_ptr_write(emu, CLIEH, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); - - if (emu->audigy) { - /* set SPDIF bypass mode */ - snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT); - /* enable rear left + rear right AC97 slots */ - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_REAR_RIGHT | - AC97SLOT_REAR_LEFT); - } - - /* init envelope engine */ - for (ch = 0; ch < NUM_G; ch++) - snd_emu10k1_voice_init(emu, ch); - - snd_emu10k1_ptr_write(emu, SPCS0, 0, emu->spdif_bits[0]); - snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]); - snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]); - - if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ - /* Hacks for Alice3 to work independent of haP16V driver */ - /* Setup SRCMulti_I2S SamplingRate */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp &= 0xfffff1ff; - tmp |= (0x2<<9); - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - - /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ - snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); - /* Setup SRCMulti Input Audio Enable */ - /* Use 0xFFFFFFFF to enable P16V sounds. */ - snd_emu10k1_ptr20_write(emu, SRCMULTI_ENABLE, 0, 0xFFFFFFFF); - - /* Enabled Phased (8-channel) P16V playback */ - outl(0x0201, emu->port + HCFG2); - /* Set playback routing. */ - snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); - } - if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ - /* Hacks for Alice3 to work independent of haP16V driver */ - snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); - /* Setup SRCMulti_I2S SamplingRate */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp &= 0xfffff1ff; - tmp |= (0x2<<9); - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - - /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ - outl(0x600000, emu->port + 0x20); - outl(0x14, emu->port + 0x24); - - /* Setup SRCMulti Input Audio Enable */ - outl(0x7b0000, emu->port + 0x20); - outl(0xFF000000, emu->port + 0x24); - - /* Setup SPDIF Out Audio Enable */ - /* The Audigy 2 Value has a separate SPDIF out, - * so no need for a mixer switch - */ - outl(0x7a0000, emu->port + 0x20); - outl(0xFF000000, emu->port + 0x24); - tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */ - outl(tmp, emu->port + A_IOCFG); - } - if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */ - int size, n; - - size = ARRAY_SIZE(spi_dac_init); - for (n = 0; n < size; n++) - snd_emu10k1_spi_write(emu, spi_dac_init[n]); - - snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10); - /* Enable GPIOs - * GPIO0: Unknown - * GPIO1: Speakers-enabled. - * GPIO2: Unknown - * GPIO3: Unknown - * GPIO4: IEC958 Output on. - * GPIO5: Unknown - * GPIO6: Unknown - * GPIO7: Unknown - */ - outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ - } - if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */ - int size, n; - - snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f); - tmp = inl(emu->port + A_IOCFG); - outl(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */ - tmp = inl(emu->port + A_IOCFG); - size = ARRAY_SIZE(i2c_adc_init); - for (n = 0; n < size; n++) - snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); - for (n = 0; n < 4; n++) { - emu->i2c_capture_volume[n][0] = 0xcf; - emu->i2c_capture_volume[n][1] = 0xcf; - } - } - - - snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr); - snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ - snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ - - silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK; - for (ch = 0; ch < NUM_G; ch++) { - snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page); - snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); - } - - if (emu->card_capabilities->emu_model) { - outl(HCFG_AUTOMUTE_ASYNC | - HCFG_EMU32_SLAVE | - HCFG_AUDIOENABLE, emu->port + HCFG); - /* - * Hokay, setup HCFG - * Mute Disable Audio = 0 - * Lock Tank Memory = 1 - * Lock Sound Memory = 0 - * Auto Mute = 1 - */ - } else if (emu->audigy) { - if (emu->revision == 4) /* audigy2 */ - outl(HCFG_AUDIOENABLE | - HCFG_AC3ENABLE_CDSPDIF | - HCFG_AC3ENABLE_GPSPDIF | - HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); - else - outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); - /* FIXME: Remove all these emu->model and replace it with a card recognition parameter, - * e.g. card_capabilities->joystick */ - } else if (emu->model == 0x20 || - emu->model == 0xc400 || - (emu->model == 0x21 && emu->revision < 6)) - outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG); - else - /* With on-chip joystick */ - outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); - - if (enable_ir) { /* enable IR for SB Live */ - if (emu->card_capabilities->emu_model) { - ; /* Disable all access to A_IOCFG for the emu1010 */ - } else if (emu->card_capabilities->i2c_adc) { - ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { - unsigned int reg = inl(emu->port + A_IOCFG); - outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); - udelay(500); - outl(reg | A_IOCFG_GPOUT1 | A_IOCFG_GPOUT2, emu->port + A_IOCFG); - udelay(100); - outl(reg, emu->port + A_IOCFG); - } else { - unsigned int reg = inl(emu->port + HCFG); - outl(reg | HCFG_GPOUT2, emu->port + HCFG); - udelay(500); - outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG); - udelay(100); - outl(reg, emu->port + HCFG); - } - } - - if (emu->card_capabilities->emu_model) { - ; /* Disable all access to A_IOCFG for the emu1010 */ - } else if (emu->card_capabilities->i2c_adc) { - ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { /* enable analog output */ - unsigned int reg = inl(emu->port + A_IOCFG); - outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); - } - - return 0; -} - -static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) -{ - /* - * Enable the audio bit - */ - outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG); - - /* Enable analog/digital outs on audigy */ - if (emu->card_capabilities->emu_model) { - ; /* Disable all access to A_IOCFG for the emu1010 */ - } else if (emu->card_capabilities->i2c_adc) { - ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { - outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); - - if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ - /* Unmute Analog now. Set GPO6 to 1 for Apollo. - * This has to be done after init ALice3 I2SOut beyond 48KHz. - * So, sequence is important. */ - outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); - } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */ - /* Unmute Analog now. */ - outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); - } else { - /* Disable routing from AC97 line out to Front speakers */ - outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); - } - } - -#if 0 - { - unsigned int tmp; - /* FIXME: the following routine disables LiveDrive-II !! */ - /* TOSLink detection */ - emu->tos_link = 0; - tmp = inl(emu->port + HCFG); - if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) { - outl(tmp|0x800, emu->port + HCFG); - udelay(50); - if (tmp != (inl(emu->port + HCFG) & ~0x800)) { - emu->tos_link = 1; - outl(tmp, emu->port + HCFG); - } - } - } -#endif - - snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE); -} - -int snd_emu10k1_done(struct snd_emu10k1 *emu) -{ - int ch; - - outl(0, emu->port + INTE); - - /* - * Shutdown the chip - */ - for (ch = 0; ch < NUM_G; ch++) - snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0); - for (ch = 0; ch < NUM_G; ch++) { - snd_emu10k1_ptr_write(emu, VTFT, ch, 0); - snd_emu10k1_ptr_write(emu, CVCF, ch, 0); - snd_emu10k1_ptr_write(emu, PTRX, ch, 0); - snd_emu10k1_ptr_write(emu, CPF, ch, 0); - } - - /* reset recording buffers */ - snd_emu10k1_ptr_write(emu, MICBS, 0, 0); - snd_emu10k1_ptr_write(emu, MICBA, 0, 0); - snd_emu10k1_ptr_write(emu, FXBS, 0, 0); - snd_emu10k1_ptr_write(emu, FXBA, 0, 0); - snd_emu10k1_ptr_write(emu, FXWC, 0, 0); - snd_emu10k1_ptr_write(emu, ADCBS, 0, ADCBS_BUFSIZE_NONE); - snd_emu10k1_ptr_write(emu, ADCBA, 0, 0); - snd_emu10k1_ptr_write(emu, TCBS, 0, TCBS_BUFFSIZE_16K); - snd_emu10k1_ptr_write(emu, TCB, 0, 0); - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, EMU10K1_DBG_SINGLE_STEP); - - /* disable channel interrupt */ - snd_emu10k1_ptr_write(emu, CLIEL, 0, 0); - snd_emu10k1_ptr_write(emu, CLIEH, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); - snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); - - /* disable audio and lock cache */ - outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG); - snd_emu10k1_ptr_write(emu, PTB, 0, 0); - - return 0; -} - -/************************************************************************* - * ECARD functional implementation - *************************************************************************/ - -/* In A1 Silicon, these bits are in the HC register */ -#define HOOKN_BIT (1L << 12) -#define HANDN_BIT (1L << 11) -#define PULSEN_BIT (1L << 10) - -#define EC_GDI1 (1 << 13) -#define EC_GDI0 (1 << 14) - -#define EC_NUM_CONTROL_BITS 20 - -#define EC_AC3_DATA_SELN 0x0001L -#define EC_EE_DATA_SEL 0x0002L -#define EC_EE_CNTRL_SELN 0x0004L -#define EC_EECLK 0x0008L -#define EC_EECS 0x0010L -#define EC_EESDO 0x0020L -#define EC_TRIM_CSN 0x0040L -#define EC_TRIM_SCLK 0x0080L -#define EC_TRIM_SDATA 0x0100L -#define EC_TRIM_MUTEN 0x0200L -#define EC_ADCCAL 0x0400L -#define EC_ADCRSTN 0x0800L -#define EC_DACCAL 0x1000L -#define EC_DACMUTEN 0x2000L -#define EC_LEDN 0x4000L - -#define EC_SPDIF0_SEL_SHIFT 15 -#define EC_SPDIF1_SEL_SHIFT 17 -#define EC_SPDIF0_SEL_MASK (0x3L << EC_SPDIF0_SEL_SHIFT) -#define EC_SPDIF1_SEL_MASK (0x7L << EC_SPDIF1_SEL_SHIFT) -#define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK) -#define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK) -#define EC_CURRENT_PROM_VERSION 0x01 /* Self-explanatory. This should - * be incremented any time the EEPROM's - * format is changed. */ - -#define EC_EEPROM_SIZE 0x40 /* ECARD EEPROM has 64 16-bit words */ - -/* Addresses for special values stored in to EEPROM */ -#define EC_PROM_VERSION_ADDR 0x20 /* Address of the current prom version */ -#define EC_BOARDREV0_ADDR 0x21 /* LSW of board rev */ -#define EC_BOARDREV1_ADDR 0x22 /* MSW of board rev */ - -#define EC_LAST_PROMFILE_ADDR 0x2f - -#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The - * can be up to 30 characters in length - * and is stored as a NULL-terminated - * ASCII string. Any unused bytes must be - * filled with zeros */ -#define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */ - - -/* Most of this stuff is pretty self-evident. According to the hardware - * dudes, we need to leave the ADCCAL bit low in order to avoid a DC - * offset problem. Weird. - */ -#define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \ - EC_TRIM_CSN) - - -#define EC_DEFAULT_ADC_GAIN 0xC4C4 -#define EC_DEFAULT_SPDIF0_SEL 0x0 -#define EC_DEFAULT_SPDIF1_SEL 0x4 - -/************************************************************************** - * @func Clock bits into the Ecard's control latch. The Ecard uses a - * control latch will is loaded bit-serially by toggling the Modem control - * lines from function 2 on the E8010. This function hides these details - * and presents the illusion that we are actually writing to a distinct - * register. - */ - -static void snd_emu10k1_ecard_write(struct snd_emu10k1 *emu, unsigned int value) -{ - unsigned short count; - unsigned int data; - unsigned long hc_port; - unsigned int hc_value; - - hc_port = emu->port + HCFG; - hc_value = inl(hc_port) & ~(HOOKN_BIT | HANDN_BIT | PULSEN_BIT); - outl(hc_value, hc_port); - - for (count = 0; count < EC_NUM_CONTROL_BITS; count++) { - - /* Set up the value */ - data = ((value & 0x1) ? PULSEN_BIT : 0); - value >>= 1; - - outl(hc_value | data, hc_port); - - /* Clock the shift register */ - outl(hc_value | data | HANDN_BIT, hc_port); - outl(hc_value | data, hc_port); - } - - /* Latch the bits */ - outl(hc_value | HOOKN_BIT, hc_port); - outl(hc_value, hc_port); -} - -/************************************************************************** - * @func Set the gain of the ECARD's CS3310 Trim/gain controller. The - * trim value consists of a 16bit value which is composed of two - * 8 bit gain/trim values, one for the left channel and one for the - * right channel. The following table maps from the Gain/Attenuation - * value in decibels into the corresponding bit pattern for a single - * channel. - */ - -static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu, - unsigned short gain) -{ - unsigned int bit; - - /* Enable writing to the TRIM registers */ - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl & ~EC_TRIM_CSN); - - /* Do it again to insure that we meet hold time requirements */ - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl & ~EC_TRIM_CSN); - - for (bit = (1 << 15); bit; bit >>= 1) { - unsigned int value; - - value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA); - - if (gain & bit) - value |= EC_TRIM_SDATA; - - /* Clock the bit */ - snd_emu10k1_ecard_write(emu, value); - snd_emu10k1_ecard_write(emu, value | EC_TRIM_SCLK); - snd_emu10k1_ecard_write(emu, value); - } - - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl); -} - -static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu) -{ - unsigned int hc_value; - - /* Set up the initial settings */ - emu->ecard_ctrl = EC_RAW_RUN_MODE | - EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) | - EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL); - - /* Step 0: Set the codec type in the hardware control register - * and enable audio output */ - hc_value = inl(emu->port + HCFG); - outl(hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S, emu->port + HCFG); - inl(emu->port + HCFG); - - /* Step 1: Turn off the led and deassert TRIM_CS */ - snd_emu10k1_ecard_write(emu, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN); - - /* Step 2: Calibrate the ADC and DAC */ - snd_emu10k1_ecard_write(emu, EC_DACCAL | EC_LEDN | EC_TRIM_CSN); - - /* Step 3: Wait for awhile; XXX We can't get away with this - * under a real operating system; we'll need to block and wait that - * way. */ - snd_emu10k1_wait(emu, 48000); - - /* Step 4: Switch off the DAC and ADC calibration. Note - * That ADC_CAL is actually an inverted signal, so we assert - * it here to stop calibration. */ - snd_emu10k1_ecard_write(emu, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN); - - /* Step 4: Switch into run mode */ - snd_emu10k1_ecard_write(emu, emu->ecard_ctrl); - - /* Step 5: Set the analog input gain */ - snd_emu10k1_ecard_setadcgain(emu, EC_DEFAULT_ADC_GAIN); - - return 0; -} - -static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) -{ - unsigned long special_port; - unsigned int value; - - /* Special initialisation routine - * before the rest of the IO-Ports become active. - */ - special_port = emu->port + 0x38; - value = inl(special_port); - outl(0x00d00000, special_port); - value = inl(special_port); - outl(0x00d00001, special_port); - value = inl(special_port); - outl(0x00d0005f, special_port); - value = inl(special_port); - outl(0x00d0007f, special_port); - value = inl(special_port); - outl(0x0090007f, special_port); - value = inl(special_port); - - snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */ - /* Delay to give time for ADC chip to switch on. It needs 113ms */ - msleep(200); - return 0; -} - -static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename) -{ - int err; - int n, i; - int reg; - int value; - unsigned int write_post; - unsigned long flags; - const struct firmware *fw_entry; - - err = request_firmware(&fw_entry, filename, &emu->pci->dev); - if (err != 0) { - snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err); - return err; - } - snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size); - - /* The FPGA is a Xilinx Spartan IIE XC2S50E */ - /* GPIO7 -> FPGA PGMN - * GPIO6 -> FPGA CCLK - * GPIO5 -> FPGA DIN - * FPGA CONFIG OFF -> FPGA PGMN - */ - spin_lock_irqsave(&emu->emu_lock, flags); - outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */ - write_post = inl(emu->port + A_IOCFG); - udelay(100); - outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ - write_post = inl(emu->port + A_IOCFG); - udelay(100); /* Allow FPGA memory to clean */ - for (n = 0; n < fw_entry->size; n++) { - value = fw_entry->data[n]; - for (i = 0; i < 8; i++) { - reg = 0x80; - if (value & 0x1) - reg = reg | 0x20; - value = value >> 1; - outl(reg, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); - outl(reg | 0x40, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); - } - } - /* After programming, set GPIO bit 4 high again. */ - outl(0x10, emu->port + A_IOCFG); - write_post = inl(emu->port + A_IOCFG); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - release_firmware(fw_entry); - return 0; -} - -static int emu1010_firmware_thread(void *data) -{ - struct snd_emu10k1 *emu = data; - u32 tmp, tmp2, reg; - int err; - - for (;;) { - /* Delay to allow Audio Dock to settle */ - msleep_interruptible(1000); - if (kthread_should_stop()) - break; - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ - if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { - /* Audio Dock attached */ - /* Return to Audio Dock programming mode */ - snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); - if (emu->card_capabilities->emu_model == - EMU_MODEL_EMU1010) { - err = snd_emu1010_load_firmware(emu, DOCK_FILENAME); - if (err != 0) - continue; - } else if (emu->card_capabilities->emu_model == - EMU_MODEL_EMU1010B) { - err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); - if (err != 0) - continue; - } else if (emu->card_capabilities->emu_model == - EMU_MODEL_EMU1616) { - err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); - if (err != 0) - continue; - } - - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); - snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", reg); - /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg); - if ((reg & 0x1f) != 0x15) { - /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", reg); - continue; - } - snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); - snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); - snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); - snd_printk(KERN_INFO "Audio Dock ver: %u.%u\n", - tmp, tmp2); - /* Sync clocking between 1010 and Dock */ - /* Allow DLL to settle */ - msleep(10); - /* Unmute all. Default is muted after a firmware load */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); - } - } - snd_printk(KERN_INFO "emu1010: firmware thread stopping\n"); - return 0; -} - -/* - * EMU-1010 - details found out from this driver, official MS Win drivers, - * testing the card: - * - * Audigy2 (aka Alice2): - * --------------------- - * * communication over PCI - * * conversion of 32-bit data coming over EMU32 links from HANA FPGA - * to 2 x 16-bit, using internal DSP instructions - * * slave mode, clock supplied by HANA - * * linked to HANA using: - * 32 x 32-bit serial EMU32 output channels - * 16 x EMU32 input channels - * (?) x I2S I/O channels (?) - * - * FPGA (aka HANA): - * --------------- - * * provides all (?) physical inputs and outputs of the card - * (ADC, DAC, SPDIF I/O, ADAT I/O, etc.) - * * provides clock signal for the card and Alice2 - * * two crystals - for 44.1kHz and 48kHz multiples - * * provides internal routing of signal sources to signal destinations - * * inputs/outputs to Alice2 - see above - * - * Current status of the driver: - * ---------------------------- - * * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz) - * * PCM device nb. 2: - * 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops - * 16 x 32-bit capture - snd_emu10k1_capture_efx_ops - */ -static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) -{ - unsigned int i; - u32 tmp, tmp2, reg; - int err; - const char *filename = NULL; - - snd_printk(KERN_INFO "emu1010: Special config.\n"); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0005a00c, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0005a004, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Mute all codecs. - */ - outl(0x0005a000, emu->port + HCFG); - /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, - * Mute all codecs. - */ - outl(0x0005a000, emu->port + HCFG); - - /* Disable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); - - /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printdd("reg1 = 0x%x\n", reg); - if ((reg & 0x3f) == 0x15) { - /* FPGA netlist already present so clear it */ - /* Return to programming mode */ - - snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02); - } - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - snd_printdd("reg2 = 0x%x\n", reg); - if ((reg & 0x3f) == 0x15) { - /* FPGA failed to return to programming mode */ - snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n"); - return -ENODEV; - } - snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg); - switch (emu->card_capabilities->emu_model) { - case EMU_MODEL_EMU1010: - filename = HANA_FILENAME; - break; - case EMU_MODEL_EMU1010B: - filename = EMU1010B_FILENAME; - break; - case EMU_MODEL_EMU1616: - filename = EMU1010_NOTEBOOK_FILENAME; - break; - case EMU_MODEL_EMU0404: - filename = EMU0404_FILENAME; - break; - default: - filename = NULL; - return -ENODEV; - break; - } - snd_printk(KERN_INFO "emu1010: filename %s testing\n", filename); - err = snd_emu1010_load_firmware(emu, filename); - if (err != 0) { - snd_printk( - KERN_INFO "emu1010: Loading Firmware file %s failed\n", - filename); - return err; - } - - /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ - snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); - if ((reg & 0x3f) != 0x15) { - /* FPGA failed to be programmed */ - snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); - return -ENODEV; - } - - snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); - snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); - snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); - snd_printk(KERN_INFO "emu1010: Hana version: %u.%u\n", tmp, tmp2); - /* Enable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); - snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp); - /* Optical -> ADAT I/O */ - /* 0 : SPDIF - * 1 : ADAT - */ - emu->emu1010.optical_in = 1; /* IN_ADAT */ - emu->emu1010.optical_out = 1; /* IN_ADAT */ - tmp = 0; - tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | - (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); - snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); - snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp); - /* Set no attenuation on Audio Dock pads. */ - snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00); - emu->emu1010.adc_pads = 0x00; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); - /* Unmute Audio dock DACs, Headphone source DAC-4. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); - snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp); - /* DAC PADs. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f); - emu->emu1010.dac_pads = 0x0f; - snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); - /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ - snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); - /* MIDI routing */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); - /* Unknown. */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); - /* IRQ Enable: All on */ - /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */ - /* IRQ Enable: All off */ - snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); - snd_printk(KERN_INFO "emu1010: Card options3 = 0x%x\n", reg); - /* Default WCLK set to 48kHz. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); - /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); - /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ - /* Audio Dock LEDs. */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); - -#if 0 - /* For 96kHz */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT2); -#endif -#if 0 - /* For 192kHz */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_RIGHT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT3); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT3); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_6, EMU_SRC_HAMOA_ADC_LEFT4); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_7, EMU_SRC_HAMOA_ADC_RIGHT4); -#endif -#if 1 - /* For 48kHz */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_0, EMU_SRC_DOCK_MIC_A1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_1, EMU_SRC_DOCK_MIC_B1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_DOCK_ADC1_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_DOCK_ADC1_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1); - /* Pavel Hofman - setting defaults for 8 more capture channels - * Defaults only, users will set their own values anyways, let's - * just copy/paste. - */ - - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_9, EMU_SRC_DOCK_MIC_B1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_A, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_B, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_ADC1_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_ADC1_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_E, EMU_SRC_DOCK_ADC2_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_F, EMU_SRC_DOCK_ADC2_RIGHT1); -#endif -#if 0 - /* Original */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_4, EMU_SRC_HANA_ADAT); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_5, EMU_SRC_HANA_ADAT + 1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_6, EMU_SRC_HANA_ADAT + 2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_7, EMU_SRC_HANA_ADAT + 3); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_8, EMU_SRC_HANA_ADAT + 4); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_9, EMU_SRC_HANA_ADAT + 5); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_A, EMU_SRC_HANA_ADAT + 6); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_B, EMU_SRC_HANA_ADAT + 7); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_MIC_A1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_MIC_B1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_E, EMU_SRC_HAMOA_ADC_LEFT2); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2); -#endif - for (i = 0; i < 0x20; i++) { - /* AudioDock Elink <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0100 + i, EMU_SRC_SILENCE); - } - for (i = 0; i < 4; i++) { - /* Hana SPDIF Out <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0200 + i, EMU_SRC_SILENCE); - } - for (i = 0; i < 7; i++) { - /* Hamoa DAC <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, 0x0300 + i, EMU_SRC_SILENCE); - } - for (i = 0; i < 7; i++) { - /* Hana ADAT Out <- Silence */ - snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE); - } - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S0_LEFT, EMU_SRC_DOCK_ADC1_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S0_RIGHT, EMU_SRC_DOCK_ADC1_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S1_LEFT, EMU_SRC_DOCK_ADC2_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S1_RIGHT, EMU_SRC_DOCK_ADC2_RIGHT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1); - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */ - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); - - /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Mute all codecs. - */ - outl(0x0000a000, emu->port + HCFG); - /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, - * Lock Sound Memory Cache, Lock Tank Memory Cache, - * Un-Mute all codecs. - */ - outl(0x0000a001, emu->port + HCFG); - - /* Initial boot complete. Now patches */ - - snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ - snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ - snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); - snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ - - /* Start Micro/Audio Dock firmware loader thread */ - if (!emu->emu1010.firmware_thread) { - emu->emu1010.firmware_thread = - kthread_create(emu1010_firmware_thread, emu, - "emu1010_firmware"); - wake_up_process(emu->emu1010.firmware_thread); - } - -#if 0 - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32B + 3); /* ALICE2 bus 0xa3 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 2); /* ALICE2 bus 0xb2 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); /* ALICE2 bus 0xb3 */ -#endif - /* Default outputs */ - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { - /* 1616(M) cardbus default outputs */ - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[0] = 17; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[1] = 18; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[2] = 19; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[3] = 20; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[4] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[5] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_MANA_DAC_LEFT, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[16] = 17; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_MANA_DAC_RIGHT, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[17] = 18; - } else { - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[0] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[1] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[2] = 23; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[3] = 24; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[4] = 25; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[5] = 26; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC4_LEFT1, EMU_SRC_ALICE_EMU32A + 6); - emu->emu1010.output_source[6] = 27; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_DAC4_RIGHT1, EMU_SRC_ALICE_EMU32A + 7); - emu->emu1010.output_source[7] = 28; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[8] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_PHONES_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[9] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[10] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_DOCK_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[11] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[12] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[13] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[14] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[15] = 22; - /* ALICE2 bus 0xa0 */ - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0); - emu->emu1010.output_source[16] = 21; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 1, EMU_SRC_ALICE_EMU32A + 1); - emu->emu1010.output_source[17] = 22; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 2, EMU_SRC_ALICE_EMU32A + 2); - emu->emu1010.output_source[18] = 23; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 3, EMU_SRC_ALICE_EMU32A + 3); - emu->emu1010.output_source[19] = 24; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 4, EMU_SRC_ALICE_EMU32A + 4); - emu->emu1010.output_source[20] = 25; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 5, EMU_SRC_ALICE_EMU32A + 5); - emu->emu1010.output_source[21] = 26; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 6, EMU_SRC_ALICE_EMU32A + 6); - emu->emu1010.output_source[22] = 27; - snd_emu1010_fpga_link_dst_src_write(emu, - EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7); - emu->emu1010.output_source[23] = 28; - } - /* TEMP: Select SPDIF in/out */ - /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */ - - /* TEMP: Select 48kHz SPDIF out */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */ - /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); - /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ - emu->emu1010.internal_clock = 1; /* 48000 */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */ - /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */ - /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */ - /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */ - - return 0; -} -/* - * Create the EMU10K1 instance - */ - -#ifdef CONFIG_PM -static int alloc_pm_buffer(struct snd_emu10k1 *emu); -static void free_pm_buffer(struct snd_emu10k1 *emu); -#endif - -static int snd_emu10k1_free(struct snd_emu10k1 *emu) -{ - if (emu->port) { /* avoid access to already used hardware */ - snd_emu10k1_fx8010_tram_setup(emu, 0); - snd_emu10k1_done(emu); - snd_emu10k1_free_efx(emu); - } - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { - /* Disable 48Volt power to Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); - } - if (emu->emu1010.firmware_thread) - kthread_stop(emu->emu1010.firmware_thread); - if (emu->irq >= 0) - free_irq(emu->irq, emu); - /* remove reserved page */ - if (emu->reserved_page) { - snd_emu10k1_synth_free(emu, - (struct snd_util_memblk *)emu->reserved_page); - emu->reserved_page = NULL; - } - if (emu->memhdr) - snd_util_memhdr_free(emu->memhdr); - if (emu->silent_page.area) - snd_dma_free_pages(&emu->silent_page); - if (emu->ptb_pages.area) - snd_dma_free_pages(&emu->ptb_pages); - vfree(emu->page_ptr_table); - vfree(emu->page_addr_table); -#ifdef CONFIG_PM - free_pm_buffer(emu); -#endif - if (emu->port) - pci_release_regions(emu->pci); - if (emu->card_capabilities->ca0151_chip) /* P16V */ - snd_p16v_free(emu); - pci_disable_device(emu->pci); - kfree(emu); - return 0; -} - -static int snd_emu10k1_dev_free(struct snd_device *device) -{ - struct snd_emu10k1 *emu = device->device_data; - return snd_emu10k1_free(emu); -} - -static struct snd_emu_chip_details emu_chip_details[] = { - /* Audigy4 (Not PRO) SB0610 */ - /* Tested by James@superbug.co.uk 4th April 2006 */ - /* A_IOCFG bits - * Output - * 0: ? - * 1: ? - * 2: ? - * 3: 0 - Digital Out, 1 - Line in - * 4: ? - * 5: ? - * 6: ? - * 7: ? - * Input - * 8: ? - * 9: ? - * A: Green jack sense (Front) - * B: ? - * C: Black jack sense (Rear/Side Right) - * D: Yellow jack sense (Center/LFE/Side Left) - * E: ? - * F: ? - * - * Digital Out/Line in switch using A_IOCFG bit 3 (0x08) - * 0 - Digital Out - * 1 - Line in - */ - /* Mic input not tested. - * Analog CD input not tested - * Digital Out not tested. - * Line in working. - * Audio output 5.1 working. Side outputs not working. - */ - /* DSP: CA10300-IAT LF - * DAC: Cirrus Logic CS4382-KQZ - * ADC: Philips 1361T - * AC97: Sigmatel STAC9750 - * CA0151: None - */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, - .driver = "Audigy2", .name = "SB Audigy 4 [SB0610]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .adc_1361t = 1, /* 24 bit capture instead of 16bit */ - .ac97_chip = 1} , - /* Audigy 2 Value AC3 out does not work yet. - * Need to find out how to turn off interpolators. - */ - /* Tested by James@superbug.co.uk 3rd July 2005 */ - /* DSP: CA0108-IAT - * DAC: CS4382-KQ - * ADC: Philips 1361T - * AC97: STAC9750 - * CA0151: None - */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, - .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .ac97_chip = 1} , - /* Audigy 2 ZS Notebook Cardbus card.*/ - /* Tested by James@superbug.co.uk 6th November 2006 */ - /* Audio output 7.1/Headphones working. - * Digital output working. (AC3 not checked, only PCM) - * Audio Mic/Line inputs working. - * Digital input not tested. - */ - /* DSP: Tina2 - * DAC: Wolfson WM8768/WM8568 - * ADC: Wolfson WM8775 - * AC97: None - * CA0151: None - */ - /* Tested by James@superbug.co.uk 4th April 2006 */ - /* A_IOCFG bits - * Output - * 0: Not Used - * 1: 0 = Mute all the 7.1 channel out. 1 = unmute. - * 2: Analog input 0 = line in, 1 = mic in - * 3: Not Used - * 4: Digital output 0 = off, 1 = on. - * 5: Not Used - * 6: Not Used - * 7: Not Used - * Input - * All bits 1 (0x3fxx) means nothing plugged in. - * 8-9: 0 = Line in/Mic, 2 = Optical in, 3 = Nothing. - * A-B: 0 = Headphones, 2 = Optical out, 3 = Nothing. - * C-D: 2 = Front/Rear/etc, 3 = nothing. - * E-F: Always 0 - * - */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .ca_cardbus_chip = 1, - .spi_dac = 1, - .i2c_adc = 1, - .spk71 = 1} , - /* Tested by James@superbug.co.uk 4th Nov 2007. */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, - .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", - .id = "EMU1010", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .ca_cardbus_chip = 1, - .spk71 = 1 , - .emu_model = EMU_MODEL_EMU1616}, - /* Tested by James@superbug.co.uk 4th Nov 2007. */ - /* This is MAEM8960, 0202 is MAEM 8980 */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, - .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]", - .id = "EMU1010", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ - /* Tested by James@superbug.co.uk 8th July 2005. */ - /* This is MAEM8810, 0202 is MAEM8820 */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, - .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]", - .id = "EMU1010", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */ - /* EMU0404b */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, - .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]", - .id = "EMU0404", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ - /* Tested by James@superbug.co.uk 20-3-2007. */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, - .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]", - .id = "EMU0404", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ - /* EMU0404 PCIe */ - {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, - .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", - .id = "EMU0404", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .spk71 = 1, - .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ - /* Note that all E-mu cards require kernel 2.6 or newer. */ - {.vendor = 0x1102, .device = 0x0008, - .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0108_chip = 1, - .ac97_chip = 1} , - /* Tested by James@superbug.co.uk 3rd July 2005 */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, - .driver = "Audigy2", .name = "SB Audigy 4 PRO [SB0380]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - /* Tested by shane-alsa@cm.nu 5th Nov 2005 */ - /* The 0x20061102 does have SB0350 written on it - * Just like 0x20021102 - */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102, - .driver = "Audigy2", .name = "SB Audigy 2 [SB0350b]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - /* 0x20051102 also has SB0350 written on it, treated as Audigy 2 ZS by - Creative's Windows driver */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20051102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350a]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0360]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - /* Audigy 2 */ - /* Tested by James@superbug.co.uk 3rd July 2005 */ - /* DSP: CA0102-IAT - * DAC: CS4382-KQ - * ADC: Philips 1361T - * AC97: STAC9721 - * CA0151: Yes - */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, - .driver = "Audigy2", .name = "SB Audigy 2 [SB0240]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .adc_1361t = 1, /* 24 bit capture instead of 16bit */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, - .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1} , - /* Dell OEM/Creative Labs Audigy 2 ZS */ - /* See ALSA bug#1365 */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102, - .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0353]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, - .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .invert_shared_spdif = 1, /* digital/analog switch swapped */ - .adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */ - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, - .driver = "Audigy2", .name = "SB Audigy 2 [Unknown]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, - .driver = "Audigy", .name = "SB Audigy 1 [SB0092]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102, - .driver = "Audigy", .name = "SB Audigy 1 ES [SB0160]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .spdif_bug = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, - .driver = "Audigy", .name = "SB Audigy 1 [SB0090]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0004, - .driver = "Audigy", .name = "Audigy 1 [Unknown]", - .id = "Audigy", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102, - .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806b1102, - .driver = "EMU10K1", .name = "SB Live! [SB0105]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806a1102, - .driver = "EMU10K1", .name = "SB Live! Value [SB0103]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, - .driver = "EMU10K1", .name = "SB Live! Value [SB0101]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by ALSA bug#1680 26th December 2005 */ - /* note: It really has SB0220 written on the card, */ - /* but it's SB0228 according to kx.inf */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102, - .driver = "EMU10K1", .name = "SB Live! 5.1 Dell OEM [SB0228]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by Thomas Zehetbauer 27th Aug 2005 */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102, - .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, - .driver = "EMU10K1", .name = "SB Live! 5.1", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, - .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0060]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum - * share the same IDs! - */ - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4850]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, - .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4871]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4831]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4870]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - /* Tested by James@superbug.co.uk 3rd July 2005 */ - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4832]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4830]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, - .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4780]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, - .driver = "EMU10K1", .name = "E-mu APS [PC545]", - .id = "APS", - .emu10k1_chip = 1, - .ecard = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, - .driver = "EMU10K1", .name = "SB Live! [CT4620]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, - .driver = "EMU10K1", .name = "SB Live! Value [CT4670]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - {.vendor = 0x1102, .device = 0x0002, - .driver = "EMU10K1", .name = "SB Live! [Unknown]", - .id = "Live", - .emu10k1_chip = 1, - .ac97_chip = 1, - .sblive51 = 1} , - { } /* terminator */ -}; - -int __devinit snd_emu10k1_create(struct snd_card *card, - struct pci_dev *pci, - unsigned short extin_mask, - unsigned short extout_mask, - long max_cache_bytes, - int enable_ir, - uint subsystem, - struct snd_emu10k1 **remu) -{ - struct snd_emu10k1 *emu; - int idx, err; - int is_audigy; - unsigned int silent_page; - const struct snd_emu_chip_details *c; - static struct snd_device_ops ops = { - .dev_free = snd_emu10k1_dev_free, - }; - - *remu = NULL; - - /* enable PCI device */ - err = pci_enable_device(pci); - if (err < 0) - return err; - - emu = kzalloc(sizeof(*emu), GFP_KERNEL); - if (emu == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - emu->card = card; - spin_lock_init(&emu->reg_lock); - spin_lock_init(&emu->emu_lock); - spin_lock_init(&emu->spi_lock); - spin_lock_init(&emu->i2c_lock); - spin_lock_init(&emu->voice_lock); - spin_lock_init(&emu->synth_lock); - spin_lock_init(&emu->memblk_lock); - mutex_init(&emu->fx8010.lock); - INIT_LIST_HEAD(&emu->mapped_link_head); - INIT_LIST_HEAD(&emu->mapped_order_link_head); - emu->pci = pci; - emu->irq = -1; - emu->synth = NULL; - emu->get_synth_voice = NULL; - /* read revision & serial */ - emu->revision = pci->revision; - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); - snd_printdd("vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x\n", pci->vendor, pci->device, emu->serial, emu->model); - - for (c = emu_chip_details; c->vendor; c++) { - if (c->vendor == pci->vendor && c->device == pci->device) { - if (subsystem) { - if (c->subsystem && (c->subsystem == subsystem)) - break; - else - continue; - } else { - if (c->subsystem && (c->subsystem != emu->serial)) - continue; - if (c->revision && c->revision != emu->revision) - continue; - } - break; - } - } - if (c->vendor == 0) { - snd_printk(KERN_ERR "emu10k1: Card not recognised\n"); - kfree(emu); - pci_disable_device(pci); - return -ENOENT; - } - emu->card_capabilities = c; - if (c->subsystem && !subsystem) - snd_printdd("Sound card name = %s\n", c->name); - else if (subsystem) - snd_printdd("Sound card name = %s, " - "vendor = 0x%x, device = 0x%x, subsystem = 0x%x. " - "Forced to subsystem = 0x%x\n", c->name, - pci->vendor, pci->device, emu->serial, c->subsystem); - else - snd_printdd("Sound card name = %s, " - "vendor = 0x%x, device = 0x%x, subsystem = 0x%x.\n", - c->name, pci->vendor, pci->device, - emu->serial); - - if (!*card->id && c->id) { - int i, n = 0; - strlcpy(card->id, c->id, sizeof(card->id)); - for (;;) { - for (i = 0; i < snd_ecards_limit; i++) { - if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id)) - break; - } - if (i >= snd_ecards_limit) - break; - n++; - if (n >= SNDRV_CARDS) - break; - snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n); - } - } - - is_audigy = emu->audigy = c->emu10k2_chip; - - /* set the DMA transfer mask */ - emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK; - if (pci_set_dma_mask(pci, emu->dma_mask) < 0 || - pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) { - snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask); - kfree(emu); - pci_disable_device(pci); - return -ENXIO; - } - if (is_audigy) - emu->gpr_base = A_FXGPREGBASE; - else - emu->gpr_base = FXGPREGBASE; - - err = pci_request_regions(pci, "EMU10K1"); - if (err < 0) { - kfree(emu); - pci_disable_device(pci); - return err; - } - emu->port = pci_resource_start(pci, 0); - - emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT; - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 32 * 1024, &emu->ptb_pages) < 0) { - err = -ENOMEM; - goto error; - } - - emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *)); - emu->page_addr_table = vmalloc(emu->max_cache_pages * - sizeof(unsigned long)); - if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) { - err = -ENOMEM; - goto error; - } - - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - EMUPAGESIZE, &emu->silent_page) < 0) { - err = -ENOMEM; - goto error; - } - emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE); - if (emu->memhdr == NULL) { - err = -ENOMEM; - goto error; - } - emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) - - sizeof(struct snd_util_memblk); - - pci_set_master(pci); - - emu->fx8010.fxbus_mask = 0x303f; - if (extin_mask == 0) - extin_mask = 0x3fcf; - if (extout_mask == 0) - extout_mask = 0x7fff; - emu->fx8010.extin_mask = extin_mask; - emu->fx8010.extout_mask = extout_mask; - emu->enable_ir = enable_ir; - - if (emu->card_capabilities->ca_cardbus_chip) { - err = snd_emu10k1_cardbus_init(emu); - if (err < 0) - goto error; - } - if (emu->card_capabilities->ecard) { - err = snd_emu10k1_ecard_init(emu); - if (err < 0) - goto error; - } else if (emu->card_capabilities->emu_model) { - err = snd_emu10k1_emu1010_init(emu); - if (err < 0) { - snd_emu10k1_free(emu); - return err; - } - } else { - /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version - does not support this, it shouldn't do any harm */ - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, - AC97SLOT_CNTR|AC97SLOT_LFE); - } - - /* initialize TRAM setup */ - emu->fx8010.itram_size = (16 * 1024)/2; - emu->fx8010.etram_pages.area = NULL; - emu->fx8010.etram_pages.bytes = 0; - - /* irq handler must be registered after I/O ports are activated */ - if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_SHARED, - KBUILD_MODNAME, emu)) { - err = -EBUSY; - goto error; - } - emu->irq = pci->irq; - - /* - * Init to 0x02109204 : - * Clock accuracy = 0 (1000ppm) - * Sample Rate = 2 (48kHz) - * Audio Channel = 1 (Left of 2) - * Source Number = 0 (Unspecified) - * Generation Status = 1 (Original for Cat Code 12) - * Cat Code = 12 (Digital Signal Mixer) - * Mode = 0 (Mode 0) - * Emphasis = 0 (None) - * CP = 1 (Copyright unasserted) - * AN = 0 (Audio data) - * P = 0 (Consumer) - */ - emu->spdif_bits[0] = emu->spdif_bits[1] = - emu->spdif_bits[2] = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; - - emu->reserved_page = (struct snd_emu10k1_memblk *) - snd_emu10k1_synth_alloc(emu, 4096); - if (emu->reserved_page) - emu->reserved_page->map_locked = 1; - - /* Clear silent pages and set up pointers */ - memset(emu->silent_page.area, 0, PAGE_SIZE); - silent_page = emu->silent_page.addr << 1; - for (idx = 0; idx < MAXPAGES; idx++) - ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx); - - /* set up voice indices */ - for (idx = 0; idx < NUM_G; idx++) { - emu->voices[idx].emu = emu; - emu->voices[idx].number = idx; - } - - err = snd_emu10k1_init(emu, enable_ir, 0); - if (err < 0) - goto error; -#ifdef CONFIG_PM - err = alloc_pm_buffer(emu); - if (err < 0) - goto error; -#endif - - /* Initialize the effect engine */ - err = snd_emu10k1_init_efx(emu); - if (err < 0) - goto error; - snd_emu10k1_audio_enable(emu); - - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops); - if (err < 0) - goto error; - -#ifdef CONFIG_PROC_FS - snd_emu10k1_proc_init(emu); -#endif - - snd_card_set_dev(card, &pci->dev); - *remu = emu; - return 0; - - error: - snd_emu10k1_free(emu); - return err; -} - -#ifdef CONFIG_PM -static unsigned char saved_regs[] = { - CPF, PTRX, CVCF, VTFT, Z1, Z2, PSST, DSL, CCCA, CCR, CLP, - FXRT, MAPA, MAPB, ENVVOL, ATKHLDV, DCYSUSV, LFOVAL1, ENVVAL, - ATKHLDM, DCYSUSM, LFOVAL2, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2, - TEMPENV, ADCCR, FXWC, MICBA, ADCBA, FXBA, - MICBS, ADCBS, FXBS, CDCS, GPSCS, SPCS0, SPCS1, SPCS2, - SPBYPASS, AC97SLOT, CDSRCS, GPSRCS, ZVSRCS, MICIDX, ADCIDX, FXIDX, - 0xff /* end */ -}; -static unsigned char saved_regs_audigy[] = { - A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE, - A_FXRT2, A_SENDAMOUNTS, A_FXRT1, - 0xff /* end */ -}; - -static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu) -{ - int size; - - size = ARRAY_SIZE(saved_regs); - if (emu->audigy) - size += ARRAY_SIZE(saved_regs_audigy); - emu->saved_ptr = vmalloc(4 * NUM_G * size); - if (!emu->saved_ptr) - return -ENOMEM; - if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0) - return -ENOMEM; - if (emu->card_capabilities->ca0151_chip && - snd_p16v_alloc_pm_buffer(emu) < 0) - return -ENOMEM; - return 0; -} - -static void free_pm_buffer(struct snd_emu10k1 *emu) -{ - vfree(emu->saved_ptr); - snd_emu10k1_efx_free_pm_buffer(emu); - if (emu->card_capabilities->ca0151_chip) - snd_p16v_free_pm_buffer(emu); -} - -void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu) -{ - int i; - unsigned char *reg; - unsigned int *val; - - val = emu->saved_ptr; - for (reg = saved_regs; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - *val = snd_emu10k1_ptr_read(emu, *reg, i); - if (emu->audigy) { - for (reg = saved_regs_audigy; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - *val = snd_emu10k1_ptr_read(emu, *reg, i); - } - if (emu->audigy) - emu->saved_a_iocfg = inl(emu->port + A_IOCFG); - emu->saved_hcfg = inl(emu->port + HCFG); -} - -void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) -{ - if (emu->card_capabilities->ca_cardbus_chip) - snd_emu10k1_cardbus_init(emu); - if (emu->card_capabilities->ecard) - snd_emu10k1_ecard_init(emu); - else if (emu->card_capabilities->emu_model) - snd_emu10k1_emu1010_init(emu); - else - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); - snd_emu10k1_init(emu, emu->enable_ir, 1); -} - -void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) -{ - int i; - unsigned char *reg; - unsigned int *val; - - snd_emu10k1_audio_enable(emu); - - /* resore for spdif */ - if (emu->audigy) - outl(emu->saved_a_iocfg, emu->port + A_IOCFG); - outl(emu->saved_hcfg, emu->port + HCFG); - - val = emu->saved_ptr; - for (reg = saved_regs; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - snd_emu10k1_ptr_write(emu, *reg, i, *val); - if (emu->audigy) { - for (reg = saved_regs_audigy; *reg != 0xff; reg++) - for (i = 0; i < NUM_G; i++, val++) - snd_emu10k1_ptr_write(emu, *reg, i, *val); - } -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c deleted file mode 100644 index e10f027b..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Patch transfer callback for Emu10k1 - * - * Copyright (C) 2000 Takashi iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * All the code for loading in a patch. There is very little that is - * chip specific here. Just the actual writing to the board. - */ - -#include "emu10k1_synth_local.h" - -/* - */ -#define BLANK_LOOP_START 4 -#define BLANK_LOOP_END 8 -#define BLANK_LOOP_SIZE 12 -#define BLANK_HEAD_SIZE 32 - -/* - * allocate a sample block and copy data from userspace - */ -int -snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *data, long count) -{ - int offset; - int truesize, size, loopsize, blocksize; - int loopend, sampleend; - unsigned int start_addr; - struct snd_emu10k1 *emu; - - emu = rec->hw; - if (snd_BUG_ON(!sp || !hdr)) - return -EINVAL; - - if (sp->v.size == 0) { - snd_printd("emu: rom font for sample %d\n", sp->v.sample); - return 0; - } - - /* recalculate address offset */ - sp->v.end -= sp->v.start; - sp->v.loopstart -= sp->v.start; - sp->v.loopend -= sp->v.start; - sp->v.start = 0; - - /* some samples have invalid data. the addresses are corrected in voice info */ - sampleend = sp->v.end; - if (sampleend > sp->v.size) - sampleend = sp->v.size; - loopend = sp->v.loopend; - if (loopend > sampleend) - loopend = sampleend; - - /* be sure loop points start < end */ - if (sp->v.loopstart >= sp->v.loopend) { - int tmp = sp->v.loopstart; - sp->v.loopstart = sp->v.loopend; - sp->v.loopend = tmp; - } - - /* compute true data size to be loaded */ - truesize = sp->v.size + BLANK_HEAD_SIZE; - loopsize = 0; -#if 0 /* not supported */ - if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) - loopsize = sp->v.loopend - sp->v.loopstart; - truesize += loopsize; -#endif - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) - truesize += BLANK_LOOP_SIZE; - - /* try to allocate a memory block */ - blocksize = truesize; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - blocksize *= 2; - sp->block = snd_emu10k1_synth_alloc(emu, blocksize); - if (sp->block == NULL) { - snd_printd("emu10k1: synth malloc failed (size=%d)\n", blocksize); - /* not ENOMEM (for compatibility with OSS) */ - return -ENOSPC; - } - /* set the total size */ - sp->v.truesize = blocksize; - - /* write blank samples at head */ - offset = 0; - size = BLANK_HEAD_SIZE; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - size *= 2; - if (offset + size > blocksize) - return -EINVAL; - snd_emu10k1_synth_bzero(emu, sp->block, offset, size); - offset += size; - - /* copy start->loopend */ - size = loopend; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - size *= 2; - if (offset + size > blocksize) - return -EINVAL; - if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { - snd_emu10k1_synth_free(emu, sp->block); - sp->block = NULL; - return -EFAULT; - } - offset += size; - data += size; - -#if 0 /* not suppported yet */ - /* handle reverse (or bidirectional) loop */ - if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) { - /* copy loop in reverse */ - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) { - int woffset; - unsigned short *wblock = (unsigned short*)block; - woffset = offset / 2; - if (offset + loopsize * 2 > blocksize) - return -EINVAL; - for (i = 0; i < loopsize; i++) - wblock[woffset + i] = wblock[woffset - i -1]; - offset += loopsize * 2; - } else { - if (offset + loopsize > blocksize) - return -EINVAL; - for (i = 0; i < loopsize; i++) - block[offset + i] = block[offset - i -1]; - offset += loopsize; - } - - /* modify loop pointers */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) { - sp->v.loopend += loopsize; - } else { - sp->v.loopstart += loopsize; - sp->v.loopend += loopsize; - } - /* add sample pointer */ - sp->v.end += loopsize; - } -#endif - - /* loopend -> sample end */ - size = sp->v.size - loopend; - if (size < 0) - return -EINVAL; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - size *= 2; - if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) { - snd_emu10k1_synth_free(emu, sp->block); - sp->block = NULL; - return -EFAULT; - } - offset += size; - - /* clear rest of samples (if any) */ - if (offset < blocksize) - snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset); - - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) { - /* if no blank loop is attached in the sample, add it */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) { - sp->v.loopstart = sp->v.end + BLANK_LOOP_START; - sp->v.loopend = sp->v.end + BLANK_LOOP_END; - } - } - -#if 0 /* not supported yet */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) { - /* unsigned -> signed */ - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) { - unsigned short *wblock = (unsigned short*)block; - for (i = 0; i < truesize; i++) - wblock[i] ^= 0x8000; - } else { - for (i = 0; i < truesize; i++) - block[i] ^= 0x80; - } - } -#endif - - /* recalculate offset */ - start_addr = BLANK_HEAD_SIZE * 2; - if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) - start_addr >>= 1; - sp->v.start += start_addr; - sp->v.end += start_addr; - sp->v.loopstart += start_addr; - sp->v.loopend += start_addr; - - return 0; -} - -/* - * free a sample block - */ -int -snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr) -{ - struct snd_emu10k1 *emu; - - emu = rec->hw; - if (snd_BUG_ON(!sp || !hdr)) - return -EINVAL; - - if (sp->block) { - snd_emu10k1_synth_free(emu, sp->block); - sp->block = NULL; - } - return 0; -} - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c deleted file mode 100644 index 4c41c903..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de> - * - * Routines for control of EMU10K1 WaveTable synth - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "emu10k1_synth_local.h" -#include <linux/init.h> -#include <linux/module.h> - -MODULE_AUTHOR("Takashi Iwai"); -MODULE_DESCRIPTION("Routines for control of EMU10K1 WaveTable synth"); -MODULE_LICENSE("GPL"); - -/* - * create a new hardware dependent device for Emu10k1 - */ -static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev) -{ - struct snd_emux *emux; - struct snd_emu10k1 *hw; - struct snd_emu10k1_synth_arg *arg; - unsigned long flags; - - arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (arg == NULL) - return -EINVAL; - - if (arg->seq_ports <= 0) - return 0; /* nothing */ - if (arg->max_voices < 1) - arg->max_voices = 1; - else if (arg->max_voices > 64) - arg->max_voices = 64; - - if (snd_emux_new(&emux) < 0) - return -ENOMEM; - - snd_emu10k1_ops_setup(emux); - hw = arg->hwptr; - emux->hw = hw; - emux->max_voices = arg->max_voices; - emux->num_ports = arg->seq_ports; - emux->pitch_shift = -501; - emux->memhdr = hw->memhdr; - /* maximum two ports */ - emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; - /* audigy has two external midis */ - emux->midi_devidx = hw->audigy ? 2 : 1; - emux->linear_panning = 0; - emux->hwdep_idx = 2; /* FIXED */ - - if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) { - snd_emux_free(emux); - return -ENOMEM; - } - - spin_lock_irqsave(&hw->voice_lock, flags); - hw->synth = emux; - hw->get_synth_voice = snd_emu10k1_synth_get_voice; - spin_unlock_irqrestore(&hw->voice_lock, flags); - - dev->driver_data = emux; - - return 0; -} - -static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev) -{ - struct snd_emux *emux; - struct snd_emu10k1 *hw; - unsigned long flags; - - if (dev->driver_data == NULL) - return 0; /* not registered actually */ - - emux = dev->driver_data; - - hw = emux->hw; - spin_lock_irqsave(&hw->voice_lock, flags); - hw->synth = NULL; - hw->get_synth_voice = NULL; - spin_unlock_irqrestore(&hw->voice_lock, flags); - - snd_emux_free(emux); - return 0; -} - -/* - * INIT part - */ - -static int __init alsa_emu10k1_synth_init(void) -{ - - static struct snd_seq_dev_ops ops = { - snd_emu10k1_synth_new_device, - snd_emu10k1_synth_delete_device, - }; - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, &ops, - sizeof(struct snd_emu10k1_synth_arg)); -} - -static void __exit alsa_emu10k1_synth_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH); -} - -module_init(alsa_emu10k1_synth_init) -module_exit(alsa_emu10k1_synth_exit) diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h deleted file mode 100644 index 25f328ff..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __EMU10K1_SYNTH_LOCAL_H -#define __EMU10K1_SYNTH_LOCAL_H -/* - * Local defininitons for Emu10k1 wavetable - * - * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/time.h> -#include <sound/core.h> -#include <sound/emu10k1_synth.h> - -/* emu10k1_patch.c */ -int snd_emu10k1_sample_new(struct snd_emux *private_data, - struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *_data, long count); -int snd_emu10k1_sample_free(struct snd_emux *private_data, - struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr); -int snd_emu10k1_memhdr_init(struct snd_emux *emu); - -/* emu10k1_callback.c */ -void snd_emu10k1_ops_setup(struct snd_emux *emu); -int snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw); - - -#endif /* __EMU10K1_SYNTH_LOCAL_H */ diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c b/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c deleted file mode 100644 index 47a651cb..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c +++ /dev/null @@ -1,1635 +0,0 @@ -/* - * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> - * Driver EMU10K1X chips - * - * Parts of this code were adapted from audigyls.c driver which is - * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> - * - * BUGS: - * -- - * - * TODO: - * - * Chips (SB0200 model): - * - EMU10K1X-DBQ - * - STAC 9708T - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <sound/ac97_codec.h> -#include <sound/info.h> -#include <sound/rawmidi.h> - -MODULE_AUTHOR("Francisco Moraes <fmoraes@nc.rr.com>"); -MODULE_DESCRIPTION("EMU10K1X"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Dell Creative Labs,SB Live!}"); - -// module parameters (see "Module Parameters") -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for the EMU10K1X soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for the EMU10K1X soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable the EMU10K1X soundcard."); - - -// some definitions were borrowed from emu10k1 driver as they seem to be the same -/************************************************************************************************/ -/* PCI function 0 registers, address = <val> + PCIBASE0 */ -/************************************************************************************************/ - -#define PTR 0x00 /* Indexed register set pointer register */ - /* NOTE: The CHANNELNUM and ADDRESS words can */ - /* be modified independently of each other. */ - -#define DATA 0x04 /* Indexed register set data register */ - -#define IPR 0x08 /* Global interrupt pending register */ - /* Clear pending interrupts by writing a 1 to */ - /* the relevant bits and zero to the other bits */ -#define IPR_MIDITRANSBUFEMPTY 0x00000001 /* MIDI UART transmit buffer empty */ -#define IPR_MIDIRECVBUFEMPTY 0x00000002 /* MIDI UART receive buffer empty */ -#define IPR_CH_0_LOOP 0x00000800 /* Channel 0 loop */ -#define IPR_CH_0_HALF_LOOP 0x00000100 /* Channel 0 half loop */ -#define IPR_CAP_0_LOOP 0x00080000 /* Channel capture loop */ -#define IPR_CAP_0_HALF_LOOP 0x00010000 /* Channel capture half loop */ - -#define INTE 0x0c /* Interrupt enable register */ -#define INTE_MIDITXENABLE 0x00000001 /* Enable MIDI transmit-buffer-empty interrupts */ -#define INTE_MIDIRXENABLE 0x00000002 /* Enable MIDI receive-buffer-empty interrupts */ -#define INTE_CH_0_LOOP 0x00000800 /* Channel 0 loop */ -#define INTE_CH_0_HALF_LOOP 0x00000100 /* Channel 0 half loop */ -#define INTE_CAP_0_LOOP 0x00080000 /* Channel capture loop */ -#define INTE_CAP_0_HALF_LOOP 0x00010000 /* Channel capture half loop */ - -#define HCFG 0x14 /* Hardware config register */ - -#define HCFG_LOCKSOUNDCACHE 0x00000008 /* 1 = Cancel bustmaster accesses to soundcache */ - /* NOTE: This should generally never be used. */ -#define HCFG_AUDIOENABLE 0x00000001 /* 0 = CODECs transmit zero-valued samples */ - /* Should be set to 1 when the EMU10K1 is */ - /* completely initialized. */ -#define GPIO 0x18 /* Defaults: 00001080-Analog, 00001000-SPDIF. */ - - -#define AC97DATA 0x1c /* AC97 register set data register (16 bit) */ - -#define AC97ADDRESS 0x1e /* AC97 register set address register (8 bit) */ - -/********************************************************************************************************/ -/* Emu10k1x pointer-offset register set, accessed through the PTR and DATA registers */ -/********************************************************************************************************/ -#define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */ - /* One list entry: 4 bytes for DMA address, - * 4 bytes for period_size << 16. - * One list entry is 8 bytes long. - * One list entry for each period in the buffer. - */ -#define PLAYBACK_LIST_SIZE 0x01 /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000 */ -#define PLAYBACK_LIST_PTR 0x02 /* Pointer to the current period being played */ -#define PLAYBACK_DMA_ADDR 0x04 /* Playback DMA address */ -#define PLAYBACK_PERIOD_SIZE 0x05 /* Playback period size */ -#define PLAYBACK_POINTER 0x06 /* Playback period pointer. Sample currently in DAC */ -#define PLAYBACK_UNKNOWN1 0x07 -#define PLAYBACK_UNKNOWN2 0x08 - -/* Only one capture channel supported */ -#define CAPTURE_DMA_ADDR 0x10 /* Capture DMA address */ -#define CAPTURE_BUFFER_SIZE 0x11 /* Capture buffer size */ -#define CAPTURE_POINTER 0x12 /* Capture buffer pointer. Sample currently in ADC */ -#define CAPTURE_UNKNOWN 0x13 - -/* From 0x20 - 0x3f, last samples played on each channel */ - -#define TRIGGER_CHANNEL 0x40 /* Trigger channel playback */ -#define TRIGGER_CHANNEL_0 0x00000001 /* Trigger channel 0 */ -#define TRIGGER_CHANNEL_1 0x00000002 /* Trigger channel 1 */ -#define TRIGGER_CHANNEL_2 0x00000004 /* Trigger channel 2 */ -#define TRIGGER_CAPTURE 0x00000100 /* Trigger capture channel */ - -#define ROUTING 0x41 /* Setup sound routing ? */ -#define ROUTING_FRONT_LEFT 0x00000001 -#define ROUTING_FRONT_RIGHT 0x00000002 -#define ROUTING_REAR_LEFT 0x00000004 -#define ROUTING_REAR_RIGHT 0x00000008 -#define ROUTING_CENTER_LFE 0x00010000 - -#define SPCS0 0x42 /* SPDIF output Channel Status 0 register */ - -#define SPCS1 0x43 /* SPDIF output Channel Status 1 register */ - -#define SPCS2 0x44 /* SPDIF output Channel Status 2 register */ - -#define SPCS_CLKACCYMASK 0x30000000 /* Clock accuracy */ -#define SPCS_CLKACCY_1000PPM 0x00000000 /* 1000 parts per million */ -#define SPCS_CLKACCY_50PPM 0x10000000 /* 50 parts per million */ -#define SPCS_CLKACCY_VARIABLE 0x20000000 /* Variable accuracy */ -#define SPCS_SAMPLERATEMASK 0x0f000000 /* Sample rate */ -#define SPCS_SAMPLERATE_44 0x00000000 /* 44.1kHz sample rate */ -#define SPCS_SAMPLERATE_48 0x02000000 /* 48kHz sample rate */ -#define SPCS_SAMPLERATE_32 0x03000000 /* 32kHz sample rate */ -#define SPCS_CHANNELNUMMASK 0x00f00000 /* Channel number */ -#define SPCS_CHANNELNUM_UNSPEC 0x00000000 /* Unspecified channel number */ -#define SPCS_CHANNELNUM_LEFT 0x00100000 /* Left channel */ -#define SPCS_CHANNELNUM_RIGHT 0x00200000 /* Right channel */ -#define SPCS_SOURCENUMMASK 0x000f0000 /* Source number */ -#define SPCS_SOURCENUM_UNSPEC 0x00000000 /* Unspecified source number */ -#define SPCS_GENERATIONSTATUS 0x00008000 /* Originality flag (see IEC-958 spec) */ -#define SPCS_CATEGORYCODEMASK 0x00007f00 /* Category code (see IEC-958 spec) */ -#define SPCS_MODEMASK 0x000000c0 /* Mode (see IEC-958 spec) */ -#define SPCS_EMPHASISMASK 0x00000038 /* Emphasis */ -#define SPCS_EMPHASIS_NONE 0x00000000 /* No emphasis */ -#define SPCS_EMPHASIS_50_15 0x00000008 /* 50/15 usec 2 channel */ -#define SPCS_COPYRIGHT 0x00000004 /* Copyright asserted flag -- do not modify */ -#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */ -#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */ - -#define SPDIF_SELECT 0x45 /* Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF */ - -/* This is the MPU port on the card */ -#define MUDATA 0x47 -#define MUCMD 0x48 -#define MUSTAT MUCMD - -/* From 0x50 - 0x5f, last samples captured */ - -/** - * The hardware has 3 channels for playback and 1 for capture. - * - channel 0 is the front channel - * - channel 1 is the rear channel - * - channel 2 is the center/lfe channel - * Volume is controlled by the AC97 for the front and rear channels by - * the PCM Playback Volume, Sigmatel Surround Playback Volume and - * Surround Playback Volume. The Sigmatel 4-Speaker Stereo switch affects - * the front/rear channel mixing in the REAR OUT jack. When using the - * 4-Speaker Stereo, both front and rear channels will be mixed in the - * REAR OUT. - * The center/lfe channel has no volume control and cannot be muted during - * playback. - */ - -struct emu10k1x_voice { - struct emu10k1x *emu; - int number; - int use; - - struct emu10k1x_pcm *epcm; -}; - -struct emu10k1x_pcm { - struct emu10k1x *emu; - struct snd_pcm_substream *substream; - struct emu10k1x_voice *voice; - unsigned short running; -}; - -struct emu10k1x_midi { - struct emu10k1x *emu; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream_input; - struct snd_rawmidi_substream *substream_output; - unsigned int midi_mode; - spinlock_t input_lock; - spinlock_t output_lock; - spinlock_t open_lock; - int tx_enable, rx_enable; - int port; - int ipr_tx, ipr_rx; - void (*interrupt)(struct emu10k1x *emu, unsigned int status); -}; - -// definition of the chip-specific record -struct emu10k1x { - struct snd_card *card; - struct pci_dev *pci; - - unsigned long port; - struct resource *res_port; - int irq; - - unsigned char revision; /* chip revision */ - unsigned int serial; /* serial number */ - unsigned short model; /* subsystem id */ - - spinlock_t emu_lock; - spinlock_t voice_lock; - - struct snd_ac97 *ac97; - struct snd_pcm *pcm; - - struct emu10k1x_voice voices[3]; - struct emu10k1x_voice capture_voice; - u32 spdif_bits[3]; // SPDIF out setup - - struct snd_dma_buffer dma_buffer; - - struct emu10k1x_midi midi; -}; - -/* hardware definition */ -static struct snd_pcm_hardware snd_emu10k1x_playback_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 64, - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = 8, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_emu10k1x_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (32*1024), - .period_bytes_min = 64, - .period_bytes_max = (16*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static unsigned int snd_emu10k1x_ptr_read(struct emu10k1x * emu, - unsigned int reg, - unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -static void snd_emu10k1x_ptr_write(struct emu10k1x *emu, - unsigned int reg, - unsigned int chn, - unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int intr_enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - intr_enable = inl(emu->port + INTE) | intrenb; - outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int intr_enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - intr_enable = inl(emu->port + INTE) & ~intrenb; - outl(intr_enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_gpio_write(struct emu10k1x *emu, unsigned int value) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(value, emu->port + GPIO); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_emu10k1x_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static void snd_emu10k1x_pcm_interrupt(struct emu10k1x *emu, struct emu10k1x_voice *voice) -{ - struct emu10k1x_pcm *epcm; - - if ((epcm = voice->epcm) == NULL) - return; - if (epcm->substream == NULL) - return; -#if 0 - snd_printk(KERN_INFO "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", - epcm->substream->ops->pointer(epcm->substream), - snd_pcm_lib_period_bytes(epcm->substream), - snd_pcm_lib_buffer_bytes(epcm->substream)); -#endif - snd_pcm_period_elapsed(epcm->substream); -} - -/* open callback */ -static int snd_emu10k1x_playback_open(struct snd_pcm_substream *substream) -{ - struct emu10k1x *chip = snd_pcm_substream_chip(substream); - struct emu10k1x_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) { - return err; - } - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) - return err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = chip; - epcm->substream = substream; - - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1x_pcm_free_substream; - - runtime->hw = snd_emu10k1x_playback_hw; - - return 0; -} - -/* close callback */ -static int snd_emu10k1x_playback_close(struct snd_pcm_substream *substream) -{ - return 0; -} - -/* hw_params callback */ -static int snd_emu10k1x_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - - if (! epcm->voice) { - epcm->voice = &epcm->emu->voices[substream->pcm->device]; - epcm->voice->use = 1; - epcm->voice->epcm = epcm; - } - - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_emu10k1x_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm; - - if (runtime->private_data == NULL) - return 0; - - epcm = runtime->private_data; - - if (epcm->voice) { - epcm->voice->use = 0; - epcm->voice->epcm = NULL; - epcm->voice = NULL; - } - - return snd_pcm_lib_free_pages(substream); -} - -/* prepare callback */ -static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int voice = epcm->voice->number; - u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice); - u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); - int i; - - for(i = 0; i < runtime->periods; i++) { - *table_base++=runtime->dma_addr+(i*period_size_bytes); - *table_base++=period_size_bytes<<16; - } - - snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_ADDR, voice, emu->dma_buffer.addr+1024*voice); - snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_SIZE, voice, (runtime->periods - 1) << 19); - snd_emu10k1x_ptr_write(emu, PLAYBACK_LIST_PTR, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_POINTER, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_UNKNOWN1, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_UNKNOWN2, voice, 0); - snd_emu10k1x_ptr_write(emu, PLAYBACK_DMA_ADDR, voice, runtime->dma_addr); - - snd_emu10k1x_ptr_write(emu, PLAYBACK_PERIOD_SIZE, voice, frames_to_bytes(runtime, runtime->period_size)<<16); - - return 0; -} - -/* trigger callback */ -static int snd_emu10k1x_pcm_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int channel = epcm->voice->number; - int result = 0; - -// snd_printk(KERN_INFO "trigger - emu10k1x = 0x%x, cmd = %i, pointer = %d\n", (int)emu, cmd, (int)substream->ops->pointer(substream)); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if(runtime->periods == 2) - snd_emu10k1x_intr_enable(emu, (INTE_CH_0_LOOP | INTE_CH_0_HALF_LOOP) << channel); - else - snd_emu10k1x_intr_enable(emu, INTE_CH_0_LOOP << channel); - epcm->running = 1; - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0)|(TRIGGER_CHANNEL_0<<channel)); - break; - case SNDRV_PCM_TRIGGER_STOP: - epcm->running = 0; - snd_emu10k1x_intr_disable(emu, (INTE_CH_0_LOOP | INTE_CH_0_HALF_LOOP) << channel); - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0) & ~(TRIGGER_CHANNEL_0<<channel)); - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* pointer callback */ -static snd_pcm_uframes_t -snd_emu10k1x_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int channel = epcm->voice->number; - snd_pcm_uframes_t ptr = 0, ptr1 = 0, ptr2= 0,ptr3 = 0,ptr4 = 0; - - if (!epcm->running) - return 0; - - ptr3 = snd_emu10k1x_ptr_read(emu, PLAYBACK_LIST_PTR, channel); - ptr1 = snd_emu10k1x_ptr_read(emu, PLAYBACK_POINTER, channel); - ptr4 = snd_emu10k1x_ptr_read(emu, PLAYBACK_LIST_PTR, channel); - - if(ptr4 == 0 && ptr1 == frames_to_bytes(runtime, runtime->buffer_size)) - return 0; - - if (ptr3 != ptr4) - ptr1 = snd_emu10k1x_ptr_read(emu, PLAYBACK_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr2 += (ptr4 >> 3) * runtime->period_size; - ptr = ptr2; - - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - - return ptr; -} - -/* operators */ -static struct snd_pcm_ops snd_emu10k1x_playback_ops = { - .open = snd_emu10k1x_playback_open, - .close = snd_emu10k1x_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1x_pcm_hw_params, - .hw_free = snd_emu10k1x_pcm_hw_free, - .prepare = snd_emu10k1x_pcm_prepare, - .trigger = snd_emu10k1x_pcm_trigger, - .pointer = snd_emu10k1x_pcm_pointer, -}; - -/* open_capture callback */ -static int snd_emu10k1x_pcm_open_capture(struct snd_pcm_substream *substream) -{ - struct emu10k1x *chip = snd_pcm_substream_chip(substream); - struct emu10k1x_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) - return err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - - epcm->emu = chip; - epcm->substream = substream; - - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1x_pcm_free_substream; - - runtime->hw = snd_emu10k1x_capture_hw; - - return 0; -} - -/* close callback */ -static int snd_emu10k1x_pcm_close_capture(struct snd_pcm_substream *substream) -{ - return 0; -} - -/* hw_params callback */ -static int snd_emu10k1x_pcm_hw_params_capture(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - - if (! epcm->voice) { - if (epcm->emu->capture_voice.use) - return -EBUSY; - epcm->voice = &epcm->emu->capture_voice; - epcm->voice->epcm = epcm; - epcm->voice->use = 1; - } - - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -/* hw_free callback */ -static int snd_emu10k1x_pcm_hw_free_capture(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - struct emu10k1x_pcm *epcm; - - if (runtime->private_data == NULL) - return 0; - epcm = runtime->private_data; - - if (epcm->voice) { - epcm->voice->use = 0; - epcm->voice->epcm = NULL; - epcm->voice = NULL; - } - - return snd_pcm_lib_free_pages(substream); -} - -/* prepare capture callback */ -static int snd_emu10k1x_pcm_prepare_capture(struct snd_pcm_substream *substream) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_emu10k1x_ptr_write(emu, CAPTURE_DMA_ADDR, 0, runtime->dma_addr); - snd_emu10k1x_ptr_write(emu, CAPTURE_BUFFER_SIZE, 0, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes - snd_emu10k1x_ptr_write(emu, CAPTURE_POINTER, 0, 0); - snd_emu10k1x_ptr_write(emu, CAPTURE_UNKNOWN, 0, 0); - - return 0; -} - -/* trigger_capture callback */ -static int snd_emu10k1x_pcm_trigger_capture(struct snd_pcm_substream *substream, - int cmd) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - int result = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_emu10k1x_intr_enable(emu, INTE_CAP_0_LOOP | - INTE_CAP_0_HALF_LOOP); - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0)|TRIGGER_CAPTURE); - epcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - epcm->running = 0; - snd_emu10k1x_intr_disable(emu, INTE_CAP_0_LOOP | - INTE_CAP_0_HALF_LOOP); - snd_emu10k1x_ptr_write(emu, TRIGGER_CHANNEL, 0, snd_emu10k1x_ptr_read(emu, TRIGGER_CHANNEL, 0) & ~(TRIGGER_CAPTURE)); - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* pointer_capture callback */ -static snd_pcm_uframes_t -snd_emu10k1x_pcm_pointer_capture(struct snd_pcm_substream *substream) -{ - struct emu10k1x *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct emu10k1x_pcm *epcm = runtime->private_data; - snd_pcm_uframes_t ptr; - - if (!epcm->running) - return 0; - - ptr = bytes_to_frames(runtime, snd_emu10k1x_ptr_read(emu, CAPTURE_POINTER, 0)); - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - - return ptr; -} - -static struct snd_pcm_ops snd_emu10k1x_capture_ops = { - .open = snd_emu10k1x_pcm_open_capture, - .close = snd_emu10k1x_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1x_pcm_hw_params_capture, - .hw_free = snd_emu10k1x_pcm_hw_free_capture, - .prepare = snd_emu10k1x_pcm_prepare_capture, - .trigger = snd_emu10k1x_pcm_trigger_capture, - .pointer = snd_emu10k1x_pcm_pointer_capture, -}; - -static unsigned short snd_emu10k1x_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - struct emu10k1x *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - val = inw(emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -static void snd_emu10k1x_ac97_write(struct snd_ac97 *ac97, - unsigned short reg, unsigned short val) -{ - struct emu10k1x *emu = ac97->private_data; - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - outw(val, emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static int snd_emu10k1x_ac97(struct emu10k1x *chip) -{ - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - int err; - static struct snd_ac97_bus_ops ops = { - .write = snd_emu10k1x_ac97_write, - .read = snd_emu10k1x_ac97_read, - }; - - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) - return err; - pbus->no_vra = 1; /* we don't need VRA */ - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = chip; - ac97.scaps = AC97_SCAP_NO_SPDIF; - return snd_ac97_mixer(pbus, &ac97, &chip->ac97); -} - -static int snd_emu10k1x_free(struct emu10k1x *chip) -{ - snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0); - // disable interrupts - outl(0, chip->port + INTE); - // disable audio - outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); - - /* release the irq */ - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - // release the i/o port - release_and_free_resource(chip->res_port); - - // release the DMA - if (chip->dma_buffer.area) { - snd_dma_free_pages(&chip->dma_buffer); - } - - pci_disable_device(chip->pci); - - // release the data - kfree(chip); - return 0; -} - -static int snd_emu10k1x_dev_free(struct snd_device *device) -{ - struct emu10k1x *chip = device->device_data; - return snd_emu10k1x_free(chip); -} - -static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id) -{ - unsigned int status; - - struct emu10k1x *chip = dev_id; - struct emu10k1x_voice *pvoice = chip->voices; - int i; - int mask; - - status = inl(chip->port + IPR); - - if (! status) - return IRQ_NONE; - - // capture interrupt - if (status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) { - struct emu10k1x_voice *cap_voice = &chip->capture_voice; - if (cap_voice->use) - snd_emu10k1x_pcm_interrupt(chip, cap_voice); - else - snd_emu10k1x_intr_disable(chip, - INTE_CAP_0_LOOP | - INTE_CAP_0_HALF_LOOP); - } - - mask = IPR_CH_0_LOOP|IPR_CH_0_HALF_LOOP; - for (i = 0; i < 3; i++) { - if (status & mask) { - if (pvoice->use) - snd_emu10k1x_pcm_interrupt(chip, pvoice); - else - snd_emu10k1x_intr_disable(chip, mask); - } - pvoice++; - mask <<= 1; - } - - if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) { - if (chip->midi.interrupt) - chip->midi.interrupt(chip, status); - else - snd_emu10k1x_intr_disable(chip, INTE_MIDITXENABLE|INTE_MIDIRXENABLE); - } - - // acknowledge the interrupt if necessary - outl(status, chip->port + IPR); - - // snd_printk(KERN_INFO "interrupt %08x\n", status); - return IRQ_HANDLED; -} - -static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - int capture = 0; - - if (rpcm) - *rpcm = NULL; - if (device == 0) - capture = 1; - - if ((err = snd_pcm_new(emu->card, "emu10k1x", device, 1, capture, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - switch(device) { - case 0: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1x_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1x_capture_ops); - break; - case 1: - case 2: - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1x_playback_ops); - break; - } - - pcm->info_flags = 0; - switch(device) { - case 0: - strcpy(pcm->name, "EMU10K1X Front"); - break; - case 1: - strcpy(pcm->name, "EMU10K1X Rear"); - break; - case 2: - strcpy(pcm->name, "EMU10K1X Center/LFE"); - break; - } - emu->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - 32*1024, 32*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -static int __devinit snd_emu10k1x_create(struct snd_card *card, - struct pci_dev *pci, - struct emu10k1x **rchip) -{ - struct emu10k1x *chip; - int err; - int ch; - static struct snd_device_ops ops = { - .dev_free = snd_emu10k1x_dev_free, - }; - - *rchip = NULL; - - if ((err = pci_enable_device(pci)) < 0) - return err; - if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 || - pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) { - snd_printk(KERN_ERR "error to set 28bit mask DMA\n"); - pci_disable_device(pci); - return -ENXIO; - } - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - pci_disable_device(pci); - return -ENOMEM; - } - - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - spin_lock_init(&chip->emu_lock); - spin_lock_init(&chip->voice_lock); - - chip->port = pci_resource_start(pci, 0); - if ((chip->res_port = request_region(chip->port, 8, - "EMU10K1X")) == NULL) { - snd_printk(KERN_ERR "emu10k1x: cannot allocate the port 0x%lx\n", chip->port); - snd_emu10k1x_free(chip); - return -EBUSY; - } - - if (request_irq(pci->irq, snd_emu10k1x_interrupt, - IRQF_SHARED, KBUILD_MODNAME, chip)) { - snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq); - snd_emu10k1x_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - - if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), - 4 * 1024, &chip->dma_buffer) < 0) { - snd_emu10k1x_free(chip); - return -ENOMEM; - } - - pci_set_master(pci); - /* read revision & serial */ - chip->revision = pci->revision; - pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); - snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, - chip->revision, chip->serial); - - outl(0, chip->port + INTE); - - for(ch = 0; ch < 3; ch++) { - chip->voices[ch].emu = chip; - chip->voices[ch].number = ch; - } - - /* - * Init to 0x02109204 : - * Clock accuracy = 0 (1000ppm) - * Sample Rate = 2 (48kHz) - * Audio Channel = 1 (Left of 2) - * Source Number = 0 (Unspecified) - * Generation Status = 1 (Original for Cat Code 12) - * Cat Code = 12 (Digital Signal Mixer) - * Mode = 0 (Mode 0) - * Emphasis = 0 (None) - * CP = 1 (Copyright unasserted) - * AN = 0 (Audio data) - * P = 0 (Consumer) - */ - snd_emu10k1x_ptr_write(chip, SPCS0, 0, - chip->spdif_bits[0] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - snd_emu10k1x_ptr_write(chip, SPCS1, 0, - chip->spdif_bits[1] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - snd_emu10k1x_ptr_write(chip, SPCS2, 0, - chip->spdif_bits[2] = - SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | - SPCS_GENERATIONSTATUS | 0x00001200 | - 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); - - snd_emu10k1x_ptr_write(chip, SPDIF_SELECT, 0, 0x700); // disable SPDIF - snd_emu10k1x_ptr_write(chip, ROUTING, 0, 0x1003F); // routing - snd_emu10k1x_gpio_write(chip, 0x1080); // analog mode - - outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &ops)) < 0) { - snd_emu10k1x_free(chip); - return err; - } - *rchip = chip; - return 0; -} - -static void snd_emu10k1x_proc_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct emu10k1x *emu = entry->private_data; - unsigned long value,value1,value2; - unsigned long flags; - int i; - - snd_iprintf(buffer, "Registers:\n\n"); - for(i = 0; i < 0x20; i+=4) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inl(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "Register %02X: %08lX\n", i, value); - } - snd_iprintf(buffer, "\nRegisters\n\n"); - for(i = 0; i <= 0x48; i++) { - value = snd_emu10k1x_ptr_read(emu, i, 0); - if(i < 0x10 || (i >= 0x20 && i < 0x40)) { - value1 = snd_emu10k1x_ptr_read(emu, i, 1); - value2 = snd_emu10k1x_ptr_read(emu, i, 2); - snd_iprintf(buffer, "%02X: %08lX %08lX %08lX\n", i, value, value1, value2); - } else { - snd_iprintf(buffer, "%02X: %08lX\n", i, value); - } - } -} - -static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct emu10k1x *emu = entry->private_data; - char line[64]; - unsigned int reg, channel_id , val; - - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) - continue; - - if (reg < 0x49 && val <= 0xffffffff && channel_id <= 2) - snd_emu10k1x_ptr_write(emu, reg, channel_id, val); - } -} - -static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu) -{ - struct snd_info_entry *entry; - - if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read); - entry->c.text.write = snd_emu10k1x_proc_reg_write; - entry->mode |= S_IWUSR; - entry->private_data = emu; - } - - return 0; -} - -#define snd_emu10k1x_shared_spdif_info snd_ctl_boolean_mono_info - -static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = (snd_emu10k1x_ptr_read(emu, SPDIF_SELECT, 0) == 0x700) ? 0 : 1; - - return 0; -} - -static int snd_emu10k1x_shared_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.integer.value[0] ; - - if (val) { - // enable spdif output - snd_emu10k1x_ptr_write(emu, SPDIF_SELECT, 0, 0x000); - snd_emu10k1x_ptr_write(emu, ROUTING, 0, 0x700); - snd_emu10k1x_gpio_write(emu, 0x1000); - } else { - // disable spdif output - snd_emu10k1x_ptr_write(emu, SPDIF_SELECT, 0, 0x700); - snd_emu10k1x_ptr_write(emu, ROUTING, 0, 0x1003F); - snd_emu10k1x_gpio_write(emu, 0x1080); - } - return change; -} - -static struct snd_kcontrol_new snd_emu10k1x_shared_spdif __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog/Digital Output Jack", - .info = snd_emu10k1x_shared_spdif_info, - .get = snd_emu10k1x_shared_spdif_get, - .put = snd_emu10k1x_shared_spdif_put -}; - -static int snd_emu10k1x_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_emu10k1x_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; - return 0; -} - -static int snd_emu10k1x_spdif_get_mask(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -static int snd_emu10k1x_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct emu10k1x *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - int change; - unsigned int val; - - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - change = val != emu->spdif_bits[idx]; - if (change) { - snd_emu10k1x_ptr_write(emu, SPCS0 + idx, 0, val); - emu->spdif_bits[idx] = val; - } - return change; -} - -static struct snd_kcontrol_new snd_emu10k1x_spdif_mask_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .count = 3, - .info = snd_emu10k1x_spdif_info, - .get = snd_emu10k1x_spdif_get_mask -}; - -static struct snd_kcontrol_new snd_emu10k1x_spdif_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .count = 3, - .info = snd_emu10k1x_spdif_info, - .get = snd_emu10k1x_spdif_get, - .put = snd_emu10k1x_spdif_put -}; - -static int __devinit snd_emu10k1x_mixer(struct emu10k1x *emu) -{ - int err; - struct snd_kcontrol *kctl; - struct snd_card *card = emu->card; - - if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_mask_control, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1x_shared_spdif, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_control, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - - return 0; -} - -#define EMU10K1X_MIDI_MODE_INPUT (1<<0) -#define EMU10K1X_MIDI_MODE_OUTPUT (1<<1) - -static inline unsigned char mpu401_read(struct emu10k1x *emu, struct emu10k1x_midi *mpu, int idx) -{ - return (unsigned char)snd_emu10k1x_ptr_read(emu, mpu->port + idx, 0); -} - -static inline void mpu401_write(struct emu10k1x *emu, struct emu10k1x_midi *mpu, int data, int idx) -{ - snd_emu10k1x_ptr_write(emu, mpu->port + idx, 0, data); -} - -#define mpu401_write_data(emu, mpu, data) mpu401_write(emu, mpu, data, 0) -#define mpu401_write_cmd(emu, mpu, data) mpu401_write(emu, mpu, data, 1) -#define mpu401_read_data(emu, mpu) mpu401_read(emu, mpu, 0) -#define mpu401_read_stat(emu, mpu) mpu401_read(emu, mpu, 1) - -#define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80)) -#define mpu401_output_ready(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x40)) - -#define MPU401_RESET 0xff -#define MPU401_ENTER_UART 0x3f -#define MPU401_ACK 0xfe - -static void mpu401_clear_rx(struct emu10k1x *emu, struct emu10k1x_midi *mpu) -{ - int timeout = 100000; - for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--) - mpu401_read_data(emu, mpu); -#ifdef CONFIG_SND_DEBUG - if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); -#endif -} - -/* - - */ - -static void do_emu10k1x_midi_interrupt(struct emu10k1x *emu, - struct emu10k1x_midi *midi, unsigned int status) -{ - unsigned char byte; - - if (midi->rmidi == NULL) { - snd_emu10k1x_intr_disable(emu, midi->tx_enable | midi->rx_enable); - return; - } - - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - mpu401_clear_rx(emu, midi); - } else { - byte = mpu401_read_data(emu, midi); - if (midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); - } - } - spin_unlock(&midi->input_lock); - - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - mpu401_write_data(emu, midi, byte); - } else { - snd_emu10k1x_intr_disable(emu, midi->tx_enable); - } - } - spin_unlock(&midi->output_lock); -} - -static void snd_emu10k1x_midi_interrupt(struct emu10k1x *emu, unsigned int status) -{ - do_emu10k1x_midi_interrupt(emu, &emu->midi, status); -} - -static int snd_emu10k1x_midi_cmd(struct emu10k1x * emu, - struct emu10k1x_midi *midi, unsigned char cmd, int ack) -{ - unsigned long flags; - int timeout, ok; - - spin_lock_irqsave(&midi->input_lock, flags); - mpu401_write_data(emu, midi, 0x00); - /* mpu401_clear_rx(emu, midi); */ - - mpu401_write_cmd(emu, midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (mpu401_input_avail(emu, midi)) { - if (mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } - } - if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } else { - ok = 1; - } - spin_unlock_irqrestore(&midi->input_lock, flags); - if (!ok) { - snd_printk(KERN_ERR "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", - cmd, emu->port, - mpu401_read_stat(emu, midi), - mpu401_read_data(emu, midi)); - return 1; - } - return 0; -} - -static int snd_emu10k1x_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1X_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1x_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1X_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1x_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1x_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1x_intr_disable(emu, midi->rx_enable); - midi->midi_mode &= ~EMU10K1X_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static int snd_emu10k1x_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1x_intr_disable(emu, midi->tx_enable); - midi->midi_mode &= ~EMU10K1X_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1x_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static void snd_emu10k1x_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) - snd_emu10k1x_intr_enable(emu, midi->rx_enable); - else - snd_emu10k1x_intr_disable(emu, midi->rx_enable); -} - -static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct emu10k1x *emu; - struct emu10k1x_midi *midi = substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) { - int max = 4; - unsigned char byte; - - /* try to send some amount of bytes here before interrupts */ - spin_lock_irqsave(&midi->output_lock, flags); - while (max > 0) { - if (mpu401_output_ready(emu, midi)) { - if (!(midi->midi_mode & EMU10K1X_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irqrestore(&midi->output_lock, flags); - return; - } - mpu401_write_data(emu, midi, byte); - max--; - } else { - break; - } - } - spin_unlock_irqrestore(&midi->output_lock, flags); - snd_emu10k1x_intr_enable(emu, midi->tx_enable); - } else { - snd_emu10k1x_intr_disable(emu, midi->tx_enable); - } -} - -/* - - */ - -static struct snd_rawmidi_ops snd_emu10k1x_midi_output = -{ - .open = snd_emu10k1x_midi_output_open, - .close = snd_emu10k1x_midi_output_close, - .trigger = snd_emu10k1x_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_emu10k1x_midi_input = -{ - .open = snd_emu10k1x_midi_input_open, - .close = snd_emu10k1x_midi_input_close, - .trigger = snd_emu10k1x_midi_input_trigger, -}; - -static void snd_emu10k1x_midi_free(struct snd_rawmidi *rmidi) -{ - struct emu10k1x_midi *midi = rmidi->private_data; - midi->interrupt = NULL; - midi->rmidi = NULL; -} - -static int __devinit emu10k1x_midi_init(struct emu10k1x *emu, - struct emu10k1x_midi *midi, int device, char *name) -{ - struct snd_rawmidi *rmidi; - int err; - - if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0) - return err; - midi->emu = emu; - spin_lock_init(&midi->open_lock); - spin_lock_init(&midi->input_lock); - spin_lock_init(&midi->output_lock); - strcpy(rmidi->name, name); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1x_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1x_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = midi; - rmidi->private_free = snd_emu10k1x_midi_free; - midi->rmidi = rmidi; - return 0; -} - -static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu) -{ - struct emu10k1x_midi *midi = &emu->midi; - int err; - - if ((err = emu10k1x_midi_init(emu, midi, 0, "EMU10K1X MPU-401 (UART)")) < 0) - return err; - - midi->tx_enable = INTE_MIDITXENABLE; - midi->rx_enable = INTE_MIDIRXENABLE; - midi->port = MUDATA; - midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; - midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; - midi->interrupt = snd_emu10k1x_midi_interrupt; - return 0; -} - -static int __devinit snd_emu10k1x_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct emu10k1x *chip; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); - if (err < 0) - return err; - - if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_emu10k1x_pcm(chip, 1, NULL)) < 0) { - snd_card_free(card); - return err; - } - if ((err = snd_emu10k1x_pcm(chip, 2, NULL)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_ac97(chip)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_mixer(chip)) < 0) { - snd_card_free(card); - return err; - } - - if ((err = snd_emu10k1x_midi(chip)) < 0) { - snd_card_free(card); - return err; - } - - snd_emu10k1x_proc_init(chip); - - strcpy(card->driver, "EMU10K1X"); - strcpy(card->shortname, "Dell Sound Blaster Live!"); - sprintf(card->longname, "%s at 0x%lx irq %i", - card->shortname, chip->port, chip->irq); - - snd_card_set_dev(card, &pci->dev); - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; - } - - pci_set_drvdata(pci, card); - dev++; - return 0; -} - -static void __devexit snd_emu10k1x_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} - -// PCI IDs -static DEFINE_PCI_DEVICE_TABLE(snd_emu10k1x_ids) = { - { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */ - { 0, } -}; -MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids); - -// pci_driver definition -static struct pci_driver driver = { - .name = KBUILD_MODNAME, - .id_table = snd_emu10k1x_ids, - .probe = snd_emu10k1x_probe, - .remove = __devexit_p(snd_emu10k1x_remove), -}; - -// initialization of the module -static int __init alsa_card_emu10k1x_init(void) -{ - return pci_register_driver(&driver); -} - -// clean up the module -static void __exit alsa_card_emu10k1x_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_emu10k1x_init) -module_exit(alsa_card_emu10k1x_exit) diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emufx.c b/ANDROID_3.4.5/sound/pci/emu10k1/emufx.c deleted file mode 100644 index dae4050e..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emufx.c +++ /dev/null @@ -1,2758 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Creative Labs, Inc. - * Routines for effect processor FX8010 - * - * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> - * Added EMU 1010 support. - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/pci.h> -#include <linux/capability.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/init.h> -#include <linux/mutex.h> -#include <linux/moduleparam.h> - -#include <sound/core.h> -#include <sound/tlv.h> -#include <sound/emu10k1.h> - -#if 0 /* for testing purposes - digital out -> capture */ -#define EMU10K1_CAPTURE_DIGITAL_OUT -#endif -#if 0 /* for testing purposes - set S/PDIF to AC3 output */ -#define EMU10K1_SET_AC3_IEC958 -#endif -#if 0 /* for testing purposes - feed the front signal to Center/LFE outputs */ -#define EMU10K1_CENTER_LFE_FROM_FRONT -#endif - -static bool high_res_gpr_volume; -module_param(high_res_gpr_volume, bool, 0444); -MODULE_PARM_DESC(high_res_gpr_volume, "GPR mixer controls use 31-bit range."); - -/* - * Tables - */ - -static char *fxbuses[16] = { - /* 0x00 */ "PCM Left", - /* 0x01 */ "PCM Right", - /* 0x02 */ "PCM Surround Left", - /* 0x03 */ "PCM Surround Right", - /* 0x04 */ "MIDI Left", - /* 0x05 */ "MIDI Right", - /* 0x06 */ "Center", - /* 0x07 */ "LFE", - /* 0x08 */ NULL, - /* 0x09 */ NULL, - /* 0x0a */ NULL, - /* 0x0b */ NULL, - /* 0x0c */ "MIDI Reverb", - /* 0x0d */ "MIDI Chorus", - /* 0x0e */ NULL, - /* 0x0f */ NULL -}; - -static char *creative_ins[16] = { - /* 0x00 */ "AC97 Left", - /* 0x01 */ "AC97 Right", - /* 0x02 */ "TTL IEC958 Left", - /* 0x03 */ "TTL IEC958 Right", - /* 0x04 */ "Zoom Video Left", - /* 0x05 */ "Zoom Video Right", - /* 0x06 */ "Optical IEC958 Left", - /* 0x07 */ "Optical IEC958 Right", - /* 0x08 */ "Line/Mic 1 Left", - /* 0x09 */ "Line/Mic 1 Right", - /* 0x0a */ "Coaxial IEC958 Left", - /* 0x0b */ "Coaxial IEC958 Right", - /* 0x0c */ "Line/Mic 2 Left", - /* 0x0d */ "Line/Mic 2 Right", - /* 0x0e */ NULL, - /* 0x0f */ NULL -}; - -static char *audigy_ins[16] = { - /* 0x00 */ "AC97 Left", - /* 0x01 */ "AC97 Right", - /* 0x02 */ "Audigy CD Left", - /* 0x03 */ "Audigy CD Right", - /* 0x04 */ "Optical IEC958 Left", - /* 0x05 */ "Optical IEC958 Right", - /* 0x06 */ NULL, - /* 0x07 */ NULL, - /* 0x08 */ "Line/Mic 2 Left", - /* 0x09 */ "Line/Mic 2 Right", - /* 0x0a */ "SPDIF Left", - /* 0x0b */ "SPDIF Right", - /* 0x0c */ "Aux2 Left", - /* 0x0d */ "Aux2 Right", - /* 0x0e */ NULL, - /* 0x0f */ NULL -}; - -static char *creative_outs[32] = { - /* 0x00 */ "AC97 Left", - /* 0x01 */ "AC97 Right", - /* 0x02 */ "Optical IEC958 Left", - /* 0x03 */ "Optical IEC958 Right", - /* 0x04 */ "Center", - /* 0x05 */ "LFE", - /* 0x06 */ "Headphone Left", - /* 0x07 */ "Headphone Right", - /* 0x08 */ "Surround Left", - /* 0x09 */ "Surround Right", - /* 0x0a */ "PCM Capture Left", - /* 0x0b */ "PCM Capture Right", - /* 0x0c */ "MIC Capture", - /* 0x0d */ "AC97 Surround Left", - /* 0x0e */ "AC97 Surround Right", - /* 0x0f */ NULL, - /* 0x10 */ NULL, - /* 0x11 */ "Analog Center", - /* 0x12 */ "Analog LFE", - /* 0x13 */ NULL, - /* 0x14 */ NULL, - /* 0x15 */ NULL, - /* 0x16 */ NULL, - /* 0x17 */ NULL, - /* 0x18 */ NULL, - /* 0x19 */ NULL, - /* 0x1a */ NULL, - /* 0x1b */ NULL, - /* 0x1c */ NULL, - /* 0x1d */ NULL, - /* 0x1e */ NULL, - /* 0x1f */ NULL, -}; - -static char *audigy_outs[32] = { - /* 0x00 */ "Digital Front Left", - /* 0x01 */ "Digital Front Right", - /* 0x02 */ "Digital Center", - /* 0x03 */ "Digital LEF", - /* 0x04 */ "Headphone Left", - /* 0x05 */ "Headphone Right", - /* 0x06 */ "Digital Rear Left", - /* 0x07 */ "Digital Rear Right", - /* 0x08 */ "Front Left", - /* 0x09 */ "Front Right", - /* 0x0a */ "Center", - /* 0x0b */ "LFE", - /* 0x0c */ NULL, - /* 0x0d */ NULL, - /* 0x0e */ "Rear Left", - /* 0x0f */ "Rear Right", - /* 0x10 */ "AC97 Front Left", - /* 0x11 */ "AC97 Front Right", - /* 0x12 */ "ADC Caputre Left", - /* 0x13 */ "ADC Capture Right", - /* 0x14 */ NULL, - /* 0x15 */ NULL, - /* 0x16 */ NULL, - /* 0x17 */ NULL, - /* 0x18 */ NULL, - /* 0x19 */ NULL, - /* 0x1a */ NULL, - /* 0x1b */ NULL, - /* 0x1c */ NULL, - /* 0x1d */ NULL, - /* 0x1e */ NULL, - /* 0x1f */ NULL, -}; - -static const u32 bass_table[41][5] = { - { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 }, - { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d }, - { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee }, - { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c }, - { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b }, - { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 }, - { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f }, - { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 }, - { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 }, - { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 }, - { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 }, - { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be }, - { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b }, - { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c }, - { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b }, - { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 }, - { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a }, - { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 }, - { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 }, - { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e }, - { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee }, - { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 }, - { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 }, - { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 }, - { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 }, - { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e }, - { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 }, - { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 }, - { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 }, - { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 }, - { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 }, - { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca }, - { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 }, - { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 }, - { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 }, - { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 }, - { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a }, - { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f }, - { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 }, - { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 }, - { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 } -}; - -static const u32 treble_table[41][5] = { - { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 }, - { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 }, - { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 }, - { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca }, - { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 }, - { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 }, - { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 }, - { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 }, - { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 }, - { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df }, - { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff }, - { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 }, - { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c }, - { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 }, - { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 }, - { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 }, - { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 }, - { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d }, - { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 }, - { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 }, - { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f }, - { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb }, - { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 }, - { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 }, - { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd }, - { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 }, - { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad }, - { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 }, - { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 }, - { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c }, - { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 }, - { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 }, - { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 }, - { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 }, - { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 }, - { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 }, - { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d }, - { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b }, - { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 }, - { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd }, - { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 } -}; - -/* dB gain = (float) 20 * log10( float(db_table_value) / 0x8000000 ) */ -static const u32 db_table[101] = { - 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540, - 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8, - 0x0207567a, 0x021fd03d, 0x0239714c, 0x02544792, 0x027061a1, - 0x028dcebb, 0x02ac9edc, 0x02cce2bf, 0x02eeabe8, 0x03120cb0, - 0x0337184e, 0x035de2df, 0x03868173, 0x03b10a18, 0x03dd93e9, - 0x040c3713, 0x043d0cea, 0x04702ff3, 0x04a5bbf2, 0x04ddcdfb, - 0x0518847f, 0x0555ff62, 0x05966005, 0x05d9c95d, 0x06206005, - 0x066a4a52, 0x06b7b067, 0x0708bc4c, 0x075d9a01, 0x07b6779d, - 0x08138561, 0x0874f5d5, 0x08dafde1, 0x0945d4ed, 0x09b5b4fd, - 0x0a2adad1, 0x0aa58605, 0x0b25f936, 0x0bac7a24, 0x0c3951d8, - 0x0ccccccc, 0x0d673b17, 0x0e08f093, 0x0eb24510, 0x0f639481, - 0x101d3f2d, 0x10dfa9e6, 0x11ab3e3f, 0x12806ac3, 0x135fa333, - 0x144960c5, 0x153e2266, 0x163e6cfe, 0x174acbb7, 0x1863d04d, - 0x198a1357, 0x1abe349f, 0x1c00db77, 0x1d52b712, 0x1eb47ee6, - 0x2026f30f, 0x21aadcb6, 0x23410e7e, 0x24ea64f9, 0x26a7c71d, - 0x287a26c4, 0x2a62812c, 0x2c61df84, 0x2e795779, 0x30aa0bcf, - 0x32f52cfe, 0x355bf9d8, 0x37dfc033, 0x3a81dda4, 0x3d43c038, - 0x4026e73c, 0x432ce40f, 0x46575af8, 0x49a8040f, 0x4d20ac2a, - 0x50c335d3, 0x54919a57, 0x588dead1, 0x5cba514a, 0x611911ea, - 0x65ac8c2f, 0x6a773c39, 0x6f7bbc23, 0x74bcc56c, 0x7a3d3272, - 0x7fffffff, -}; - -/* EMU10k1/EMU10k2 DSP control db gain */ -static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); -static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0); - -/* EMU10K1 bass/treble db gain */ -static const DECLARE_TLV_DB_SCALE(snd_emu10k1_bass_treble_db_scale, -1200, 60, 0); - -static const u32 onoff_table[2] = { - 0x00000000, 0x00000001 -}; - -/* - */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* - * controls - */ - -static int snd_emu10k1_gpr_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1_fx8010_ctl *ctl = - (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value; - - if (ctl->min == 0 && ctl->max == 1) - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - else - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = ctl->vcount; - uinfo->value.integer.min = ctl->min; - uinfo->value.integer.max = ctl->max; - return 0; -} - -static int snd_emu10k1_gpr_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_fx8010_ctl *ctl = - (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value; - unsigned long flags; - unsigned int i; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (i = 0; i < ctl->vcount; i++) - ucontrol->value.integer.value[i] = ctl->value[i]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_gpr_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_fx8010_ctl *ctl = - (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value; - unsigned long flags; - unsigned int nval, val; - unsigned int i, j; - int change = 0; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (i = 0; i < ctl->vcount; i++) { - nval = ucontrol->value.integer.value[i]; - if (nval < ctl->min) - nval = ctl->min; - if (nval > ctl->max) - nval = ctl->max; - if (nval != ctl->value[i]) - change = 1; - val = ctl->value[i] = nval; - switch (ctl->translation) { - case EMU10K1_GPR_TRANSLATION_NONE: - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val); - break; - case EMU10K1_GPR_TRANSLATION_TABLE100: - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]); - break; - case EMU10K1_GPR_TRANSLATION_BASS: - if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { - change = -EIO; - goto __error; - } - for (j = 0; j < 5; j++) - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]); - break; - case EMU10K1_GPR_TRANSLATION_TREBLE: - if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) { - change = -EIO; - goto __error; - } - for (j = 0; j < 5; j++) - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]); - break; - case EMU10K1_GPR_TRANSLATION_ONOFF: - snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]); - break; - } - } - __error: - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -/* - * Interrupt handler - */ - -static void snd_emu10k1_fx8010_interrupt(struct snd_emu10k1 *emu) -{ - struct snd_emu10k1_fx8010_irq *irq, *nirq; - - irq = emu->fx8010.irq_handlers; - while (irq) { - nirq = irq->next; /* irq ptr can be removed from list */ - if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) { - if (irq->handler) - irq->handler(emu, irq->private_data); - snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1); - } - irq = nirq; - } -} - -int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu, - snd_fx8010_irq_handler_t *handler, - unsigned char gpr_running, - void *private_data, - struct snd_emu10k1_fx8010_irq **r_irq) -{ - struct snd_emu10k1_fx8010_irq *irq; - unsigned long flags; - - irq = kmalloc(sizeof(*irq), GFP_ATOMIC); - if (irq == NULL) - return -ENOMEM; - irq->handler = handler; - irq->gpr_running = gpr_running; - irq->private_data = private_data; - irq->next = NULL; - spin_lock_irqsave(&emu->fx8010.irq_lock, flags); - if (emu->fx8010.irq_handlers == NULL) { - emu->fx8010.irq_handlers = irq; - emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt; - snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE); - } else { - irq->next = emu->fx8010.irq_handlers; - emu->fx8010.irq_handlers = irq; - } - spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags); - if (r_irq) - *r_irq = irq; - return 0; -} - -int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_irq *irq) -{ - struct snd_emu10k1_fx8010_irq *tmp; - unsigned long flags; - - spin_lock_irqsave(&emu->fx8010.irq_lock, flags); - if ((tmp = emu->fx8010.irq_handlers) == irq) { - emu->fx8010.irq_handlers = tmp->next; - if (emu->fx8010.irq_handlers == NULL) { - snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); - emu->dsp_interrupt = NULL; - } - } else { - while (tmp && tmp->next != irq) - tmp = tmp->next; - if (tmp) - tmp->next = tmp->next->next; - } - spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags); - kfree(irq); - return 0; -} - -/************************************************************************* - * EMU10K1 effect manager - *************************************************************************/ - -static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode, - unsigned int *ptr, - u32 op, u32 r, u32 a, u32 x, u32 y) -{ - u_int32_t *code; - if (snd_BUG_ON(*ptr >= 512)) - return; - code = (u_int32_t __force *)icode->code + (*ptr) * 2; - set_bit(*ptr, icode->code_valid); - code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff); - code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff); - (*ptr)++; -} - -#define OP(icode, ptr, op, r, a, x, y) \ - snd_emu10k1_write_op(icode, ptr, op, r, a, x, y) - -static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode, - unsigned int *ptr, - u32 op, u32 r, u32 a, u32 x, u32 y) -{ - u_int32_t *code; - if (snd_BUG_ON(*ptr >= 1024)) - return; - code = (u_int32_t __force *)icode->code + (*ptr) * 2; - set_bit(*ptr, icode->code_valid); - code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff); - code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff); - (*ptr)++; -} - -#define A_OP(icode, ptr, op, r, a, x, y) \ - snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y) - -static void snd_emu10k1_efx_write(struct snd_emu10k1 *emu, unsigned int pc, unsigned int data) -{ - pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; - snd_emu10k1_ptr_write(emu, pc, 0, data); -} - -unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc) -{ - pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; - return snd_emu10k1_ptr_read(emu, pc, 0); -} - -static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int gpr; - u32 val; - - for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { - if (!test_bit(gpr, icode->gpr_valid)) - continue; - if (get_user(val, &icode->gpr_map[gpr])) - return -EFAULT; - snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val); - } - return 0; -} - -static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int gpr; - u32 val; - - for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { - set_bit(gpr, icode->gpr_valid); - val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0); - if (put_user(val, &icode->gpr_map[gpr])) - return -EFAULT; - } - return 0; -} - -static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int tram; - u32 addr, val; - - for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { - if (!test_bit(tram, icode->tram_valid)) - continue; - if (get_user(val, &icode->tram_data_map[tram]) || - get_user(addr, &icode->tram_addr_map[tram])) - return -EFAULT; - snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val); - if (!emu->audigy) { - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr); - } else { - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12); - snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20); - } - } - return 0; -} - -static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int tram; - u32 val, addr; - - memset(icode->tram_valid, 0, sizeof(icode->tram_valid)); - for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { - set_bit(tram, icode->tram_valid); - val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0); - if (!emu->audigy) { - addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0); - } else { - addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12; - addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20; - } - if (put_user(val, &icode->tram_data_map[tram]) || - put_user(addr, &icode->tram_addr_map[tram])) - return -EFAULT; - } - return 0; -} - -static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - u32 pc, lo, hi; - - for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { - if (!test_bit(pc / 2, icode->code_valid)) - continue; - if (get_user(lo, &icode->code[pc + 0]) || - get_user(hi, &icode->code[pc + 1])) - return -EFAULT; - snd_emu10k1_efx_write(emu, pc + 0, lo); - snd_emu10k1_efx_write(emu, pc + 1, hi); - } - return 0; -} - -static int snd_emu10k1_code_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - u32 pc; - - memset(icode->code_valid, 0, sizeof(icode->code_valid)); - for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { - set_bit(pc / 2, icode->code_valid); - if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0])) - return -EFAULT; - if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1])) - return -EFAULT; - } - return 0; -} - -static struct snd_emu10k1_fx8010_ctl * -snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id) -{ - struct snd_emu10k1_fx8010_ctl *ctl; - struct snd_kcontrol *kcontrol; - - list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { - kcontrol = ctl->kcontrol; - if (kcontrol->id.iface == id->iface && - !strcmp(kcontrol->id.name, id->name) && - kcontrol->id.index == id->index) - return ctl; - } - return NULL; -} - -#define MAX_TLV_SIZE 256 - -static unsigned int *copy_tlv(const unsigned int __user *_tlv) -{ - unsigned int data[2]; - unsigned int *tlv; - - if (!_tlv) - return NULL; - if (copy_from_user(data, _tlv, sizeof(data))) - return NULL; - if (data[1] >= MAX_TLV_SIZE) - return NULL; - tlv = kmalloc(data[1] + sizeof(data), GFP_KERNEL); - if (!tlv) - return NULL; - memcpy(tlv, data, sizeof(data)); - if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { - kfree(tlv); - return NULL; - } - return tlv; -} - -static int copy_gctl(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_control_gpr *gctl, - struct snd_emu10k1_fx8010_control_gpr __user *_gctl, - int idx) -{ - struct snd_emu10k1_fx8010_control_old_gpr __user *octl; - - if (emu->support_tlv) - return copy_from_user(gctl, &_gctl[idx], sizeof(*gctl)); - octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl; - if (copy_from_user(gctl, &octl[idx], sizeof(*octl))) - return -EFAULT; - gctl->tlv = NULL; - return 0; -} - -static int copy_gctl_to_user(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_control_gpr __user *_gctl, - struct snd_emu10k1_fx8010_control_gpr *gctl, - int idx) -{ - struct snd_emu10k1_fx8010_control_old_gpr __user *octl; - - if (emu->support_tlv) - return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl)); - - octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl; - return copy_to_user(&octl[idx], gctl, sizeof(*octl)); -} - -static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i; - struct snd_ctl_elem_id __user *_id; - struct snd_ctl_elem_id id; - struct snd_emu10k1_fx8010_control_gpr *gctl; - int err; - - for (i = 0, _id = icode->gpr_del_controls; - i < icode->gpr_del_control_count; i++, _id++) { - if (copy_from_user(&id, _id, sizeof(id))) - return -EFAULT; - if (snd_emu10k1_look_for_ctl(emu, &id) == NULL) - return -ENOENT; - } - gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); - if (! gctl) - return -ENOMEM; - err = 0; - for (i = 0; i < icode->gpr_add_control_count; i++) { - if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { - err = -EFAULT; - goto __error; - } - if (snd_emu10k1_look_for_ctl(emu, &gctl->id)) - continue; - down_read(&emu->card->controls_rwsem); - if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) { - up_read(&emu->card->controls_rwsem); - err = -EEXIST; - goto __error; - } - up_read(&emu->card->controls_rwsem); - if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && - gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) { - err = -EINVAL; - goto __error; - } - } - for (i = 0; i < icode->gpr_list_control_count; i++) { - /* FIXME: we need to check the WRITE access */ - if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) { - err = -EFAULT; - goto __error; - } - } - __error: - kfree(gctl); - return err; -} - -static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl) -{ - struct snd_emu10k1_fx8010_ctl *ctl; - - ctl = (struct snd_emu10k1_fx8010_ctl *) kctl->private_value; - kctl->private_value = 0; - list_del(&ctl->list); - kfree(ctl); - if (kctl->tlv.p) - kfree(kctl->tlv.p); -} - -static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i, j; - struct snd_emu10k1_fx8010_control_gpr *gctl; - struct snd_emu10k1_fx8010_ctl *ctl, *nctl; - struct snd_kcontrol_new knew; - struct snd_kcontrol *kctl; - struct snd_ctl_elem_value *val; - int err = 0; - - val = kmalloc(sizeof(*val), GFP_KERNEL); - gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); - nctl = kmalloc(sizeof(*nctl), GFP_KERNEL); - if (!val || !gctl || !nctl) { - err = -ENOMEM; - goto __error; - } - - for (i = 0; i < icode->gpr_add_control_count; i++) { - if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { - err = -EFAULT; - goto __error; - } - if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER && - gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) { - err = -EINVAL; - goto __error; - } - if (! gctl->id.name[0]) { - err = -EINVAL; - goto __error; - } - ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id); - memset(&knew, 0, sizeof(knew)); - knew.iface = gctl->id.iface; - knew.name = gctl->id.name; - knew.index = gctl->id.index; - knew.device = gctl->id.device; - knew.subdevice = gctl->id.subdevice; - knew.info = snd_emu10k1_gpr_ctl_info; - knew.tlv.p = copy_tlv(gctl->tlv); - if (knew.tlv.p) - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - knew.get = snd_emu10k1_gpr_ctl_get; - knew.put = snd_emu10k1_gpr_ctl_put; - memset(nctl, 0, sizeof(*nctl)); - nctl->vcount = gctl->vcount; - nctl->count = gctl->count; - for (j = 0; j < 32; j++) { - nctl->gpr[j] = gctl->gpr[j]; - nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */ - val->value.integer.value[j] = gctl->value[j]; - } - nctl->min = gctl->min; - nctl->max = gctl->max; - nctl->translation = gctl->translation; - if (ctl == NULL) { - ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); - if (ctl == NULL) { - err = -ENOMEM; - kfree(knew.tlv.p); - goto __error; - } - knew.private_value = (unsigned long)ctl; - *ctl = *nctl; - if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) { - kfree(ctl); - kfree(knew.tlv.p); - goto __error; - } - kctl->private_free = snd_emu10k1_ctl_private_free; - ctl->kcontrol = kctl; - list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl); - } else { - /* overwrite */ - nctl->list = ctl->list; - nctl->kcontrol = ctl->kcontrol; - *ctl = *nctl; - snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id); - } - snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val); - } - __error: - kfree(nctl); - kfree(gctl); - kfree(val); - return err; -} - -static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i; - struct snd_ctl_elem_id id; - struct snd_ctl_elem_id __user *_id; - struct snd_emu10k1_fx8010_ctl *ctl; - struct snd_card *card = emu->card; - - for (i = 0, _id = icode->gpr_del_controls; - i < icode->gpr_del_control_count; i++, _id++) { - if (copy_from_user(&id, _id, sizeof(id))) - return -EFAULT; - down_write(&card->controls_rwsem); - ctl = snd_emu10k1_look_for_ctl(emu, &id); - if (ctl) - snd_ctl_remove(card, ctl->kcontrol); - up_write(&card->controls_rwsem); - } - return 0; -} - -static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - unsigned int i = 0, j; - unsigned int total = 0; - struct snd_emu10k1_fx8010_control_gpr *gctl; - struct snd_emu10k1_fx8010_ctl *ctl; - struct snd_ctl_elem_id *id; - - gctl = kmalloc(sizeof(*gctl), GFP_KERNEL); - if (! gctl) - return -ENOMEM; - - list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) { - total++; - if (icode->gpr_list_controls && - i < icode->gpr_list_control_count) { - memset(gctl, 0, sizeof(*gctl)); - id = &ctl->kcontrol->id; - gctl->id.iface = id->iface; - strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name)); - gctl->id.index = id->index; - gctl->id.device = id->device; - gctl->id.subdevice = id->subdevice; - gctl->vcount = ctl->vcount; - gctl->count = ctl->count; - for (j = 0; j < 32; j++) { - gctl->gpr[j] = ctl->gpr[j]; - gctl->value[j] = ctl->value[j]; - } - gctl->min = ctl->min; - gctl->max = ctl->max; - gctl->translation = ctl->translation; - if (copy_gctl_to_user(emu, icode->gpr_list_controls, - gctl, i)) { - kfree(gctl); - return -EFAULT; - } - i++; - } - } - icode->gpr_list_control_total = total; - kfree(gctl); - return 0; -} - -static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int err = 0; - - mutex_lock(&emu->fx8010.lock); - if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0) - goto __error; - strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); - /* stop FX processor - this may be dangerous, but it's better to miss - some samples than generate wrong ones - [jk] */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); - /* ok, do the main job */ - if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 || - (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 || - (err = snd_emu10k1_tram_poke(emu, icode)) < 0 || - (err = snd_emu10k1_code_poke(emu, icode)) < 0 || - (err = snd_emu10k1_add_controls(emu, icode)) < 0) - goto __error; - /* start FX processor when the DSP code is updated */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); - __error: - mutex_unlock(&emu->fx8010.lock); - return err; -} - -static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) -{ - int err; - - mutex_lock(&emu->fx8010.lock); - strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name)); - /* ok, do the main job */ - err = snd_emu10k1_gpr_peek(emu, icode); - if (err >= 0) - err = snd_emu10k1_tram_peek(emu, icode); - if (err >= 0) - err = snd_emu10k1_code_peek(emu, icode); - if (err >= 0) - err = snd_emu10k1_list_controls(emu, icode); - mutex_unlock(&emu->fx8010.lock); - return err; -} - -static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_pcm_rec *ipcm) -{ - unsigned int i; - int err = 0; - struct snd_emu10k1_fx8010_pcm *pcm; - - if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) - return -EINVAL; - if (ipcm->channels > 32) - return -EINVAL; - pcm = &emu->fx8010.pcm[ipcm->substream]; - mutex_lock(&emu->fx8010.lock); - spin_lock_irq(&emu->reg_lock); - if (pcm->opened) { - err = -EBUSY; - goto __error; - } - if (ipcm->channels == 0) { /* remove */ - pcm->valid = 0; - } else { - /* FIXME: we need to add universal code to the PCM transfer routine */ - if (ipcm->channels != 2) { - err = -EINVAL; - goto __error; - } - pcm->valid = 1; - pcm->opened = 0; - pcm->channels = ipcm->channels; - pcm->tram_start = ipcm->tram_start; - pcm->buffer_size = ipcm->buffer_size; - pcm->gpr_size = ipcm->gpr_size; - pcm->gpr_count = ipcm->gpr_count; - pcm->gpr_tmpcount = ipcm->gpr_tmpcount; - pcm->gpr_ptr = ipcm->gpr_ptr; - pcm->gpr_trigger = ipcm->gpr_trigger; - pcm->gpr_running = ipcm->gpr_running; - for (i = 0; i < pcm->channels; i++) - pcm->etram[i] = ipcm->etram[i]; - } - __error: - spin_unlock_irq(&emu->reg_lock); - mutex_unlock(&emu->fx8010.lock); - return err; -} - -static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_pcm_rec *ipcm) -{ - unsigned int i; - int err = 0; - struct snd_emu10k1_fx8010_pcm *pcm; - - if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT) - return -EINVAL; - pcm = &emu->fx8010.pcm[ipcm->substream]; - mutex_lock(&emu->fx8010.lock); - spin_lock_irq(&emu->reg_lock); - ipcm->channels = pcm->channels; - ipcm->tram_start = pcm->tram_start; - ipcm->buffer_size = pcm->buffer_size; - ipcm->gpr_size = pcm->gpr_size; - ipcm->gpr_ptr = pcm->gpr_ptr; - ipcm->gpr_count = pcm->gpr_count; - ipcm->gpr_tmpcount = pcm->gpr_tmpcount; - ipcm->gpr_trigger = pcm->gpr_trigger; - ipcm->gpr_running = pcm->gpr_running; - for (i = 0; i < pcm->channels; i++) - ipcm->etram[i] = pcm->etram[i]; - ipcm->res1 = ipcm->res2 = 0; - ipcm->pad = 0; - spin_unlock_irq(&emu->reg_lock); - mutex_unlock(&emu->fx8010.lock); - return err; -} - -#define SND_EMU10K1_GPR_CONTROLS 44 -#define SND_EMU10K1_INPUTS 12 -#define SND_EMU10K1_PLAYBACK_CHANNELS 8 -#define SND_EMU10K1_CAPTURE_CHANNELS 4 - -static void __devinit -snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 1; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - if (high_res_gpr_volume) { - ctl->min = 0; - ctl->max = 0x7fffffff; - ctl->tlv = snd_emu10k1_db_linear; - ctl->translation = EMU10K1_GPR_TRANSLATION_NONE; - } else { - ctl->min = 0; - ctl->max = 100; - ctl->tlv = snd_emu10k1_db_scale1; - ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; - } -} - -static void __devinit -snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 2; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; - if (high_res_gpr_volume) { - ctl->min = 0; - ctl->max = 0x7fffffff; - ctl->tlv = snd_emu10k1_db_linear; - ctl->translation = EMU10K1_GPR_TRANSLATION_NONE; - } else { - ctl->min = 0; - ctl->max = 100; - ctl->tlv = snd_emu10k1_db_scale1; - ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; - } -} - -static void __devinit -snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 1; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - ctl->min = 0; - ctl->max = 1; - ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; -} - -static void __devinit -snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl, - const char *name, int gpr, int defval) -{ - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, name); - ctl->vcount = ctl->count = 2; - ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; - ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; - ctl->min = 0; - ctl->max = 1; - ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; -} - -/* - * Used for emu1010 - conversion from 32-bit capture inputs from HANA - * to 2 x 16-bit registers in audigy - their values are read via DMA. - * Conversion is performed by Audigy DSP instructions of FX8010. - */ -static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( - struct snd_emu10k1_fx8010_code *icode, - u32 *ptr, int tmp, int bit_shifter16, - int reg_in, int reg_out) -{ - A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000); - A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000); - A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2)); - A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000); - A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000); - A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000); - A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2)); - A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000); - return 1; -} - -/* - * initial DSP configuration for Audigy - */ - -static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) -{ - int err, i, z, gpr, nctl; - int bit_shifter16; - const int playback = 10; - const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ - const int stereo_mix = capture + 2; - const int tmp = 0x88; - u32 ptr; - struct snd_emu10k1_fx8010_code *icode = NULL; - struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; - u32 *gpr_map; - mm_segment_t seg; - - if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL || - (icode->gpr_map = (u_int32_t __user *) - kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), - GFP_KERNEL)) == NULL || - (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, - sizeof(*controls), GFP_KERNEL)) == NULL) { - err = -ENOMEM; - goto __err; - } - gpr_map = (u32 __force *)icode->gpr_map; - - icode->tram_data_map = icode->gpr_map + 512; - icode->tram_addr_map = icode->tram_data_map + 256; - icode->code = icode->tram_addr_map + 256; - - /* clear free GPRs */ - for (i = 0; i < 512; i++) - set_bit(i, icode->gpr_valid); - - /* clear TRAM data & address lines */ - for (i = 0; i < 256; i++) - set_bit(i, icode->tram_valid); - - strcpy(icode->name, "Audigy DSP code for ALSA"); - ptr = 0; - nctl = 0; - gpr = stereo_mix + 10; - gpr_map[gpr++] = 0x00007fff; - gpr_map[gpr++] = 0x00008000; - gpr_map[gpr++] = 0x0000ffff; - bit_shifter16 = gpr; - - /* stop FX processor */ - snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); - -#if 1 - /* PCM front Playback Volume (independent from stereo mix) - * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31) - * where gpr contains attenuation from corresponding mixer control - * (snd_emu10k1_init_stereo_control) - */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); - gpr += 2; - - /* PCM Surround Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100); - gpr += 2; - - /* PCM Side Playback (independent from stereo mix) */ - if (emu->card_capabilities->spk71) { - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100); - gpr += 2; - } - - /* PCM Center Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER)); - snd_emu10k1_init_mono_control(&controls[nctl++], "PCM Center Playback Volume", gpr, 100); - gpr++; - - /* PCM LFE Playback (independent from stereo mix) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE)); - snd_emu10k1_init_mono_control(&controls[nctl++], "PCM LFE Playback Volume", gpr, 100); - gpr++; - - /* - * Stereo Mix - */ - /* Wave (PCM) Playback Volume (will be renamed later) */ - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100); - gpr += 2; - - /* Synth Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100); - gpr += 2; - - /* Wave (PCM) Capture */ - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0); - gpr += 2; - - /* Synth Capture */ - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); - gpr += 2; - - /* - * inputs - */ -#define A_ADD_VOLUME_IN(var,vol,input) \ -A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) - - /* emu1212 DSP 0 and DSP 1 Capture */ - if (emu->card_capabilities->emu_model) { - if (emu->card_capabilities->ca0108_chip) { - /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */ - A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp)); - A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp)); - } else { - A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0)); - A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1)); - } - snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0); - gpr += 2; - } - /* AC'97 Playback Volume - used only for mic (renamed later) */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "AMic Playback Volume", gpr, 0); - gpr += 2; - /* AC'97 Capture Volume - used only for mic */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Mic Capture Volume", gpr, 0); - gpr += 2; - - /* mic capture buffer */ - A_OP(icode, &ptr, iINTERP, A_EXTOUT(A_EXTOUT_MIC_CAP), A_EXTIN(A_EXTIN_AC97_L), 0xcd, A_EXTIN(A_EXTIN_AC97_R)); - - /* Audigy CD Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume", - gpr, 0); - gpr += 2; - /* Audigy CD Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume", - gpr, 0); - gpr += 2; - - /* Optical SPDIF Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_OPT_SPDIF_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_OPT_SPDIF_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",PLAYBACK,VOLUME), gpr, 0); - gpr += 2; - /* Optical SPDIF Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_OPT_SPDIF_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_OPT_SPDIF_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",CAPTURE,VOLUME), gpr, 0); - gpr += 2; - - /* Line2 Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume", - gpr, 0); - gpr += 2; - /* Line2 Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume", - gpr, 0); - gpr += 2; - - /* Philips ADC Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_ADC_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_ADC_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Playback Volume", gpr, 0); - gpr += 2; - /* Philips ADC Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_ADC_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_ADC_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Capture Volume", gpr, 0); - gpr += 2; - - /* Aux2 Playback Volume */ - A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L); - A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume", - gpr, 0); - gpr += 2; - /* Aux2 Capture Volume */ - A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L); - A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R); - snd_emu10k1_init_stereo_control(&controls[nctl++], - emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume", - gpr, 0); - gpr += 2; - - /* Stereo Mix Front Playback Volume */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Front Playback Volume", gpr, 100); - gpr += 2; - - /* Stereo Mix Surround Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 0); - gpr += 2; - - /* Stereo Mix Center Playback */ - /* Center = sub = Left/2 + Right/2 */ - A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_GPR(stereo_mix), 0xcd, A_GPR(stereo_mix+1)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp)); - snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0); - gpr++; - - /* Stereo Mix LFE Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp)); - snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0); - gpr++; - - if (emu->card_capabilities->spk71) { - /* Stereo Mix Side Playback */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1)); - snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0); - gpr += 2; - } - - /* - * outputs - */ -#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_00000000, A_C_00000000, A_GPR(src)) -#define A_PUT_STEREO_OUTPUT(out1,out2,src) \ - {A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);} - -#define _A_SWITCH(icode, ptr, dst, src, sw) \ - A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw); -#define A_SWITCH(icode, ptr, dst, src, sw) \ - _A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw)) -#define _A_SWITCH_NEG(icode, ptr, dst, src) \ - A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001); -#define A_SWITCH_NEG(icode, ptr, dst, src) \ - _A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src)) - - - /* - * Process tone control - */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), A_GPR(playback + 0), A_C_00000000, A_C_00000000); /* left */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), A_GPR(playback + 1), A_C_00000000, A_C_00000000); /* right */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), A_GPR(playback + 2), A_C_00000000, A_C_00000000); /* rear left */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */ - if (emu->card_capabilities->spk71) { - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */ - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */ - } - - - ctl = &controls[nctl + 0]; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Bass"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->translation = EMU10K1_GPR_TRANSLATION_BASS; - ctl = &controls[nctl + 1]; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Treble"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE; - -#define BASS_GPR 0x8c -#define TREBLE_GPR 0x96 - - for (z = 0; z < 5; z++) { - int j; - for (j = 0; j < 2; j++) { - controls[nctl + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j; - controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j; - } - } - for (z = 0; z < 4; z++) { /* front/rear/center-lfe/side */ - int j, k, l, d; - for (j = 0; j < 2; j++) { /* left/right */ - k = 0xb0 + (z * 8) + (j * 4); - l = 0xe0 + (z * 8) + (j * 4); - d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j; - - A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(d), A_GPR(BASS_GPR + 0 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(k+1), A_GPR(k), A_GPR(k+1), A_GPR(BASS_GPR + 4 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(k), A_GPR(d), A_GPR(k), A_GPR(BASS_GPR + 2 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(k+3), A_GPR(k+2), A_GPR(k+3), A_GPR(BASS_GPR + 8 + j)); - A_OP(icode, &ptr, iMAC0, A_GPR(k+2), A_GPR_ACCU, A_GPR(k+2), A_GPR(BASS_GPR + 6 + j)); - A_OP(icode, &ptr, iACC3, A_GPR(k+2), A_GPR(k+2), A_GPR(k+2), A_C_00000000); - - A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(k+2), A_GPR(TREBLE_GPR + 0 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(l+1), A_GPR(l), A_GPR(l+1), A_GPR(TREBLE_GPR + 4 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(l), A_GPR(k+2), A_GPR(l), A_GPR(TREBLE_GPR + 2 + j)); - A_OP(icode, &ptr, iMACMV, A_GPR(l+3), A_GPR(l+2), A_GPR(l+3), A_GPR(TREBLE_GPR + 8 + j)); - A_OP(icode, &ptr, iMAC0, A_GPR(l+2), A_GPR_ACCU, A_GPR(l+2), A_GPR(TREBLE_GPR + 6 + j)); - A_OP(icode, &ptr, iMACINT0, A_GPR(l+2), A_C_00000000, A_GPR(l+2), A_C_00000010); - - A_OP(icode, &ptr, iACC3, A_GPR(d), A_GPR(l+2), A_C_00000000, A_C_00000000); - - if (z == 2) /* center */ - break; - } - } - nctl += 2; - -#undef BASS_GPR -#undef TREBLE_GPR - - for (z = 0; z < 8; z++) { - A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0); - A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0); - A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1); - A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); - } - snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0); - gpr += 2; - - /* Master volume (will be renamed later) */ - A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS)); - A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS)); - snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0); - gpr += 2; - - /* analog speakers */ - A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); - if (emu->card_capabilities->spk71) - A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS); - - /* headphone */ - A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); - - /* digital outputs */ - /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ - if (emu->card_capabilities->emu_model) { - /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */ - snd_printk(KERN_INFO "EMU outputs on\n"); - for (z = 0; z < 8; z++) { - if (emu->card_capabilities->ca0108_chip) { - A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); - } else { - A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000); - } - } - } - - /* IEC958 Optical Raw Playback Switch */ - gpr_map[gpr++] = 0; - gpr_map[gpr++] = 0x1008; - gpr_map[gpr++] = 0xffff0000; - for (z = 0; z < 2; z++) { - A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000); - A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001); - A_OP(icode, &ptr, iACC3, A_GPR(tmp + 2), A_C_00000000, A_C_00010000, A_GPR(tmp + 2)); - A_OP(icode, &ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_GPR(gpr - 1), A_C_00000000); - A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z); - A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z); - A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1); - if ((z==1) && (emu->card_capabilities->spdif_bug)) { - /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */ - snd_printk(KERN_INFO "Installing spdif_bug patch: %s\n", emu->card_capabilities->name); - A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); - } else { - A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000); - } - } - snd_emu10k1_init_stereo_onoff_control(controls + nctl++, SNDRV_CTL_NAME_IEC958("Optical Raw ",PLAYBACK,SWITCH), gpr, 0); - gpr += 2; - - A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS); - A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); - - /* ADC buffer */ -#ifdef EMU10K1_CAPTURE_DIGITAL_OUT - A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); -#else - A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture); - A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); -#endif - - if (emu->card_capabilities->emu_model) { - if (emu->card_capabilities->ca0108_chip) { - snd_printk(KERN_INFO "EMU2 inputs on\n"); - for (z = 0; z < 0x10; z++) { - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, - bit_shifter16, - A3_EMU32IN(z), - A_FXBUS2(z*2) ); - } - } else { - snd_printk(KERN_INFO "EMU inputs on\n"); - /* Capture 16 (originally 8) channels of S32_LE sound */ - - /* - printk(KERN_DEBUG "emufx.c: gpr=0x%x, tmp=0x%x\n", - gpr, tmp); - */ - /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ - /* A_P16VIN(0) is delayed by one sample, - * so all other A_P16VIN channels will need to also be delayed - */ - /* Left ADC in. 1 of 2 */ - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); - /* Right ADC in 1 of 2 */ - gpr_map[gpr++] = 0x00000000; - /* Delaying by one sample: instead of copying the input - * value A_P16VIN to output A_FXBUS2 as in the first channel, - * we use an auxiliary register, delaying the value by one - * sample - */ - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000); - /* For 96kHz mode */ - /* Left ADC in. 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000); - /* Right ADC in 2 of 2 */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); - /* Pavel Hofman - we still have voices, A_FXBUS2s, and - * A_P16VINs available - - * let's add 8 more capture channels - total of 16 - */ - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x10)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x12)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x14)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x16)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x18)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1a)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1c)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), - A_C_00000000, A_C_00000000); - gpr_map[gpr++] = 0x00000000; - snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, - bit_shifter16, - A_GPR(gpr - 1), - A_FXBUS2(0x1e)); - A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), - A_C_00000000, A_C_00000000); - } - -#if 0 - for (z = 4; z < 8; z++) { - A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000); - } - for (z = 0xc; z < 0x10; z++) { - A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000); - } -#endif - } else { - /* EFX capture - capture the 16 EXTINs */ - /* Capture 16 channels of S16_LE sound */ - for (z = 0; z < 16; z++) { - A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z)); - } - } - -#endif /* JCD test */ - /* - * ok, set up done.. - */ - - if (gpr > tmp) { - snd_BUG(); - err = -EIO; - goto __err; - } - /* clear remaining instruction memory */ - while (ptr < 0x400) - A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0); - - seg = snd_enter_user(); - icode->gpr_add_control_count = nctl; - icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; - emu->support_tlv = 1; /* support TLV */ - err = snd_emu10k1_icode_poke(emu, icode); - emu->support_tlv = 0; /* clear again */ - snd_leave_user(seg); - - __err: - kfree(controls); - if (icode != NULL) { - kfree((void __force *)icode->gpr_map); - kfree(icode); - } - return err; -} - - -/* - * initial DSP configuration for Emu10k1 - */ - -/* when volume = max, then copy only to avoid volume modification */ -/* with iMAC0 (negative values) */ -static void __devinit _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) -{ - OP(icode, ptr, iMAC0, dst, C_00000000, src, vol); - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001); - OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000); -} -static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) -{ - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001); - OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); - OP(icode, ptr, iMAC0, dst, dst, src, vol); -} -static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol) -{ - OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff); - OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000); - OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001); - OP(icode, ptr, iMAC0, dst, C_00000000, src, vol); -} - -#define VOLUME(icode, ptr, dst, src, vol) \ - _volume(icode, ptr, GPR(dst), GPR(src), GPR(vol)) -#define VOLUME_IN(icode, ptr, dst, src, vol) \ - _volume(icode, ptr, GPR(dst), EXTIN(src), GPR(vol)) -#define VOLUME_ADD(icode, ptr, dst, src, vol) \ - _volume_add(icode, ptr, GPR(dst), GPR(src), GPR(vol)) -#define VOLUME_ADDIN(icode, ptr, dst, src, vol) \ - _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol)) -#define VOLUME_OUT(icode, ptr, dst, src, vol) \ - _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol)) -#define _SWITCH(icode, ptr, dst, src, sw) \ - OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw); -#define SWITCH(icode, ptr, dst, src, sw) \ - _SWITCH(icode, ptr, GPR(dst), GPR(src), GPR(sw)) -#define SWITCH_IN(icode, ptr, dst, src, sw) \ - _SWITCH(icode, ptr, GPR(dst), EXTIN(src), GPR(sw)) -#define _SWITCH_NEG(icode, ptr, dst, src) \ - OP((icode), ptr, iANDXOR, dst, src, C_00000001, C_00000001); -#define SWITCH_NEG(icode, ptr, dst, src) \ - _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src)) - - -static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) -{ - int err, i, z, gpr, tmp, playback, capture; - u32 ptr; - struct snd_emu10k1_fx8010_code *icode; - struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL; - struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; - u32 *gpr_map; - mm_segment_t seg; - - if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL) - return -ENOMEM; - if ((icode->gpr_map = (u_int32_t __user *) - kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), - GFP_KERNEL)) == NULL || - (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, - sizeof(struct snd_emu10k1_fx8010_control_gpr), - GFP_KERNEL)) == NULL || - (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) { - err = -ENOMEM; - goto __err; - } - gpr_map = (u32 __force *)icode->gpr_map; - - icode->tram_data_map = icode->gpr_map + 256; - icode->tram_addr_map = icode->tram_data_map + 160; - icode->code = icode->tram_addr_map + 160; - - /* clear free GPRs */ - for (i = 0; i < 256; i++) - set_bit(i, icode->gpr_valid); - - /* clear TRAM data & address lines */ - for (i = 0; i < 160; i++) - set_bit(i, icode->tram_valid); - - strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela"); - ptr = 0; i = 0; - /* we have 12 inputs */ - playback = SND_EMU10K1_INPUTS; - /* we have 6 playback channels and tone control doubles */ - capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); - gpr = capture + SND_EMU10K1_CAPTURE_CHANNELS; - tmp = 0x88; /* we need 4 temporary GPR */ - /* from 0x8c to 0xff is the area for tone control */ - - /* stop FX processor */ - snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP); - - /* - * Process FX Buses - */ - OP(icode, &ptr, iMACINT0, GPR(0), C_00000000, FXBUS(FXBUS_PCM_LEFT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(1), C_00000000, FXBUS(FXBUS_PCM_RIGHT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(2), C_00000000, FXBUS(FXBUS_MIDI_LEFT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(3), C_00000000, FXBUS(FXBUS_MIDI_RIGHT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(4), C_00000000, FXBUS(FXBUS_PCM_LEFT_REAR), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(5), C_00000000, FXBUS(FXBUS_PCM_RIGHT_REAR), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(6), C_00000000, FXBUS(FXBUS_PCM_CENTER), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */ - OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */ - OP(icode, &ptr, iMACINT0, GPR(10), C_00000000, FXBUS(FXBUS_PCM_LEFT_FRONT), C_00000004); - OP(icode, &ptr, iMACINT0, GPR(11), C_00000000, FXBUS(FXBUS_PCM_RIGHT_FRONT), C_00000004); - - /* Raw S/PDIF PCM */ - ipcm->substream = 0; - ipcm->channels = 2; - ipcm->tram_start = 0; - ipcm->buffer_size = (64 * 1024) / 2; - ipcm->gpr_size = gpr++; - ipcm->gpr_ptr = gpr++; - ipcm->gpr_count = gpr++; - ipcm->gpr_tmpcount = gpr++; - ipcm->gpr_trigger = gpr++; - ipcm->gpr_running = gpr++; - ipcm->etram[0] = 0; - ipcm->etram[1] = 1; - - gpr_map[gpr + 0] = 0xfffff000; - gpr_map[gpr + 1] = 0xffff0000; - gpr_map[gpr + 2] = 0x70000000; - gpr_map[gpr + 3] = 0x00000007; - gpr_map[gpr + 4] = 0x001f << 11; - gpr_map[gpr + 5] = 0x001c << 11; - gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */ - gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */ - gpr_map[gpr + 8] = 0x2000000 + (2<<11); - gpr_map[gpr + 9] = 0x4000000 + (2<<11); - gpr_map[gpr + 10] = 1<<11; - gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */ - gpr_map[gpr + 12] = 0; - - /* if the trigger flag is not set, skip */ - /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000); - /* 01: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_ZERO, GPR(gpr + 6)); - /* if the running flag is set, we're running */ - /* 02: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_running), C_00000000, C_00000000); - /* 03: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000004); - /* wait until ((GPR_DBAC>>11) & 0x1f) == 0x1c) */ - /* 04: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), GPR_DBAC, GPR(gpr + 4), C_00000000); - /* 05: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(gpr + 5)); - /* 06: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 7)); - /* 07: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000010, C_00000001, C_00000000); - - /* 08: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000000, C_00000001); - /* 09: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), GPR(gpr + 12), C_ffffffff, C_00000000); - /* 0a: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 11)); - /* 0b: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000001, C_00000000, C_00000000); - - /* 0c: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[0]), GPR(gpr + 0), C_00000000); - /* 0d: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000); - /* 0e: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2)); - /* 0f: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001); - /* 10: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(8), GPR(gpr + 1), GPR(gpr + 2)); - - /* 11: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[1]), GPR(gpr + 0), C_00000000); - /* 12: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000); - /* 13: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2)); - /* 14: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001); - /* 15: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(9), GPR(gpr + 1), GPR(gpr + 2)); - - /* 16: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(ipcm->gpr_ptr), C_00000001, C_00000000); - /* 17: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(ipcm->gpr_size)); - /* 18: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_MINUS, C_00000001); - /* 19: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), C_00000000, C_00000000, C_00000000); - /* 1a: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_ptr), GPR(tmp + 0), C_00000000, C_00000000); - - /* 1b: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_tmpcount), C_ffffffff, C_00000000); - /* 1c: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002); - /* 1d: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_count), C_00000000, C_00000000); - /* 1e: */ OP(icode, &ptr, iACC3, GPR_IRQ, C_80000000, C_00000000, C_00000000); - /* 1f: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000001, C_00010000); - - /* 20: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00010000, C_00000001); - /* 21: */ OP(icode, &ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000002); - - /* 22: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[0]), GPR(gpr + 8), GPR_DBAC, C_ffffffff); - /* 23: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[1]), GPR(gpr + 9), GPR_DBAC, C_ffffffff); - - /* 24: */ - gpr += 13; - - /* Wave Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME(icode, &ptr, playback + z, z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Wave Playback Volume", gpr, 100); - gpr += 2; - - /* Wave Surround Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME(icode, &ptr, playback + 2 + z, z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Wave Surround Playback Volume", gpr, 0); - gpr += 2; - - /* Wave Center/LFE Playback Volume */ - OP(icode, &ptr, iACC3, GPR(tmp + 0), FXBUS(FXBUS_PCM_LEFT), FXBUS(FXBUS_PCM_RIGHT), C_00000000); - OP(icode, &ptr, iMACINT0, GPR(tmp + 0), C_00000000, GPR(tmp + 0), C_00000002); - VOLUME(icode, &ptr, playback + 4, tmp + 0, gpr); - snd_emu10k1_init_mono_control(controls + i++, "Wave Center Playback Volume", gpr++, 0); - VOLUME(icode, &ptr, playback + 5, tmp + 0, gpr); - snd_emu10k1_init_mono_control(controls + i++, "Wave LFE Playback Volume", gpr++, 0); - - /* Wave Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, z, gpr + 2 + z); - VOLUME(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Wave Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0); - gpr += 4; - - /* Synth Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100); - gpr += 2; - - /* Synth Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0); - gpr += 4; - - /* Surround Digital Playback Volume (renamed later without Digital) */ - for (z = 0; z < 2; z++) - VOLUME_ADD(icode, &ptr, playback + 2 + z, 4 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Surround Digital Playback Volume", gpr, 100); - gpr += 2; - - /* Surround Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, 4 + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Surround Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Surround Capture Switch", gpr + 2, 0); - gpr += 4; - - /* Center Playback Volume (renamed later without Digital) */ - VOLUME_ADD(icode, &ptr, playback + 4, 6, gpr); - snd_emu10k1_init_mono_control(controls + i++, "Center Digital Playback Volume", gpr++, 100); - - /* LFE Playback Volume + Switch (renamed later without Digital) */ - VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr); - snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100); - - /* Front Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADD(icode, &ptr, playback + z, 10 + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Front Playback Volume", gpr, 100); - gpr += 2; - - /* Front Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, 10 + z, gpr + 2); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Front Capture Volume", gpr, 0); - snd_emu10k1_init_mono_onoff_control(controls + i++, "Front Capture Switch", gpr + 2, 0); - gpr += 3; - - /* - * Process inputs - */ - - if (emu->fx8010.extin_mask & ((1<<EXTIN_AC97_L)|(1<<EXTIN_AC97_R))) { - /* AC'97 Playback Volume */ - VOLUME_ADDIN(icode, &ptr, playback + 0, EXTIN_AC97_L, gpr); gpr++; - VOLUME_ADDIN(icode, &ptr, playback + 1, EXTIN_AC97_R, gpr); gpr++; - snd_emu10k1_init_stereo_control(controls + i++, "AC97 Playback Volume", gpr-2, 0); - /* AC'97 Capture Volume */ - VOLUME_ADDIN(icode, &ptr, capture + 0, EXTIN_AC97_L, gpr); gpr++; - VOLUME_ADDIN(icode, &ptr, capture + 1, EXTIN_AC97_R, gpr); gpr++; - snd_emu10k1_init_stereo_control(controls + i++, "AC97 Capture Volume", gpr-2, 100); - } - - if (emu->fx8010.extin_mask & ((1<<EXTIN_SPDIF_CD_L)|(1<<EXTIN_SPDIF_CD_R))) { - /* IEC958 TTL Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_SPDIF_CD_L + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",PLAYBACK,VOLUME), gpr, 0); - gpr += 2; - - /* IEC958 TTL Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_SPDIF_CD_L + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,VOLUME), gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,SWITCH), gpr + 2, 0); - gpr += 4; - } - - if (emu->fx8010.extin_mask & ((1<<EXTIN_ZOOM_L)|(1<<EXTIN_ZOOM_R))) { - /* Zoom Video Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_ZOOM_L + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Playback Volume", gpr, 0); - gpr += 2; - - /* Zoom Video Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_ZOOM_L + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Zoom Video Capture Switch", gpr + 2, 0); - gpr += 4; - } - - if (emu->fx8010.extin_mask & ((1<<EXTIN_TOSLINK_L)|(1<<EXTIN_TOSLINK_R))) { - /* IEC958 Optical Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_TOSLINK_L + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",PLAYBACK,VOLUME), gpr, 0); - gpr += 2; - - /* IEC958 Optical Capture Volume */ - for (z = 0; z < 2; z++) { - SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_TOSLINK_L + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,VOLUME), gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,SWITCH), gpr + 2, 0); - gpr += 4; - } - - if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE1_L)|(1<<EXTIN_LINE1_R))) { - /* Line LiveDrive Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE1_L + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Playback Volume", gpr, 0); - gpr += 2; - - /* Line LiveDrive Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE1_L + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Capture Volume", gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line LiveDrive Capture Switch", gpr + 2, 0); - gpr += 4; - } - - if (emu->fx8010.extin_mask & ((1<<EXTIN_COAX_SPDIF_L)|(1<<EXTIN_COAX_SPDIF_R))) { - /* IEC958 Coax Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_COAX_SPDIF_L + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",PLAYBACK,VOLUME), gpr, 0); - gpr += 2; - - /* IEC958 Coax Capture Volume + Switch */ - for (z = 0; z < 2; z++) { - SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_COAX_SPDIF_L + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,VOLUME), gpr, 0); - snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,SWITCH), gpr + 2, 0); - gpr += 4; - } - - if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE2_L)|(1<<EXTIN_LINE2_R))) { - /* Line LiveDrive Playback Volume */ - for (z = 0; z < 2; z++) - VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE2_L + z, gpr + z); - snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Playback Volume", gpr, 0); - controls[i-1].id.index = 1; - gpr += 2; - - /* Line LiveDrive Capture Volume */ - for (z = 0; z < 2; z++) { - SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE2_L + z, gpr + 2 + z); - VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z); - } - snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Capture Volume", gpr, 0); - controls[i-1].id.index = 1; - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line2 LiveDrive Capture Switch", gpr + 2, 0); - controls[i-1].id.index = 1; - gpr += 4; - } - - /* - * Process tone control - */ - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), GPR(playback + 0), C_00000000, C_00000000); /* left */ - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), GPR(playback + 1), C_00000000, C_00000000); /* right */ - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), GPR(playback + 2), C_00000000, C_00000000); /* rear left */ - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), GPR(playback + 3), C_00000000, C_00000000); /* rear right */ - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), GPR(playback + 4), C_00000000, C_00000000); /* center */ - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), GPR(playback + 5), C_00000000, C_00000000); /* LFE */ - - ctl = &controls[i + 0]; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Bass"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->tlv = snd_emu10k1_bass_treble_db_scale; - ctl->translation = EMU10K1_GPR_TRANSLATION_BASS; - ctl = &controls[i + 1]; - ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(ctl->id.name, "Tone Control - Treble"); - ctl->vcount = 2; - ctl->count = 10; - ctl->min = 0; - ctl->max = 40; - ctl->value[0] = ctl->value[1] = 20; - ctl->tlv = snd_emu10k1_bass_treble_db_scale; - ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE; - -#define BASS_GPR 0x8c -#define TREBLE_GPR 0x96 - - for (z = 0; z < 5; z++) { - int j; - for (j = 0; j < 2; j++) { - controls[i + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j; - controls[i + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j; - } - } - for (z = 0; z < 3; z++) { /* front/rear/center-lfe */ - int j, k, l, d; - for (j = 0; j < 2; j++) { /* left/right */ - k = 0xa0 + (z * 8) + (j * 4); - l = 0xd0 + (z * 8) + (j * 4); - d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j; - - OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(d), GPR(BASS_GPR + 0 + j)); - OP(icode, &ptr, iMACMV, GPR(k+1), GPR(k), GPR(k+1), GPR(BASS_GPR + 4 + j)); - OP(icode, &ptr, iMACMV, GPR(k), GPR(d), GPR(k), GPR(BASS_GPR + 2 + j)); - OP(icode, &ptr, iMACMV, GPR(k+3), GPR(k+2), GPR(k+3), GPR(BASS_GPR + 8 + j)); - OP(icode, &ptr, iMAC0, GPR(k+2), GPR_ACCU, GPR(k+2), GPR(BASS_GPR + 6 + j)); - OP(icode, &ptr, iACC3, GPR(k+2), GPR(k+2), GPR(k+2), C_00000000); - - OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(k+2), GPR(TREBLE_GPR + 0 + j)); - OP(icode, &ptr, iMACMV, GPR(l+1), GPR(l), GPR(l+1), GPR(TREBLE_GPR + 4 + j)); - OP(icode, &ptr, iMACMV, GPR(l), GPR(k+2), GPR(l), GPR(TREBLE_GPR + 2 + j)); - OP(icode, &ptr, iMACMV, GPR(l+3), GPR(l+2), GPR(l+3), GPR(TREBLE_GPR + 8 + j)); - OP(icode, &ptr, iMAC0, GPR(l+2), GPR_ACCU, GPR(l+2), GPR(TREBLE_GPR + 6 + j)); - OP(icode, &ptr, iMACINT0, GPR(l+2), C_00000000, GPR(l+2), C_00000010); - - OP(icode, &ptr, iACC3, GPR(d), GPR(l+2), C_00000000, C_00000000); - - if (z == 2) /* center */ - break; - } - } - i += 2; - -#undef BASS_GPR -#undef TREBLE_GPR - - for (z = 0; z < 6; z++) { - SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0); - SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0); - SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1); - OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000); - } - snd_emu10k1_init_stereo_onoff_control(controls + i++, "Tone Control - Switch", gpr, 0); - gpr += 2; - - /* - * Process outputs - */ - if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_L)|(1<<EXTOUT_AC97_R))) { - /* AC'97 Playback Volume */ - - for (z = 0; z < 2; z++) - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), C_00000000, C_00000000); - } - - if (emu->fx8010.extout_mask & ((1<<EXTOUT_TOSLINK_L)|(1<<EXTOUT_TOSLINK_R))) { - /* IEC958 Optical Raw Playback Switch */ - - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, 8 + z, gpr + z); - SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z); - SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1); - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_TOSLINK_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000); -#ifdef EMU10K1_CAPTURE_DIGITAL_OUT - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000); -#endif - } - - snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("Optical Raw ",PLAYBACK,SWITCH), gpr, 0); - gpr += 2; - } - - if (emu->fx8010.extout_mask & ((1<<EXTOUT_HEADPHONE_L)|(1<<EXTOUT_HEADPHONE_R))) { - /* Headphone Playback Volume */ - - for (z = 0; z < 2; z++) { - SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4 + z, gpr + 2 + z); - SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 2 + z); - SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1); - OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(tmp + 0), GPR(tmp + 1), C_00000000); - VOLUME_OUT(icode, &ptr, EXTOUT_HEADPHONE_L + z, tmp + 0, gpr + z); - } - - snd_emu10k1_init_stereo_control(controls + i++, "Headphone Playback Volume", gpr + 0, 0); - controls[i-1].id.index = 1; /* AC'97 can have also Headphone control */ - snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone Center Playback Switch", gpr + 2, 0); - controls[i-1].id.index = 1; - snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone LFE Playback Switch", gpr + 3, 0); - controls[i-1].id.index = 1; - - gpr += 4; - } - - if (emu->fx8010.extout_mask & ((1<<EXTOUT_REAR_L)|(1<<EXTOUT_REAR_R))) - for (z = 0; z < 2; z++) - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000); - - if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_REAR_L)|(1<<EXTOUT_AC97_REAR_R))) - for (z = 0; z < 2; z++) - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000); - - if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_CENTER)) { -#ifndef EMU10K1_CENTER_LFE_FROM_FRONT - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000); - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000); -#else - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000); - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000); -#endif - } - - if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_LFE)) { -#ifndef EMU10K1_CENTER_LFE_FROM_FRONT - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000); - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000); -#else - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000); - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000); -#endif - } - -#ifndef EMU10K1_CAPTURE_DIGITAL_OUT - for (z = 0; z < 2; z++) - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(capture + z), C_00000000, C_00000000); -#endif - - if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP)) - OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000); - - /* EFX capture - capture the 16 EXTINS */ - if (emu->card_capabilities->sblive51) { - /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER - * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording. - * - * Since only 14 of the 16 EXTINs are used, this is not a big problem. - * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture - * 0 and 3, then the rest of the EXTINs to the corresponding FX capture - * channel. Multitrack recorders will still see the center/lfe output signal - * on the second and third channels. - */ - OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0)); - OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1)); - OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2)); - OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3)); - for (z = 4; z < 14; z++) - OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); - } else { - for (z = 0; z < 16; z++) - OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); - } - - - if (gpr > tmp) { - snd_BUG(); - err = -EIO; - goto __err; - } - if (i > SND_EMU10K1_GPR_CONTROLS) { - snd_BUG(); - err = -EIO; - goto __err; - } - - /* clear remaining instruction memory */ - while (ptr < 0x200) - OP(icode, &ptr, iACC3, C_00000000, C_00000000, C_00000000, C_00000000); - - if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0) - goto __err; - seg = snd_enter_user(); - icode->gpr_add_control_count = i; - icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; - emu->support_tlv = 1; /* support TLV */ - err = snd_emu10k1_icode_poke(emu, icode); - emu->support_tlv = 0; /* clear again */ - snd_leave_user(seg); - if (err >= 0) - err = snd_emu10k1_ipcm_poke(emu, ipcm); - __err: - kfree(ipcm); - kfree(controls); - if (icode != NULL) { - kfree((void __force *)icode->gpr_map); - kfree(icode); - } - return err; -} - -int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu) -{ - spin_lock_init(&emu->fx8010.irq_lock); - INIT_LIST_HEAD(&emu->fx8010.gpr_ctl); - if (emu->audigy) - return _snd_emu10k1_audigy_init_efx(emu); - else - return _snd_emu10k1_init_efx(emu); -} - -void snd_emu10k1_free_efx(struct snd_emu10k1 *emu) -{ - /* stop processor */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP); -} - -#if 0 /* FIXME: who use them? */ -int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output) -{ - if (output < 0 || output >= 6) - return -EINVAL; - snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1); - return 0; -} - -int snd_emu10k1_fx8010_tone_control_deactivate(struct snd_emu10k1 *emu, int output) -{ - if (output < 0 || output >= 6) - return -EINVAL; - snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0); - return 0; -} -#endif - -int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size) -{ - u8 size_reg = 0; - - /* size is in samples */ - if (size != 0) { - size = (size - 1) >> 13; - - while (size) { - size >>= 1; - size_reg++; - } - size = 0x2000 << size_reg; - } - if ((emu->fx8010.etram_pages.bytes / 2) == size) - return 0; - spin_lock_irq(&emu->emu_lock); - outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); - spin_unlock_irq(&emu->emu_lock); - snd_emu10k1_ptr_write(emu, TCB, 0, 0); - snd_emu10k1_ptr_write(emu, TCBS, 0, 0); - if (emu->fx8010.etram_pages.area != NULL) { - snd_dma_free_pages(&emu->fx8010.etram_pages); - emu->fx8010.etram_pages.area = NULL; - emu->fx8010.etram_pages.bytes = 0; - } - - if (size > 0) { - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), - size * 2, &emu->fx8010.etram_pages) < 0) - return -ENOMEM; - memset(emu->fx8010.etram_pages.area, 0, size * 2); - snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr); - snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); - spin_lock_irq(&emu->emu_lock); - outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); - spin_unlock_irq(&emu->emu_lock); - } - - return 0; -} - -static int snd_emu10k1_fx8010_open(struct snd_hwdep * hw, struct file *file) -{ - return 0; -} - -static void copy_string(char *dst, char *src, char *null, int idx) -{ - if (src == NULL) - sprintf(dst, "%s %02X", null, idx); - else - strcpy(dst, src); -} - -static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_info *info) -{ - char **fxbus, **extin, **extout; - unsigned short fxbus_mask, extin_mask, extout_mask; - int res; - - info->internal_tram_size = emu->fx8010.itram_size; - info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; - fxbus = fxbuses; - extin = emu->audigy ? audigy_ins : creative_ins; - extout = emu->audigy ? audigy_outs : creative_outs; - fxbus_mask = emu->fx8010.fxbus_mask; - extin_mask = emu->fx8010.extin_mask; - extout_mask = emu->fx8010.extout_mask; - for (res = 0; res < 16; res++, fxbus++, extin++, extout++) { - copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res); - copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res); - copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); - } - for (res = 16; res < 32; res++, extout++) - copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res); - info->gpr_controls = emu->fx8010.gpr_count; -} - -static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_emu10k1 *emu = hw->private_data; - struct snd_emu10k1_fx8010_info *info; - struct snd_emu10k1_fx8010_code *icode; - struct snd_emu10k1_fx8010_pcm_rec *ipcm; - unsigned int addr; - void __user *argp = (void __user *)arg; - int res; - - switch (cmd) { - case SNDRV_EMU10K1_IOCTL_PVERSION: - emu->support_tlv = 1; - return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp); - case SNDRV_EMU10K1_IOCTL_INFO: - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - snd_emu10k1_fx8010_info(emu, info); - if (copy_to_user(argp, info, sizeof(*info))) { - kfree(info); - return -EFAULT; - } - kfree(info); - return 0; - case SNDRV_EMU10K1_IOCTL_CODE_POKE: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - icode = memdup_user(argp, sizeof(*icode)); - if (IS_ERR(icode)) - return PTR_ERR(icode); - res = snd_emu10k1_icode_poke(emu, icode); - kfree(icode); - return res; - case SNDRV_EMU10K1_IOCTL_CODE_PEEK: - icode = memdup_user(argp, sizeof(*icode)); - if (IS_ERR(icode)) - return PTR_ERR(icode); - res = snd_emu10k1_icode_peek(emu, icode); - if (res == 0 && copy_to_user(argp, icode, sizeof(*icode))) { - kfree(icode); - return -EFAULT; - } - kfree(icode); - return res; - case SNDRV_EMU10K1_IOCTL_PCM_POKE: - ipcm = memdup_user(argp, sizeof(*ipcm)); - if (IS_ERR(ipcm)) - return PTR_ERR(ipcm); - res = snd_emu10k1_ipcm_poke(emu, ipcm); - kfree(ipcm); - return res; - case SNDRV_EMU10K1_IOCTL_PCM_PEEK: - ipcm = memdup_user(argp, sizeof(*ipcm)); - if (IS_ERR(ipcm)) - return PTR_ERR(ipcm); - res = snd_emu10k1_ipcm_peek(emu, ipcm); - if (res == 0 && copy_to_user(argp, ipcm, sizeof(*ipcm))) { - kfree(ipcm); - return -EFAULT; - } - kfree(ipcm); - return res; - case SNDRV_EMU10K1_IOCTL_TRAM_SETUP: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (get_user(addr, (unsigned int __user *)argp)) - return -EFAULT; - mutex_lock(&emu->fx8010.lock); - res = snd_emu10k1_fx8010_tram_setup(emu, addr); - mutex_unlock(&emu->fx8010.lock); - return res; - case SNDRV_EMU10K1_IOCTL_STOP: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP); - return 0; - case SNDRV_EMU10K1_IOCTL_CONTINUE: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = 0); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = 0); - return 0; - case SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_ZC); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_ZC); - udelay(10); - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); - return 0; - case SNDRV_EMU10K1_IOCTL_SINGLE_STEP: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (get_user(addr, (unsigned int __user *)argp)) - return -EFAULT; - if (addr > 0x1ff) - return -EINVAL; - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr); - udelay(10); - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr); - return 0; - case SNDRV_EMU10K1_IOCTL_DBG_READ: - if (emu->audigy) - addr = snd_emu10k1_ptr_read(emu, A_DBG, 0); - else - addr = snd_emu10k1_ptr_read(emu, DBG, 0); - if (put_user(addr, (unsigned int __user *)argp)) - return -EFAULT; - return 0; - } - return -ENOTTY; -} - -static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file) -{ - return 0; -} - -int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep) -{ - struct snd_hwdep *hw; - int err; - - if (rhwdep) - *rhwdep = NULL; - if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0) - return err; - strcpy(hw->name, "EMU10K1 (FX8010)"); - hw->iface = SNDRV_HWDEP_IFACE_EMU10K1; - hw->ops.open = snd_emu10k1_fx8010_open; - hw->ops.ioctl = snd_emu10k1_fx8010_ioctl; - hw->ops.release = snd_emu10k1_fx8010_release; - hw->private_data = emu; - if (rhwdep) - *rhwdep = hw; - return 0; -} - -#ifdef CONFIG_PM -int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu) -{ - int len; - - len = emu->audigy ? 0x200 : 0x100; - emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL); - if (! emu->saved_gpr) - return -ENOMEM; - len = emu->audigy ? 0x100 : 0xa0; - emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL); - emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL); - if (! emu->tram_val_saved || ! emu->tram_addr_saved) - return -ENOMEM; - len = emu->audigy ? 2 * 1024 : 2 * 512; - emu->saved_icode = vmalloc(len * 4); - if (! emu->saved_icode) - return -ENOMEM; - return 0; -} - -void snd_emu10k1_efx_free_pm_buffer(struct snd_emu10k1 *emu) -{ - kfree(emu->saved_gpr); - kfree(emu->tram_val_saved); - kfree(emu->tram_addr_saved); - vfree(emu->saved_icode); -} - -/* - * save/restore GPR, TRAM and codes - */ -void snd_emu10k1_efx_suspend(struct snd_emu10k1 *emu) -{ - int i, len; - - len = emu->audigy ? 0x200 : 0x100; - for (i = 0; i < len; i++) - emu->saved_gpr[i] = snd_emu10k1_ptr_read(emu, emu->gpr_base + i, 0); - - len = emu->audigy ? 0x100 : 0xa0; - for (i = 0; i < len; i++) { - emu->tram_val_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + i, 0); - emu->tram_addr_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + i, 0); - if (emu->audigy) { - emu->tram_addr_saved[i] >>= 12; - emu->tram_addr_saved[i] |= - snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + i, 0) << 20; - } - } - - len = emu->audigy ? 2 * 1024 : 2 * 512; - for (i = 0; i < len; i++) - emu->saved_icode[i] = snd_emu10k1_efx_read(emu, i); -} - -void snd_emu10k1_efx_resume(struct snd_emu10k1 *emu) -{ - int i, len; - - /* set up TRAM */ - if (emu->fx8010.etram_pages.bytes > 0) { - unsigned size, size_reg = 0; - size = emu->fx8010.etram_pages.bytes / 2; - size = (size - 1) >> 13; - while (size) { - size >>= 1; - size_reg++; - } - outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG); - snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr); - snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg); - outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG); - } - - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); - - len = emu->audigy ? 0x200 : 0x100; - for (i = 0; i < len; i++) - snd_emu10k1_ptr_write(emu, emu->gpr_base + i, 0, emu->saved_gpr[i]); - - len = emu->audigy ? 0x100 : 0xa0; - for (i = 0; i < len; i++) { - snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + i, 0, - emu->tram_val_saved[i]); - if (! emu->audigy) - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, - emu->tram_addr_saved[i]); - else { - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, - emu->tram_addr_saved[i] << 12); - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0, - emu->tram_addr_saved[i] >> 20); - } - } - - len = emu->audigy ? 2 * 1024 : 2 * 512; - for (i = 0; i < len; i++) - snd_emu10k1_efx_write(emu, i, emu->saved_icode[i]); - - /* start FX processor when the DSP code is updated */ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg); - else - snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg); -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c b/ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c deleted file mode 100644 index 9d890a5a..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c +++ /dev/null @@ -1,2143 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, - * Takashi Iwai <tiwai@suse.de> - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips / mixer routines - * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> - * - * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> - * Added EMU 1010 support. - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/time.h> -#include <linux/init.h> -#include <sound/core.h> -#include <sound/emu10k1.h> -#include <linux/delay.h> -#include <sound/tlv.h> - -#include "p17v.h" - -#define AC97_ID_STAC9758 0x83847658 - -static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */ - -static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; - return 0; -} - -static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - unsigned long flags; - - /* Limit: emu->spdif_bits */ - if (idx >= 3) - return -EINVAL; - spin_lock_irqsave(&emu->reg_lock, flags); - ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; - ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.iec958.status[0] = 0xff; - ucontrol->value.iec958.status[1] = 0xff; - ucontrol->value.iec958.status[2] = 0xff; - ucontrol->value.iec958.status[3] = 0xff; - return 0; -} - -/* - * Items labels in enum mixer controls assigning source data to - * each destination - */ -static char *emu1010_src_texts[] = { - "Silence", - "Dock Mic A", - "Dock Mic B", - "Dock ADC1 Left", - "Dock ADC1 Right", - "Dock ADC2 Left", - "Dock ADC2 Right", - "Dock ADC3 Left", - "Dock ADC3 Right", - "0202 ADC Left", - "0202 ADC Right", - "0202 SPDIF Left", - "0202 SPDIF Right", - "ADAT 0", - "ADAT 1", - "ADAT 2", - "ADAT 3", - "ADAT 4", - "ADAT 5", - "ADAT 6", - "ADAT 7", - "DSP 0", - "DSP 1", - "DSP 2", - "DSP 3", - "DSP 4", - "DSP 5", - "DSP 6", - "DSP 7", - "DSP 8", - "DSP 9", - "DSP 10", - "DSP 11", - "DSP 12", - "DSP 13", - "DSP 14", - "DSP 15", - "DSP 16", - "DSP 17", - "DSP 18", - "DSP 19", - "DSP 20", - "DSP 21", - "DSP 22", - "DSP 23", - "DSP 24", - "DSP 25", - "DSP 26", - "DSP 27", - "DSP 28", - "DSP 29", - "DSP 30", - "DSP 31", -}; - -/* 1616(m) cardbus */ - -static char *emu1616_src_texts[] = { - "Silence", - "Dock Mic A", - "Dock Mic B", - "Dock ADC1 Left", - "Dock ADC1 Right", - "Dock ADC2 Left", - "Dock ADC2 Right", - "Dock SPDIF Left", - "Dock SPDIF Right", - "ADAT 0", - "ADAT 1", - "ADAT 2", - "ADAT 3", - "ADAT 4", - "ADAT 5", - "ADAT 6", - "ADAT 7", - "DSP 0", - "DSP 1", - "DSP 2", - "DSP 3", - "DSP 4", - "DSP 5", - "DSP 6", - "DSP 7", - "DSP 8", - "DSP 9", - "DSP 10", - "DSP 11", - "DSP 12", - "DSP 13", - "DSP 14", - "DSP 15", - "DSP 16", - "DSP 17", - "DSP 18", - "DSP 19", - "DSP 20", - "DSP 21", - "DSP 22", - "DSP 23", - "DSP 24", - "DSP 25", - "DSP 26", - "DSP 27", - "DSP 28", - "DSP 29", - "DSP 30", - "DSP 31", -}; - - -/* - * List of data sources available for each destination - */ -static unsigned int emu1010_src_regs[] = { - EMU_SRC_SILENCE,/* 0 */ - EMU_SRC_DOCK_MIC_A1, /* 1 */ - EMU_SRC_DOCK_MIC_B1, /* 2 */ - EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */ - EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */ - EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */ - EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */ - EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */ - EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */ - EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */ - EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */ - EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */ - EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */ - EMU_SRC_HANA_ADAT, /* 13 */ - EMU_SRC_HANA_ADAT+1, /* 14 */ - EMU_SRC_HANA_ADAT+2, /* 15 */ - EMU_SRC_HANA_ADAT+3, /* 16 */ - EMU_SRC_HANA_ADAT+4, /* 17 */ - EMU_SRC_HANA_ADAT+5, /* 18 */ - EMU_SRC_HANA_ADAT+6, /* 19 */ - EMU_SRC_HANA_ADAT+7, /* 20 */ - EMU_SRC_ALICE_EMU32A, /* 21 */ - EMU_SRC_ALICE_EMU32A+1, /* 22 */ - EMU_SRC_ALICE_EMU32A+2, /* 23 */ - EMU_SRC_ALICE_EMU32A+3, /* 24 */ - EMU_SRC_ALICE_EMU32A+4, /* 25 */ - EMU_SRC_ALICE_EMU32A+5, /* 26 */ - EMU_SRC_ALICE_EMU32A+6, /* 27 */ - EMU_SRC_ALICE_EMU32A+7, /* 28 */ - EMU_SRC_ALICE_EMU32A+8, /* 29 */ - EMU_SRC_ALICE_EMU32A+9, /* 30 */ - EMU_SRC_ALICE_EMU32A+0xa, /* 31 */ - EMU_SRC_ALICE_EMU32A+0xb, /* 32 */ - EMU_SRC_ALICE_EMU32A+0xc, /* 33 */ - EMU_SRC_ALICE_EMU32A+0xd, /* 34 */ - EMU_SRC_ALICE_EMU32A+0xe, /* 35 */ - EMU_SRC_ALICE_EMU32A+0xf, /* 36 */ - EMU_SRC_ALICE_EMU32B, /* 37 */ - EMU_SRC_ALICE_EMU32B+1, /* 38 */ - EMU_SRC_ALICE_EMU32B+2, /* 39 */ - EMU_SRC_ALICE_EMU32B+3, /* 40 */ - EMU_SRC_ALICE_EMU32B+4, /* 41 */ - EMU_SRC_ALICE_EMU32B+5, /* 42 */ - EMU_SRC_ALICE_EMU32B+6, /* 43 */ - EMU_SRC_ALICE_EMU32B+7, /* 44 */ - EMU_SRC_ALICE_EMU32B+8, /* 45 */ - EMU_SRC_ALICE_EMU32B+9, /* 46 */ - EMU_SRC_ALICE_EMU32B+0xa, /* 47 */ - EMU_SRC_ALICE_EMU32B+0xb, /* 48 */ - EMU_SRC_ALICE_EMU32B+0xc, /* 49 */ - EMU_SRC_ALICE_EMU32B+0xd, /* 50 */ - EMU_SRC_ALICE_EMU32B+0xe, /* 51 */ - EMU_SRC_ALICE_EMU32B+0xf, /* 52 */ -}; - -/* 1616(m) cardbus */ -static unsigned int emu1616_src_regs[] = { - EMU_SRC_SILENCE, - EMU_SRC_DOCK_MIC_A1, - EMU_SRC_DOCK_MIC_B1, - EMU_SRC_DOCK_ADC1_LEFT1, - EMU_SRC_DOCK_ADC1_RIGHT1, - EMU_SRC_DOCK_ADC2_LEFT1, - EMU_SRC_DOCK_ADC2_RIGHT1, - EMU_SRC_MDOCK_SPDIF_LEFT1, - EMU_SRC_MDOCK_SPDIF_RIGHT1, - EMU_SRC_MDOCK_ADAT, - EMU_SRC_MDOCK_ADAT+1, - EMU_SRC_MDOCK_ADAT+2, - EMU_SRC_MDOCK_ADAT+3, - EMU_SRC_MDOCK_ADAT+4, - EMU_SRC_MDOCK_ADAT+5, - EMU_SRC_MDOCK_ADAT+6, - EMU_SRC_MDOCK_ADAT+7, - EMU_SRC_ALICE_EMU32A, - EMU_SRC_ALICE_EMU32A+1, - EMU_SRC_ALICE_EMU32A+2, - EMU_SRC_ALICE_EMU32A+3, - EMU_SRC_ALICE_EMU32A+4, - EMU_SRC_ALICE_EMU32A+5, - EMU_SRC_ALICE_EMU32A+6, - EMU_SRC_ALICE_EMU32A+7, - EMU_SRC_ALICE_EMU32A+8, - EMU_SRC_ALICE_EMU32A+9, - EMU_SRC_ALICE_EMU32A+0xa, - EMU_SRC_ALICE_EMU32A+0xb, - EMU_SRC_ALICE_EMU32A+0xc, - EMU_SRC_ALICE_EMU32A+0xd, - EMU_SRC_ALICE_EMU32A+0xe, - EMU_SRC_ALICE_EMU32A+0xf, - EMU_SRC_ALICE_EMU32B, - EMU_SRC_ALICE_EMU32B+1, - EMU_SRC_ALICE_EMU32B+2, - EMU_SRC_ALICE_EMU32B+3, - EMU_SRC_ALICE_EMU32B+4, - EMU_SRC_ALICE_EMU32B+5, - EMU_SRC_ALICE_EMU32B+6, - EMU_SRC_ALICE_EMU32B+7, - EMU_SRC_ALICE_EMU32B+8, - EMU_SRC_ALICE_EMU32B+9, - EMU_SRC_ALICE_EMU32B+0xa, - EMU_SRC_ALICE_EMU32B+0xb, - EMU_SRC_ALICE_EMU32B+0xc, - EMU_SRC_ALICE_EMU32B+0xd, - EMU_SRC_ALICE_EMU32B+0xe, - EMU_SRC_ALICE_EMU32B+0xf, -}; - -/* - * Data destinations - physical EMU outputs. - * Each destination has an enum mixer control to choose a data source - */ -static unsigned int emu1010_output_dst[] = { - EMU_DST_DOCK_DAC1_LEFT1, /* 0 */ - EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */ - EMU_DST_DOCK_DAC2_LEFT1, /* 2 */ - EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */ - EMU_DST_DOCK_DAC3_LEFT1, /* 4 */ - EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */ - EMU_DST_DOCK_DAC4_LEFT1, /* 6 */ - EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */ - EMU_DST_DOCK_PHONES_LEFT1, /* 8 */ - EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */ - EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */ - EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */ - EMU_DST_HANA_SPDIF_LEFT1, /* 12 */ - EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */ - EMU_DST_HAMOA_DAC_LEFT1, /* 14 */ - EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */ - EMU_DST_HANA_ADAT, /* 16 */ - EMU_DST_HANA_ADAT+1, /* 17 */ - EMU_DST_HANA_ADAT+2, /* 18 */ - EMU_DST_HANA_ADAT+3, /* 19 */ - EMU_DST_HANA_ADAT+4, /* 20 */ - EMU_DST_HANA_ADAT+5, /* 21 */ - EMU_DST_HANA_ADAT+6, /* 22 */ - EMU_DST_HANA_ADAT+7, /* 23 */ -}; - -/* 1616(m) cardbus */ -static unsigned int emu1616_output_dst[] = { - EMU_DST_DOCK_DAC1_LEFT1, - EMU_DST_DOCK_DAC1_RIGHT1, - EMU_DST_DOCK_DAC2_LEFT1, - EMU_DST_DOCK_DAC2_RIGHT1, - EMU_DST_DOCK_DAC3_LEFT1, - EMU_DST_DOCK_DAC3_RIGHT1, - EMU_DST_MDOCK_SPDIF_LEFT1, - EMU_DST_MDOCK_SPDIF_RIGHT1, - EMU_DST_MDOCK_ADAT, - EMU_DST_MDOCK_ADAT+1, - EMU_DST_MDOCK_ADAT+2, - EMU_DST_MDOCK_ADAT+3, - EMU_DST_MDOCK_ADAT+4, - EMU_DST_MDOCK_ADAT+5, - EMU_DST_MDOCK_ADAT+6, - EMU_DST_MDOCK_ADAT+7, - EMU_DST_MANA_DAC_LEFT, - EMU_DST_MANA_DAC_RIGHT, -}; - -/* - * Data destinations - HANA outputs going to Alice2 (audigy) for - * capture (EMU32 + I2S links) - * Each destination has an enum mixer control to choose a data source - */ -static unsigned int emu1010_input_dst[] = { - EMU_DST_ALICE2_EMU32_0, - EMU_DST_ALICE2_EMU32_1, - EMU_DST_ALICE2_EMU32_2, - EMU_DST_ALICE2_EMU32_3, - EMU_DST_ALICE2_EMU32_4, - EMU_DST_ALICE2_EMU32_5, - EMU_DST_ALICE2_EMU32_6, - EMU_DST_ALICE2_EMU32_7, - EMU_DST_ALICE2_EMU32_8, - EMU_DST_ALICE2_EMU32_9, - EMU_DST_ALICE2_EMU32_A, - EMU_DST_ALICE2_EMU32_B, - EMU_DST_ALICE2_EMU32_C, - EMU_DST_ALICE2_EMU32_D, - EMU_DST_ALICE2_EMU32_E, - EMU_DST_ALICE2_EMU32_F, - EMU_DST_ALICE_I2S0_LEFT, - EMU_DST_ALICE_I2S0_RIGHT, - EMU_DST_ALICE_I2S1_LEFT, - EMU_DST_ALICE_I2S1_RIGHT, - EMU_DST_ALICE_I2S2_LEFT, - EMU_DST_ALICE_I2S2_RIGHT, -}; - -static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - char **items; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { - uinfo->value.enumerated.items = 49; - items = emu1616_src_texts; - } else { - uinfo->value.enumerated.items = 53; - items = emu1010_src_texts; - } - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = - uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, - items[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int channel; - - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_output_dst, emu->emu1010.output_source */ - if (channel >= 24 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - channel >= 18)) - return -EINVAL; - ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel]; - return 0; -} - -static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - unsigned int channel; - - val = ucontrol->value.enumerated.item[0]; - if (val >= 53 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - val >= 49)) - return -EINVAL; - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_output_dst, emu->emu1010.output_source */ - if (channel >= 24 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - channel >= 18)) - return -EINVAL; - if (emu->emu1010.output_source[channel] == val) - return 0; - emu->emu1010.output_source[channel] = val; - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) - snd_emu1010_fpga_link_dst_src_write(emu, - emu1616_output_dst[channel], emu1616_src_regs[val]); - else - snd_emu1010_fpga_link_dst_src_write(emu, - emu1010_output_dst[channel], emu1010_src_regs[val]); - return 1; -} - -static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int channel; - - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_input_dst, emu->emu1010.input_source */ - if (channel >= 22) - return -EINVAL; - ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel]; - return 0; -} - -static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - unsigned int channel; - - val = ucontrol->value.enumerated.item[0]; - if (val >= 53 || - (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 && - val >= 49)) - return -EINVAL; - channel = (kcontrol->private_value) & 0xff; - /* Limit: emu1010_input_dst, emu->emu1010.input_source */ - if (channel >= 22) - return -EINVAL; - if (emu->emu1010.input_source[channel] == val) - return 0; - emu->emu1010.input_source[channel] = val; - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) - snd_emu1010_fpga_link_dst_src_write(emu, - emu1010_input_dst[channel], emu1616_src_regs[val]); - else - snd_emu1010_fpga_link_dst_src_write(emu, - emu1010_input_dst[channel], emu1010_src_regs[val]); - return 1; -} - -#define EMU1010_SOURCE_OUTPUT(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_input_output_source_info, \ - .get = snd_emu1010_output_source_get, \ - .put = snd_emu1010_output_source_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = { - EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0), - EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5), - EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6), - EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7), - EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8), - EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb), - EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc), - EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd), - EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe), - EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf), - EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10), - EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11), - EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12), - EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13), - EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14), - EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15), - EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16), - EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17), -}; - - -/* 1616(m) cardbus */ -static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] __devinitdata = { - EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0), - EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2), - EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4), - EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 6), - EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 7), - EMU1010_SOURCE_OUTPUT("Dock ADAT 0 Playback Enum", 8), - EMU1010_SOURCE_OUTPUT("Dock ADAT 1 Playback Enum", 9), - EMU1010_SOURCE_OUTPUT("Dock ADAT 2 Playback Enum", 0xa), - EMU1010_SOURCE_OUTPUT("Dock ADAT 3 Playback Enum", 0xb), - EMU1010_SOURCE_OUTPUT("Dock ADAT 4 Playback Enum", 0xc), - EMU1010_SOURCE_OUTPUT("Dock ADAT 5 Playback Enum", 0xd), - EMU1010_SOURCE_OUTPUT("Dock ADAT 6 Playback Enum", 0xe), - EMU1010_SOURCE_OUTPUT("Dock ADAT 7 Playback Enum", 0xf), - EMU1010_SOURCE_OUTPUT("Mana DAC Left Playback Enum", 0x10), - EMU1010_SOURCE_OUTPUT("Mana DAC Right Playback Enum", 0x11), -}; - - -#define EMU1010_SOURCE_INPUT(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_input_output_source_info, \ - .get = snd_emu1010_input_source_get, \ - .put = snd_emu1010_input_source_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = { - EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0), - EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1), - EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2), - EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3), - EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4), - EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5), - EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6), - EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7), - EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8), - EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9), - EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa), - EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb), - EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc), - EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd), - EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe), - EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf), - EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10), - EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11), - EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12), - EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13), - EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14), - EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15), -}; - - - -#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info - -static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0; - return 0; -} - -static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - unsigned int val, cache; - val = ucontrol->value.integer.value[0]; - cache = emu->emu1010.adc_pads; - if (val == 1) - cache = cache | mask; - else - cache = cache & ~mask; - if (cache != emu->emu1010.adc_pads) { - snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache ); - emu->emu1010.adc_pads = cache; - } - - return 0; -} - - - -#define EMU1010_ADC_PADS(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_adc_pads_info, \ - .get = snd_emu1010_adc_pads_get, \ - .put = snd_emu1010_adc_pads_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = { - EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1), - EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2), - EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3), - EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1), -}; - -#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info - -static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0; - return 0; -} - -static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int mask = kcontrol->private_value & 0xff; - unsigned int val, cache; - val = ucontrol->value.integer.value[0]; - cache = emu->emu1010.dac_pads; - if (val == 1) - cache = cache | mask; - else - cache = cache & ~mask; - if (cache != emu->emu1010.dac_pads) { - snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache ); - emu->emu1010.dac_pads = cache; - } - - return 0; -} - - - -#define EMU1010_DAC_PADS(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = snd_emu1010_dac_pads_info, \ - .get = snd_emu1010_dac_pads_get, \ - .put = snd_emu1010_dac_pads_put, \ - .private_value = chid \ -} - -static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = { - EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1), - EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2), - EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3), - EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4), - EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1), -}; - - -static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { - "44100", "48000", "SPDIF", "ADAT" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; - - -} - -static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock; - return 0; -} - -static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - - val = ucontrol->value.enumerated.item[0] ; - /* Limit: uinfo->value.enumerated.items = 4; */ - if (val >= 4) - return -EINVAL; - change = (emu->emu1010.internal_clock != val); - if (change) { - emu->emu1010.internal_clock = val; - switch (val) { - case 0: - /* 44100 */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K ); - /* Word Clock source, Internal 44.1kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, - EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - break; - case 1: - /* 48000 */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); - /* Word Clock source, Internal 48kHz x1 */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, - EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - break; - - case 2: /* Take clock from S/PDIF IN */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); - /* Word Clock source, sync to S/PDIF input */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, - EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - break; - - case 3: - /* Take clock from ADAT IN */ - /* Mute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); - /* Default fallback clock 48kHz */ - snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); - /* Word Clock source, sync to ADAT input */ - snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, - EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X ); - /* Set LEDs on Audio Dock */ - snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK ); - /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */ - /* Allow DLL to settle */ - msleep(10); - /* Unmute all */ - snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); - - - break; - } - } - return change; -} - -static struct snd_kcontrol_new snd_emu1010_internal_clock = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Clock Internal Rate", - .count = 1, - .info = snd_emu1010_internal_clock_info, - .get = snd_emu1010_internal_clock_get, - .put = snd_emu1010_internal_clock_put -}; - -static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ -#if 0 - static char *texts[4] = { - "Unknown1", "Unknown2", "Mic", "Line" - }; -#endif - static char *texts[2] = { - "Mic", "Line" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 2; - if (uinfo->value.enumerated.item > 1) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; - return 0; -} - -static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int source_id; - unsigned int ngain, ogain; - u32 gpio; - int change = 0; - unsigned long flags; - u32 source; - /* If the capture source has changed, - * update the capture volume from the cached value - * for the particular source. - */ - source_id = ucontrol->value.enumerated.item[0]; - /* Limit: uinfo->value.enumerated.items = 2; */ - /* emu->i2c_capture_volume */ - if (source_id >= 2) - return -EINVAL; - change = (emu->i2c_capture_source != source_id); - if (change) { - snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ - spin_lock_irqsave(&emu->emu_lock, flags); - gpio = inl(emu->port + A_IOCFG); - if (source_id==0) - outl(gpio | 0x4, emu->port + A_IOCFG); - else - outl(gpio & ~0x4, emu->port + A_IOCFG); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ - if (ngain != ogain) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); - ngain = emu->i2c_capture_volume[source_id][1]; /* Right */ - ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ - if (ngain != ogain) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - - source = 1 << (source_id + 2); - snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */ - emu->i2c_capture_source = source_id; - } - return change; -} - -static struct snd_kcontrol_new snd_audigy_i2c_capture_source = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_audigy_i2c_capture_source_info, - .get = snd_audigy_i2c_capture_source_get, - .put = snd_audigy_i2c_capture_source_put -}; - -static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int source_id; - - source_id = kcontrol->private_value; - /* Limit: emu->i2c_capture_volume */ - /* capture_source: uinfo->value.enumerated.items = 2 */ - if (source_id >= 2) - return -EINVAL; - - ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; - ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; - return 0; -} - -static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int ogain; - unsigned int ngain; - unsigned int source_id; - int change = 0; - - source_id = kcontrol->private_value; - /* Limit: emu->i2c_capture_volume */ - /* capture_source: uinfo->value.enumerated.items = 2 */ - if (source_id >= 2) - return -EINVAL; - ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ - ngain = ucontrol->value.integer.value[0]; - if (ngain > 0xff) - return 0; - if (ogain != ngain) { - if (emu->i2c_capture_source == source_id) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); - emu->i2c_capture_volume[source_id][0] = ngain; - change = 1; - } - ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ - ngain = ucontrol->value.integer.value[1]; - if (ngain > 0xff) - return 0; - if (ogain != ngain) { - if (emu->i2c_capture_source == source_id) - snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - emu->i2c_capture_volume[source_id][1] = ngain; - change = 1; - } - - return change; -} - -#define I2C_VOLUME(xname,chid) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_audigy_i2c_volume_info, \ - .get = snd_audigy_i2c_volume_get, \ - .put = snd_audigy_i2c_volume_put, \ - .tlv = { .p = snd_audigy_db_scale2 }, \ - .private_value = chid \ -} - - -static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = { - I2C_VOLUME("Mic Capture Volume", 0), - I2C_VOLUME("Line Capture Volume", 0) -}; - -#if 0 -static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[] = {"44100", "48000", "96000"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) - uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int tmp; - unsigned long flags; - - - spin_lock_irqsave(&emu->reg_lock, flags); - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - switch (tmp & A_SPDIF_RATE_MASK) { - case A_SPDIF_44100: - ucontrol->value.enumerated.item[0] = 0; - break; - case A_SPDIF_48000: - ucontrol->value.enumerated.item[0] = 1; - break; - case A_SPDIF_96000: - ucontrol->value.enumerated.item[0] = 2; - break; - default: - ucontrol->value.enumerated.item[0] = 1; - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int change; - unsigned int reg, val, tmp; - unsigned long flags; - - switch(ucontrol->value.enumerated.item[0]) { - case 0: - val = A_SPDIF_44100; - break; - case 1: - val = A_SPDIF_48000; - break; - case 2: - val = A_SPDIF_96000; - break; - default: - val = A_SPDIF_48000; - break; - } - - - spin_lock_irqsave(&emu->reg_lock, flags); - reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); - tmp = reg & ~A_SPDIF_RATE_MASK; - tmp |= val; - if ((change = (tmp != reg))) - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_audigy_spdif_output_rate = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Audigy SPDIF Output Sample Rate", - .count = 1, - .info = snd_audigy_spdif_output_rate_info, - .get = snd_audigy_spdif_output_rate_get, - .put = snd_audigy_spdif_output_rate_put -}; -#endif - -static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - int change; - unsigned int val; - unsigned long flags; - - /* Limit: emu->spdif_bits */ - if (idx >= 3) - return -EINVAL; - val = (ucontrol->value.iec958.status[0] << 0) | - (ucontrol->value.iec958.status[1] << 8) | - (ucontrol->value.iec958.status[2] << 16) | - (ucontrol->value.iec958.status[3] << 24); - spin_lock_irqsave(&emu->reg_lock, flags); - change = val != emu->spdif_bits[idx]; - if (change) { - snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val); - emu->spdif_bits[idx] = val; - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), - .count = 3, - .info = snd_emu10k1_spdif_info, - .get = snd_emu10k1_spdif_get_mask -}; - -static struct snd_kcontrol_new snd_emu10k1_spdif_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), - .count = 3, - .info = snd_emu10k1_spdif_info, - .get = snd_emu10k1_spdif_get, - .put = snd_emu10k1_spdif_put -}; - - -static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route) -{ - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXRT1, voice, - snd_emu10k1_compose_audigy_fxrt1(route)); - snd_emu10k1_ptr_write(emu, A_FXRT2, voice, - snd_emu10k1_compose_audigy_fxrt2(route)); - } else { - snd_emu10k1_ptr_write(emu, FXRT, voice, - snd_emu10k1_compose_send_routing(route)); - } -} - -static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume) -{ - snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]); - snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]); - snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]); - snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]); - if (emu->audigy) { - unsigned int val = ((unsigned int)volume[4] << 24) | - ((unsigned int)volume[5] << 16) | - ((unsigned int)volume[6] << 8) | - (unsigned int)volume[7]; - snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val); - } -} - -/* PCM stream controls */ - -static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 3*8 : 3*4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; - return 0; -} - -static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int voice, idx; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (voice = 0; voice < 3; voice++) - for (idx = 0; idx < num_efx; idx++) - ucontrol->value.integer.value[(voice * num_efx) + idx] = - mix->send_routing[voice][idx] & mask; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int change = 0, voice, idx, val; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (voice = 0; voice < 3; voice++) - for (idx = 0; idx < num_efx; idx++) { - val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask; - if (mix->send_routing[voice][idx] != val) { - mix->send_routing[voice][idx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[0] && mix->epcm->voices[1]) { - update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, - &mix->send_routing[1][0]); - update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number, - &mix->send_routing[2][0]); - } else if (mix->epcm->voices[0]) { - update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, - &mix->send_routing[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_send_routing_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "EMU10K1 PCM Send Routing", - .count = 32, - .info = snd_emu10k1_send_routing_info, - .get = snd_emu10k1_send_routing_get, - .put = snd_emu10k1_send_routing_put -}; - -static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 3*8 : 3*4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int idx; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3*num_efx; idx++) - ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int change = 0, idx, val; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3*num_efx; idx++) { - val = ucontrol->value.integer.value[idx] & 255; - if (mix->send_volume[idx/num_efx][idx%num_efx] != val) { - mix->send_volume[idx/num_efx][idx%num_efx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[0] && mix->epcm->voices[1]) { - update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, - &mix->send_volume[1][0]); - update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number, - &mix->send_volume[2][0]); - } else if (mix->epcm->voices[0]) { - update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, - &mix->send_volume[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_send_volume_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "EMU10K1 PCM Send Volume", - .count = 32, - .info = snd_emu10k1_send_volume_info, - .get = snd_emu10k1_send_volume_get, - .put = snd_emu10k1_send_volume_put -}; - -static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 3; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; - return 0; -} - -static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - unsigned long flags; - int idx; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3; idx++) - ucontrol->value.integer.value[idx] = mix->attn[idx]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int change = 0, idx, val; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < 3; idx++) { - val = ucontrol->value.integer.value[idx] & 0xffff; - if (mix->attn[idx] != val) { - mix->attn[idx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[0] && mix->epcm->voices[1]) { - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]); - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]); - } else if (mix->epcm->voices[0]) { - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_attn_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "EMU10K1 PCM Volume", - .count = 32, - .info = snd_emu10k1_attn_info, - .get = snd_emu10k1_attn_get, - .put = snd_emu10k1_attn_put -}; - -/* Mutichannel PCM stream controls */ - -static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 8 : 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; - return 0; -} - -static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int idx; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) - ucontrol->value.integer.value[idx] = - mix->send_routing[0][idx] & mask; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; - int change = 0, idx, val; - int num_efx = emu->audigy ? 8 : 4; - int mask = emu->audigy ? 0x3f : 0x0f; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) { - val = ucontrol->value.integer.value[idx] & mask; - if (mix->send_routing[0][idx] != val) { - mix->send_routing[0][idx] = val; - change = 1; - } - } - - if (change && mix->epcm) { - if (mix->epcm->voices[ch]) { - update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number, - &mix->send_routing[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multichannel PCM Send Routing", - .count = 16, - .info = snd_emu10k1_efx_send_routing_info, - .get = snd_emu10k1_efx_send_routing_get, - .put = snd_emu10k1_efx_send_routing_put -}; - -static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = emu->audigy ? 8 : 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - int idx; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) - ucontrol->value.integer.value[idx] = mix->send_volume[0][idx]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; - int change = 0, idx, val; - int num_efx = emu->audigy ? 8 : 4; - - spin_lock_irqsave(&emu->reg_lock, flags); - for (idx = 0; idx < num_efx; idx++) { - val = ucontrol->value.integer.value[idx] & 255; - if (mix->send_volume[0][idx] != val) { - mix->send_volume[0][idx] = val; - change = 1; - } - } - if (change && mix->epcm) { - if (mix->epcm->voices[ch]) { - update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number, - &mix->send_volume[0][0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - - -static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multichannel PCM Send Volume", - .count = 16, - .info = snd_emu10k1_efx_send_volume_info, - .get = snd_emu10k1_efx_send_volume_get, - .put = snd_emu10k1_efx_send_volume_put -}; - -static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0xffff; - return 0; -} - -static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - struct snd_emu10k1_pcm_mixer *mix = - &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; - unsigned long flags; - - spin_lock_irqsave(&emu->reg_lock, flags); - ucontrol->value.integer.value[0] = mix->attn[0]; - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; - int change = 0, val; - - spin_lock_irqsave(&emu->reg_lock, flags); - val = ucontrol->value.integer.value[0] & 0xffff; - if (mix->attn[0] != val) { - mix->attn[0] = val; - change = 1; - } - if (change && mix->epcm) { - if (mix->epcm->voices[ch]) { - snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); - } - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_efx_attn_control = -{ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Multichannel PCM Volume", - .count = 16, - .info = snd_emu10k1_efx_attn_info, - .get = snd_emu10k1_efx_attn_get, - .put = snd_emu10k1_efx_attn_put -}; - -#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info - -static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - if (emu->audigy) - ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; - else - ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0; - if (emu->card_capabilities->invert_shared_spdif) - ucontrol->value.integer.value[0] = - !ucontrol->value.integer.value[0]; - - return 0; -} - -static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - unsigned long flags; - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int reg, val, sw; - int change = 0; - - sw = ucontrol->value.integer.value[0]; - if (emu->card_capabilities->invert_shared_spdif) - sw = !sw; - spin_lock_irqsave(&emu->reg_lock, flags); - if ( emu->card_capabilities->i2c_adc) { - /* Do nothing for Audigy 2 ZS Notebook */ - } else if (emu->audigy) { - reg = inl(emu->port + A_IOCFG); - val = sw ? A_IOCFG_GPOUT0 : 0; - change = (reg & A_IOCFG_GPOUT0) != val; - if (change) { - reg &= ~A_IOCFG_GPOUT0; - reg |= val; - outl(reg | val, emu->port + A_IOCFG); - } - } - reg = inl(emu->port + HCFG); - val = sw ? HCFG_GPOUT0 : 0; - change |= (reg & HCFG_GPOUT0) != val; - if (change) { - reg &= ~HCFG_GPOUT0; - reg |= val; - outl(reg | val, emu->port + HCFG); - } - spin_unlock_irqrestore(&emu->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "SB Live Analog/Digital Output Jack", - .info = snd_emu10k1_shared_spdif_info, - .get = snd_emu10k1_shared_spdif_get, - .put = snd_emu10k1_shared_spdif_put -}; - -static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Audigy Analog/Digital Output Jack", - .info = snd_emu10k1_shared_spdif_info, - .get = snd_emu10k1_shared_spdif_get, - .put = snd_emu10k1_shared_spdif_put -}; - -/* workaround for too low volume on Audigy due to 16bit/24bit conversion */ - -#define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info - -static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - - /* FIXME: better to use a cached version */ - val = snd_ac97_read(emu->ac97, AC97_REC_GAIN); - ucontrol->value.integer.value[0] = !!val; - return 0; -} - -static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - - if (ucontrol->value.integer.value[0]) - val = 0x0f0f; - else - val = 0; - return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val); -} - -static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Capture Boost", - .info = snd_audigy_capture_boost_info, - .get = snd_audigy_capture_boost_get, - .put = snd_audigy_capture_boost_put -}; - - -/* - */ -static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97) -{ - struct snd_emu10k1 *emu = ac97->private_data; - emu->ac97 = NULL; -} - -/* - */ -static int remove_ctl(struct snd_card *card, const char *name) -{ - struct snd_ctl_elem_id id; - memset(&id, 0, sizeof(id)); - strcpy(id.name, name); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_remove_id(card, &id); -} - -static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) -{ - struct snd_ctl_elem_id sid; - memset(&sid, 0, sizeof(sid)); - strcpy(sid.name, name); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - return snd_ctl_find_id(card, &sid); -} - -static int rename_ctl(struct snd_card *card, const char *src, const char *dst) -{ - struct snd_kcontrol *kctl = ctl_find(card, src); - if (kctl) { - strcpy(kctl->id.name, dst); - return 0; - } - return -ENOENT; -} - -int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, - int pcm_device, int multi_device) -{ - int err, pcm; - struct snd_kcontrol *kctl; - struct snd_card *card = emu->card; - char **c; - static char *emu10k1_remove_ctls[] = { - /* no AC97 mono, surround, center/lfe */ - "Master Mono Playback Switch", - "Master Mono Playback Volume", - "PCM Out Path & Mute", - "Mono Output Select", - "Surround Playback Switch", - "Surround Playback Volume", - "Center Playback Switch", - "Center Playback Volume", - "LFE Playback Switch", - "LFE Playback Volume", - NULL - }; - static char *emu10k1_rename_ctls[] = { - "Surround Digital Playback Volume", "Surround Playback Volume", - "Center Digital Playback Volume", "Center Playback Volume", - "LFE Digital Playback Volume", "LFE Playback Volume", - NULL - }; - static char *audigy_remove_ctls[] = { - /* Master/PCM controls on ac97 of Audigy has no effect */ - /* On the Audigy2 the AC97 playback is piped into - * the Philips ADC for 24bit capture */ - "PCM Playback Switch", - "PCM Playback Volume", - "Master Mono Playback Switch", - "Master Mono Playback Volume", - "Master Playback Switch", - "Master Playback Volume", - "PCM Out Path & Mute", - "Mono Output Select", - /* remove unused AC97 capture controls */ - "Capture Source", - "Capture Switch", - "Capture Volume", - "Mic Select", - "Video Playback Switch", - "Video Playback Volume", - "Mic Playback Switch", - "Mic Playback Volume", - NULL - }; - static char *audigy_rename_ctls[] = { - /* use conventional names */ - "Wave Playback Volume", "PCM Playback Volume", - /* "Wave Capture Volume", "PCM Capture Volume", */ - "Wave Master Playback Volume", "Master Playback Volume", - "AMic Playback Volume", "Mic Playback Volume", - NULL - }; - static char *audigy_rename_ctls_i2c_adc[] = { - //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume", - "Line Capture Volume", "Analog Mix Capture Volume", - "Wave Playback Volume", "OLD PCM Playback Volume", - "Wave Master Playback Volume", "Master Playback Volume", - "AMic Playback Volume", "Old Mic Playback Volume", - "CD Capture Volume", "IEC958 Optical Capture Volume", - NULL - }; - static char *audigy_remove_ctls_i2c_adc[] = { - /* On the Audigy2 ZS Notebook - * Capture via WM8775 */ - "Mic Capture Volume", - "Analog Mix Capture Volume", - "Aux Capture Volume", - "IEC958 Optical Capture Volume", - NULL - }; - static char *audigy_remove_ctls_1361t_adc[] = { - /* On the Audigy2 the AC97 playback is piped into - * the Philips ADC for 24bit capture */ - "PCM Playback Switch", - "PCM Playback Volume", - "Master Mono Playback Switch", - "Master Mono Playback Volume", - "Capture Source", - "Capture Switch", - "Capture Volume", - "Mic Capture Volume", - "Headphone Playback Switch", - "Headphone Playback Volume", - "3D Control - Center", - "3D Control - Depth", - "3D Control - Switch", - "Line2 Playback Volume", - "Line2 Capture Volume", - NULL - }; - static char *audigy_rename_ctls_1361t_adc[] = { - "Master Playback Switch", "Master Capture Switch", - "Master Playback Volume", "Master Capture Volume", - "Wave Master Playback Volume", "Master Playback Volume", - "Beep Playback Switch", "Beep Capture Switch", - "Beep Playback Volume", "Beep Capture Volume", - "Phone Playback Switch", "Phone Capture Switch", - "Phone Playback Volume", "Phone Capture Volume", - "Mic Playback Switch", "Mic Capture Switch", - "Mic Playback Volume", "Mic Capture Volume", - "Line Playback Switch", "Line Capture Switch", - "Line Playback Volume", "Line Capture Volume", - "CD Playback Switch", "CD Capture Switch", - "CD Playback Volume", "CD Capture Volume", - "Aux Playback Switch", "Aux Capture Switch", - "Aux Playback Volume", "Aux Capture Volume", - "Video Playback Switch", "Video Capture Switch", - "Video Playback Volume", "Video Capture Volume", - - NULL - }; - - if (emu->card_capabilities->ac97_chip) { - struct snd_ac97_bus *pbus; - struct snd_ac97_template ac97; - static struct snd_ac97_bus_ops ops = { - .write = snd_emu10k1_ac97_write, - .read = snd_emu10k1_ac97_read, - }; - - if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) - return err; - pbus->no_vra = 1; /* we don't need VRA */ - - memset(&ac97, 0, sizeof(ac97)); - ac97.private_data = emu; - ac97.private_free = snd_emu10k1_mixer_free_ac97; - ac97.scaps = AC97_SCAP_NO_SPDIF; - if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) { - if (emu->card_capabilities->ac97_chip == 1) - return err; - snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n"); - snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n"); - snd_device_free(emu->card, pbus); - goto no_ac97; /* FIXME: get rid of ugly gotos.. */ - } - if (emu->audigy) { - /* set master volume to 0 dB */ - snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); - /* set capture source to mic */ - snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); - if (emu->card_capabilities->adc_1361t) - c = audigy_remove_ctls_1361t_adc; - else - c = audigy_remove_ctls; - } else { - /* - * Credits for cards based on STAC9758: - * James Courtier-Dutton <James@superbug.demon.co.uk> - * Voluspa <voluspa@comhem.se> - */ - if (emu->ac97->id == AC97_ID_STAC9758) { - emu->rear_ac97 = 1; - snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); - snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202); - remove_ctl(card,"Front Playback Volume"); - remove_ctl(card,"Front Playback Switch"); - } - /* remove unused AC97 controls */ - snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); - snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202); - c = emu10k1_remove_ctls; - } - for (; *c; c++) - remove_ctl(card, *c); - } else if (emu->card_capabilities->i2c_adc) { - c = audigy_remove_ctls_i2c_adc; - for (; *c; c++) - remove_ctl(card, *c); - } else { - no_ac97: - if (emu->card_capabilities->ecard) - strcpy(emu->card->mixername, "EMU APS"); - else if (emu->audigy) - strcpy(emu->card->mixername, "SB Audigy"); - else - strcpy(emu->card->mixername, "Emu10k1"); - } - - if (emu->audigy) - if (emu->card_capabilities->adc_1361t) - c = audigy_rename_ctls_1361t_adc; - else if (emu->card_capabilities->i2c_adc) - c = audigy_rename_ctls_i2c_adc; - else - c = audigy_rename_ctls; - else - c = emu10k1_rename_ctls; - for (; *c; c += 2) - rename_ctl(card, c[0], c[1]); - - if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */ - remove_ctl(card, "Center Playback Volume"); - remove_ctl(card, "LFE Playback Volume"); - remove_ctl(card, "Wave Center Playback Volume"); - remove_ctl(card, "Wave LFE Playback Volume"); - } - if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ - rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); - rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); - rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume"); - rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume"); - remove_ctl(card, "Headphone Playback Switch"); - remove_ctl(card, "Headphone Playback Volume"); - remove_ctl(card, "3D Control - Center"); - remove_ctl(card, "3D Control - Depth"); - remove_ctl(card, "3D Control - Switch"); - } - if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL) - return -ENOMEM; - kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) - return err; - - /* initialize the routing and volume table for each pcm playback stream */ - for (pcm = 0; pcm < 32; pcm++) { - struct snd_emu10k1_pcm_mixer *mix; - int v; - - mix = &emu->pcm_mixer[pcm]; - mix->epcm = NULL; - - for (v = 0; v < 4; v++) - mix->send_routing[0][v] = - mix->send_routing[1][v] = - mix->send_routing[2][v] = v; - - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = mix->send_volume[0][1] = - mix->send_volume[1][0] = mix->send_volume[2][1] = 255; - - mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; - } - - /* initialize the routing and volume table for the multichannel playback stream */ - for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) { - struct snd_emu10k1_pcm_mixer *mix; - int v; - - mix = &emu->efx_pcm_mixer[pcm]; - mix->epcm = NULL; - - mix->send_routing[0][0] = pcm; - mix->send_routing[0][1] = (pcm == 0) ? 1 : 0; - for (v = 0; v < 2; v++) - mix->send_routing[0][2+v] = 13+v; - if (emu->audigy) - for (v = 0; v < 4; v++) - mix->send_routing[0][4+v] = 60+v; - - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = 255; - - mix->attn[0] = 0xffff; - } - - if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */ - /* sb live! and audigy */ - if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) - return -ENOMEM; - if (!emu->audigy) - kctl->id.device = emu->pcm_efx->device; - if ((err = snd_ctl_add(card, kctl))) - return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL) - return -ENOMEM; - if (!emu->audigy) - kctl->id.device = emu->pcm_efx->device; - if ((err = snd_ctl_add(card, kctl))) - return err; - } - - if (emu->card_capabilities->emu_model) { - ; /* Disable the snd_audigy_spdif_shared_spdif */ - } else if (emu->audigy) { - if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; -#if 0 - if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; -#endif - } else if (! emu->card_capabilities->ecard) { - /* sb live! */ - if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) - return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) - return err; - } - if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_p16v_mixer(emu))) - return err; - } - - if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) { - /* 1616(m) cardbus */ - int i; - - for (i = 0; i < ARRAY_SIZE(snd_emu1616_output_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1616_output_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads) - 2; i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads) - 2; i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); - if (err < 0) - return err; - } - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_internal_clock, emu)); - if (err < 0) - return err; - - } else if (emu->card_capabilities->emu_model) { - /* all other e-mu cards for now */ - int i; - - for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], - emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); - if (err < 0) - return err; - } - err = snd_ctl_add(card, - snd_ctl_new1(&snd_emu1010_internal_clock, emu)); - if (err < 0) - return err; - } - - if ( emu->card_capabilities->i2c_adc) { - int i; - - err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu)); - if (err < 0) - return err; - - for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu)); - if (err < 0) - return err; - } - } - - if (emu->card_capabilities->ac97_chip && emu->audigy) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost, - emu)); - if (err < 0) - return err; - } - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c b/ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c deleted file mode 100644 index bab56482..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of EMU10K1 MPU-401 in UART mode - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/time.h> -#include <linux/init.h> -#include <sound/core.h> -#include <sound/emu10k1.h> - -#define EMU10K1_MIDI_MODE_INPUT (1<<0) -#define EMU10K1_MIDI_MODE_OUTPUT (1<<1) - -static inline unsigned char mpu401_read(struct snd_emu10k1 *emu, - struct snd_emu10k1_midi *mpu, int idx) -{ - if (emu->audigy) - return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0); - else - return inb(emu->port + mpu->port + idx); -} - -static inline void mpu401_write(struct snd_emu10k1 *emu, - struct snd_emu10k1_midi *mpu, int data, int idx) -{ - if (emu->audigy) - snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data); - else - outb(data, emu->port + mpu->port + idx); -} - -#define mpu401_write_data(emu, mpu, data) mpu401_write(emu, mpu, data, 0) -#define mpu401_write_cmd(emu, mpu, data) mpu401_write(emu, mpu, data, 1) -#define mpu401_read_data(emu, mpu) mpu401_read(emu, mpu, 0) -#define mpu401_read_stat(emu, mpu) mpu401_read(emu, mpu, 1) - -#define mpu401_input_avail(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x80)) -#define mpu401_output_ready(emu,mpu) (!(mpu401_read_stat(emu,mpu) & 0x40)) - -#define MPU401_RESET 0xff -#define MPU401_ENTER_UART 0x3f -#define MPU401_ACK 0xfe - -static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu) -{ - int timeout = 100000; - for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--) - mpu401_read_data(emu, mpu); -#ifdef CONFIG_SND_DEBUG - if (timeout <= 0) - snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", mpu401_read_stat(emu, mpu)); -#endif -} - -/* - - */ - -static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status) -{ - unsigned char byte; - - if (midi->rmidi == NULL) { - snd_emu10k1_intr_disable(emu, midi->tx_enable | midi->rx_enable); - return; - } - - spin_lock(&midi->input_lock); - if ((status & midi->ipr_rx) && mpu401_input_avail(emu, midi)) { - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - mpu401_clear_rx(emu, midi); - } else { - byte = mpu401_read_data(emu, midi); - if (midi->substream_input) - snd_rawmidi_receive(midi->substream_input, &byte, 1); - } - } - spin_unlock(&midi->input_lock); - - spin_lock(&midi->output_lock); - if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) { - if (midi->substream_output && - snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) { - mpu401_write_data(emu, midi, byte); - } else { - snd_emu10k1_intr_disable(emu, midi->tx_enable); - } - } - spin_unlock(&midi->output_lock); -} - -static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status) -{ - do_emu10k1_midi_interrupt(emu, &emu->midi, status); -} - -static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status) -{ - do_emu10k1_midi_interrupt(emu, &emu->midi2, status); -} - -static int snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack) -{ - unsigned long flags; - int timeout, ok; - - spin_lock_irqsave(&midi->input_lock, flags); - mpu401_write_data(emu, midi, 0x00); - /* mpu401_clear_rx(emu, midi); */ - - mpu401_write_cmd(emu, midi, cmd); - if (ack) { - ok = 0; - timeout = 10000; - while (!ok && timeout-- > 0) { - if (mpu401_input_avail(emu, midi)) { - if (mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } - } - if (!ok && mpu401_read_data(emu, midi) == MPU401_ACK) - ok = 1; - } else { - ok = 1; - } - spin_unlock_irqrestore(&midi->input_lock, flags); - if (!ok) { - snd_printk(KERN_ERR "midi_cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)!!!\n", - cmd, emu->port, - mpu401_read_stat(emu, midi), - mpu401_read_data(emu, midi)); - return 1; - } - return 0; -} - -static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1_MIDI_MODE_INPUT; - midi->substream_input = substream; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - midi->midi_mode |= EMU10K1_MIDI_MODE_OUTPUT; - midi->substream_output = substream; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 1)) - goto error_out; - if (snd_emu10k1_midi_cmd(emu, midi, MPU401_ENTER_UART, 1)) - goto error_out; - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return 0; - -error_out: - return -EIO; -} - -static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1_intr_disable(emu, midi->rx_enable); - midi->midi_mode &= ~EMU10K1_MIDI_MODE_INPUT; - midi->substream_input = NULL; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - int err = 0; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return -ENXIO; - spin_lock_irqsave(&midi->open_lock, flags); - snd_emu10k1_intr_disable(emu, midi->tx_enable); - midi->midi_mode &= ~EMU10K1_MIDI_MODE_OUTPUT; - midi->substream_output = NULL; - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_INPUT)) { - spin_unlock_irqrestore(&midi->open_lock, flags); - err = snd_emu10k1_midi_cmd(emu, midi, MPU401_RESET, 0); - } else { - spin_unlock_irqrestore(&midi->open_lock, flags); - } - return err; -} - -static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) - snd_emu10k1_intr_enable(emu, midi->rx_enable); - else - snd_emu10k1_intr_disable(emu, midi->rx_enable); -} - -static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_emu10k1 *emu; - struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data; - unsigned long flags; - - emu = midi->emu; - if (snd_BUG_ON(!emu)) - return; - - if (up) { - int max = 4; - unsigned char byte; - - /* try to send some amount of bytes here before interrupts */ - spin_lock_irqsave(&midi->output_lock, flags); - while (max > 0) { - if (mpu401_output_ready(emu, midi)) { - if (!(midi->midi_mode & EMU10K1_MIDI_MODE_OUTPUT) || - snd_rawmidi_transmit(substream, &byte, 1) != 1) { - /* no more data */ - spin_unlock_irqrestore(&midi->output_lock, flags); - return; - } - mpu401_write_data(emu, midi, byte); - max--; - } else { - break; - } - } - spin_unlock_irqrestore(&midi->output_lock, flags); - snd_emu10k1_intr_enable(emu, midi->tx_enable); - } else { - snd_emu10k1_intr_disable(emu, midi->tx_enable); - } -} - -/* - - */ - -static struct snd_rawmidi_ops snd_emu10k1_midi_output = -{ - .open = snd_emu10k1_midi_output_open, - .close = snd_emu10k1_midi_output_close, - .trigger = snd_emu10k1_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_emu10k1_midi_input = -{ - .open = snd_emu10k1_midi_input_open, - .close = snd_emu10k1_midi_input_close, - .trigger = snd_emu10k1_midi_input_trigger, -}; - -static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi) -{ - struct snd_emu10k1_midi *midi = rmidi->private_data; - midi->interrupt = NULL; - midi->rmidi = NULL; -} - -static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name) -{ - struct snd_rawmidi *rmidi; - int err; - - if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0) - return err; - midi->emu = emu; - spin_lock_init(&midi->open_lock); - spin_lock_init(&midi->input_lock); - spin_lock_init(&midi->output_lock); - strcpy(rmidi->name, name); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_emu10k1_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_emu10k1_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = midi; - rmidi->private_free = snd_emu10k1_midi_free; - midi->rmidi = rmidi; - return 0; -} - -int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu) -{ - struct snd_emu10k1_midi *midi = &emu->midi; - int err; - - if ((err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)")) < 0) - return err; - - midi->tx_enable = INTE_MIDITXENABLE; - midi->rx_enable = INTE_MIDIRXENABLE; - midi->port = MUDATA; - midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; - midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; - midi->interrupt = snd_emu10k1_midi_interrupt; - return 0; -} - -int __devinit snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu) -{ - struct snd_emu10k1_midi *midi; - int err; - - midi = &emu->midi; - if ((err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)")) < 0) - return err; - - midi->tx_enable = INTE_MIDITXENABLE; - midi->rx_enable = INTE_MIDIRXENABLE; - midi->port = A_MUDATA1; - midi->ipr_tx = IPR_MIDITRANSBUFEMPTY; - midi->ipr_rx = IPR_MIDIRECVBUFEMPTY; - midi->interrupt = snd_emu10k1_midi_interrupt; - - midi = &emu->midi2; - if ((err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2")) < 0) - return err; - - midi->tx_enable = INTE_A_MIDITXENABLE2; - midi->rx_enable = INTE_A_MIDIRXENABLE2; - midi->port = A_MUDATA2; - midi->ipr_tx = IPR_A_MIDITRANSBUFEMPTY2; - midi->ipr_rx = IPR_A_MIDIRECVBUFEMPTY2; - midi->interrupt = snd_emu10k1_midi_interrupt2; - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c b/ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c deleted file mode 100644 index e22b8e2b..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c +++ /dev/null @@ -1,1870 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips / PCM routines - * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/init.h> -#include <sound/core.h> -#include <sound/emu10k1.h> - -static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu, - struct snd_emu10k1_voice *voice) -{ - struct snd_emu10k1_pcm *epcm; - - if ((epcm = voice->epcm) == NULL) - return; - if (epcm->substream == NULL) - return; -#if 0 - printk(KERN_DEBUG "IRQ: position = 0x%x, period = 0x%x, size = 0x%x\n", - epcm->substream->runtime->hw->pointer(emu, epcm->substream), - snd_pcm_lib_period_bytes(epcm->substream), - snd_pcm_lib_buffer_bytes(epcm->substream)); -#endif - snd_pcm_period_elapsed(epcm->substream); -} - -static void snd_emu10k1_pcm_ac97adc_interrupt(struct snd_emu10k1 *emu, - unsigned int status) -{ -#if 0 - if (status & IPR_ADCBUFHALFFULL) { - if (emu->pcm_capture_substream->runtime->mode == SNDRV_PCM_MODE_FRAME) - return; - } -#endif - snd_pcm_period_elapsed(emu->pcm_capture_substream); -} - -static void snd_emu10k1_pcm_ac97mic_interrupt(struct snd_emu10k1 *emu, - unsigned int status) -{ -#if 0 - if (status & IPR_MICBUFHALFFULL) { - if (emu->pcm_capture_mic_substream->runtime->mode == SNDRV_PCM_MODE_FRAME) - return; - } -#endif - snd_pcm_period_elapsed(emu->pcm_capture_mic_substream); -} - -static void snd_emu10k1_pcm_efx_interrupt(struct snd_emu10k1 *emu, - unsigned int status) -{ -#if 0 - if (status & IPR_EFXBUFHALFFULL) { - if (emu->pcm_capture_efx_substream->runtime->mode == SNDRV_PCM_MODE_FRAME) - return; - } -#endif - snd_pcm_period_elapsed(emu->pcm_capture_efx_substream); -} - -static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int ptr; - - if (!epcm->running) - return 0; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff; - ptr += runtime->buffer_size; - ptr -= epcm->ccca_start_addr; - ptr %= runtime->buffer_size; - - return ptr; -} - -static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voices) -{ - int err, i; - - if (epcm->voices[1] != NULL && voices < 2) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); - epcm->voices[1] = NULL; - } - for (i = 0; i < voices; i++) { - if (epcm->voices[i] == NULL) - break; - } - if (i == voices) - return 0; /* already allocated */ - - for (i = 0; i < ARRAY_SIZE(epcm->voices); i++) { - if (epcm->voices[i]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); - epcm->voices[i] = NULL; - } - } - err = snd_emu10k1_voice_alloc(epcm->emu, - epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX, - voices, - &epcm->voices[0]); - - if (err < 0) - return err; - epcm->voices[0]->epcm = epcm; - if (voices > 1) { - for (i = 1; i < voices; i++) { - epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i]; - epcm->voices[i]->epcm = epcm; - } - } - if (epcm->extra == NULL) { - err = snd_emu10k1_voice_alloc(epcm->emu, - epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX, - 1, - &epcm->extra); - if (err < 0) { - /* - printk(KERN_DEBUG "pcm_channel_alloc: " - "failed extra: voices=%d, frame=%d\n", - voices, frame); - */ - for (i = 0; i < voices; i++) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); - epcm->voices[i] = NULL; - } - return err; - } - epcm->extra->epcm = epcm; - epcm->extra->interrupt = snd_emu10k1_pcm_interrupt; - } - return 0; -} - -static unsigned int capture_period_sizes[31] = { - 384, 448, 512, 640, - 384*2, 448*2, 512*2, 640*2, - 384*4, 448*4, 512*4, 640*4, - 384*8, 448*8, 512*8, 640*8, - 384*16, 448*16, 512*16, 640*16, - 384*32, 448*32, 512*32, 640*32, - 384*64, 448*64, 512*64, 640*64, - 384*128,448*128,512*128 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_capture_period_sizes = { - .count = 31, - .list = capture_period_sizes, - .mask = 0 -}; - -static unsigned int capture_rates[8] = { - 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_capture_rates = { - .count = 8, - .list = capture_rates, - .mask = 0 -}; - -static unsigned int snd_emu10k1_capture_rate_reg(unsigned int rate) -{ - switch (rate) { - case 8000: return ADCCR_SAMPLERATE_8; - case 11025: return ADCCR_SAMPLERATE_11; - case 16000: return ADCCR_SAMPLERATE_16; - case 22050: return ADCCR_SAMPLERATE_22; - case 24000: return ADCCR_SAMPLERATE_24; - case 32000: return ADCCR_SAMPLERATE_32; - case 44100: return ADCCR_SAMPLERATE_44; - case 48000: return ADCCR_SAMPLERATE_48; - default: - snd_BUG(); - return ADCCR_SAMPLERATE_8; - } -} - -static unsigned int snd_emu10k1_audigy_capture_rate_reg(unsigned int rate) -{ - switch (rate) { - case 8000: return A_ADCCR_SAMPLERATE_8; - case 11025: return A_ADCCR_SAMPLERATE_11; - case 12000: return A_ADCCR_SAMPLERATE_12; /* really supported? */ - case 16000: return ADCCR_SAMPLERATE_16; - case 22050: return ADCCR_SAMPLERATE_22; - case 24000: return ADCCR_SAMPLERATE_24; - case 32000: return ADCCR_SAMPLERATE_32; - case 44100: return ADCCR_SAMPLERATE_44; - case 48000: return ADCCR_SAMPLERATE_48; - default: - snd_BUG(); - return A_ADCCR_SAMPLERATE_8; - } -} - -static unsigned int emu10k1_calc_pitch_target(unsigned int rate) -{ - unsigned int pitch_target; - - pitch_target = (rate << 8) / 375; - pitch_target = (pitch_target >> 1) + (pitch_target & 1); - return pitch_target; -} - -#define PITCH_48000 0x00004000 -#define PITCH_96000 0x00008000 -#define PITCH_85000 0x00007155 -#define PITCH_80726 0x00006ba2 -#define PITCH_67882 0x00005a82 -#define PITCH_57081 0x00004c1c - -static unsigned int emu10k1_select_interprom(unsigned int pitch_target) -{ - if (pitch_target == PITCH_48000) - return CCCA_INTERPROM_0; - else if (pitch_target < PITCH_48000) - return CCCA_INTERPROM_1; - else if (pitch_target >= PITCH_96000) - return CCCA_INTERPROM_0; - else if (pitch_target >= PITCH_85000) - return CCCA_INTERPROM_6; - else if (pitch_target >= PITCH_80726) - return CCCA_INTERPROM_5; - else if (pitch_target >= PITCH_67882) - return CCCA_INTERPROM_4; - else if (pitch_target >= PITCH_57081) - return CCCA_INTERPROM_3; - else - return CCCA_INTERPROM_2; -} - -/* - * calculate cache invalidate size - * - * stereo: channel is stereo - * w_16: using 16bit samples - * - * returns: cache invalidate size in samples - */ -static inline int emu10k1_ccis(int stereo, int w_16) -{ - if (w_16) { - return stereo ? 24 : 26; - } else { - return stereo ? 24*2 : 26*2; - } -} - -static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu, - int master, int extra, - struct snd_emu10k1_voice *evoice, - unsigned int start_addr, - unsigned int end_addr, - struct snd_emu10k1_pcm_mixer *mix) -{ - struct snd_pcm_substream *substream = evoice->epcm->substream; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int silent_page, tmp; - int voice, stereo, w_16; - unsigned char attn, send_amount[8]; - unsigned char send_routing[8]; - unsigned long flags; - unsigned int pitch_target; - unsigned int ccis; - - voice = evoice->number; - stereo = runtime->channels == 2; - w_16 = snd_pcm_format_width(runtime->format) == 16; - - if (!extra && stereo) { - start_addr >>= 1; - end_addr >>= 1; - } - if (w_16) { - start_addr >>= 1; - end_addr >>= 1; - } - - spin_lock_irqsave(&emu->reg_lock, flags); - - /* volume parameters */ - if (extra) { - attn = 0; - memset(send_routing, 0, sizeof(send_routing)); - send_routing[0] = 0; - send_routing[1] = 1; - send_routing[2] = 2; - send_routing[3] = 3; - memset(send_amount, 0, sizeof(send_amount)); - } else { - /* mono, left, right (master voice = left) */ - tmp = stereo ? (master ? 1 : 2) : 0; - memcpy(send_routing, &mix->send_routing[tmp][0], 8); - memcpy(send_amount, &mix->send_volume[tmp][0], 8); - } - - ccis = emu10k1_ccis(stereo, w_16); - - if (master) { - evoice->epcm->ccca_start_addr = start_addr + ccis; - if (extra) { - start_addr += ccis; - end_addr += ccis + emu->delay_pcm_irq; - } - if (stereo && !extra) { - snd_emu10k1_ptr_write(emu, CPF, voice, CPF_STEREO_MASK); - snd_emu10k1_ptr_write(emu, CPF, (voice + 1), CPF_STEREO_MASK); - } else { - snd_emu10k1_ptr_write(emu, CPF, voice, 0); - } - } - - /* setup routing */ - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXRT1, voice, - snd_emu10k1_compose_audigy_fxrt1(send_routing)); - snd_emu10k1_ptr_write(emu, A_FXRT2, voice, - snd_emu10k1_compose_audigy_fxrt2(send_routing)); - snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, - ((unsigned int)send_amount[4] << 24) | - ((unsigned int)send_amount[5] << 16) | - ((unsigned int)send_amount[6] << 8) | - (unsigned int)send_amount[7]); - } else - snd_emu10k1_ptr_write(emu, FXRT, voice, - snd_emu10k1_compose_send_routing(send_routing)); - /* Stop CA */ - /* Assumption that PT is already 0 so no harm overwriting */ - snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); - snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); - snd_emu10k1_ptr_write(emu, PSST, voice, - (start_addr + (extra ? emu->delay_pcm_irq : 0)) | - (send_amount[2] << 24)); - if (emu->card_capabilities->emu_model) - pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ - else - pitch_target = emu10k1_calc_pitch_target(runtime->rate); - if (extra) - snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr | - emu10k1_select_interprom(pitch_target) | - (w_16 ? 0 : CCCA_8BITSELECT)); - else - snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) | - emu10k1_select_interprom(pitch_target) | - (w_16 ? 0 : CCCA_8BITSELECT)); - /* Clear filter delay memory */ - snd_emu10k1_ptr_write(emu, Z1, voice, 0); - snd_emu10k1_ptr_write(emu, Z2, voice, 0); - /* invalidate maps */ - silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK; - snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); - snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); - /* modulation envelope */ - snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff); - snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff); - snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0); - snd_emu10k1_ptr_write(emu, DCYSUSM, voice, 0x007f); - snd_emu10k1_ptr_write(emu, LFOVAL1, voice, 0x8000); - snd_emu10k1_ptr_write(emu, LFOVAL2, voice, 0x8000); - snd_emu10k1_ptr_write(emu, FMMOD, voice, 0); - snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0); - snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0); - snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000); - /* volume envelope */ - snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f); - snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000); - /* filter envelope */ - snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f); - /* pitch envelope */ - snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0); - - spin_unlock_irqrestore(&emu->reg_lock, flags); -} - -static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int err; - - if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0) - return err; - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - if (err > 0) { /* change */ - int mapped; - if (epcm->memblk != NULL) - snd_emu10k1_free_pages(emu, epcm->memblk); - epcm->memblk = snd_emu10k1_alloc_pages(emu, substream); - epcm->start_addr = 0; - if (! epcm->memblk) - return -ENOMEM; - mapped = ((struct snd_emu10k1_memblk *)epcm->memblk)->mapped_page; - if (mapped < 0) - return -ENOMEM; - epcm->start_addr = mapped << PAGE_SHIFT; - } - return 0; -} - -static int snd_emu10k1_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm; - - if (runtime->private_data == NULL) - return 0; - epcm = runtime->private_data; - if (epcm->extra) { - snd_emu10k1_voice_free(epcm->emu, epcm->extra); - epcm->extra = NULL; - } - if (epcm->voices[1]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]); - epcm->voices[1] = NULL; - } - if (epcm->voices[0]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]); - epcm->voices[0] = NULL; - } - if (epcm->memblk) { - snd_emu10k1_free_pages(emu, epcm->memblk); - epcm->memblk = NULL; - epcm->start_addr = 0; - } - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm; - int i; - - if (runtime->private_data == NULL) - return 0; - epcm = runtime->private_data; - if (epcm->extra) { - snd_emu10k1_voice_free(epcm->emu, epcm->extra); - epcm->extra = NULL; - } - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - if (epcm->voices[i]) { - snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); - epcm->voices[i] = NULL; - } - } - if (epcm->memblk) { - snd_emu10k1_free_pages(emu, epcm->memblk); - epcm->memblk = NULL; - epcm->start_addr = 0; - } - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_emu10k1_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int start_addr, end_addr; - - start_addr = epcm->start_addr; - end_addr = snd_pcm_lib_period_bytes(substream); - if (runtime->channels == 2) { - start_addr >>= 1; - end_addr >>= 1; - } - end_addr += start_addr; - snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, - start_addr, end_addr, NULL); - start_addr = epcm->start_addr; - end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); - snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0], - start_addr, end_addr, - &emu->pcm_mixer[substream->number]); - if (epcm->voices[1]) - snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[1], - start_addr, end_addr, - &emu->pcm_mixer[substream->number]); - return 0; -} - -static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int start_addr, end_addr; - unsigned int channel_size; - int i; - - start_addr = epcm->start_addr; - end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream); - - /* - * the kX driver leaves some space between voices - */ - channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK; - - snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra, - start_addr, start_addr + (channel_size / 2), NULL); - - /* only difference with the master voice is we use it for the pointer */ - snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0], - start_addr, start_addr + channel_size, - &emu->efx_pcm_mixer[0]); - - start_addr += channel_size; - for (i = 1; i < NUM_EFX_PLAYBACK; i++) { - snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i], - start_addr, start_addr + channel_size, - &emu->efx_pcm_mixer[i]); - start_addr += channel_size; - } - - return 0; -} - -static struct snd_pcm_hardware snd_emu10k1_efx_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = NUM_EFX_PLAYBACK, - .channels_max = NUM_EFX_PLAYBACK, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 64, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static int snd_emu10k1_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_emu10k1_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_emu10k1_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int idx; - - /* zeroing the buffer size will stop capture */ - snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0); - switch (epcm->type) { - case CAPTURE_AC97ADC: - snd_emu10k1_ptr_write(emu, ADCCR, 0, 0); - break; - case CAPTURE_EFX: - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0); - snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0); - } else - snd_emu10k1_ptr_write(emu, FXWC, 0, 0); - break; - default: - break; - } - snd_emu10k1_ptr_write(emu, epcm->capture_ba_reg, 0, runtime->dma_addr); - epcm->capture_bufsize = snd_pcm_lib_buffer_bytes(substream); - epcm->capture_bs_val = 0; - for (idx = 0; idx < 31; idx++) { - if (capture_period_sizes[idx] == epcm->capture_bufsize) { - epcm->capture_bs_val = idx + 1; - break; - } - } - if (epcm->capture_bs_val == 0) { - snd_BUG(); - epcm->capture_bs_val++; - } - if (epcm->type == CAPTURE_AC97ADC) { - epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE; - if (runtime->channels > 1) - epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE; - epcm->capture_cr_val |= emu->audigy ? - snd_emu10k1_audigy_capture_rate_reg(runtime->rate) : - snd_emu10k1_capture_rate_reg(runtime->rate); - } - return 0; -} - -static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int extra, struct snd_emu10k1_voice *evoice) -{ - struct snd_pcm_runtime *runtime; - unsigned int voice, stereo, i, ccis, cra = 64, cs, sample; - - if (evoice == NULL) - return; - runtime = evoice->epcm->substream->runtime; - voice = evoice->number; - stereo = (!extra && runtime->channels == 2); - sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080; - ccis = emu10k1_ccis(stereo, sample == 0); - /* set cs to 2 * number of cache registers beside the invalidated */ - cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1; - if (cs > 16) cs = 16; - for (i = 0; i < cs; i++) { - snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample); - if (stereo) { - snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample); - } - } - /* reset cache */ - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0); - snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra); - if (stereo) { - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0); - snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra); - } - /* fill cache */ - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis); - if (stereo) { - snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis); - } -} - -static void snd_emu10k1_playback_prepare_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice, - int master, int extra, - struct snd_emu10k1_pcm_mixer *mix) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned int attn, vattn; - unsigned int voice, tmp; - - if (evoice == NULL) /* skip second voice for mono */ - return; - substream = evoice->epcm->substream; - runtime = substream->runtime; - voice = evoice->number; - - attn = extra ? 0 : 0x00ff; - tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0; - vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0; - snd_emu10k1_ptr_write(emu, IFATN, voice, attn); - snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | 0xffff); - snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | 0xffff); - snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f); - snd_emu10k1_voice_clear_loop_stop(emu, voice); -} - -static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice, int master, int extra) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - unsigned int voice, pitch, pitch_target; - - if (evoice == NULL) /* skip second voice for mono */ - return; - substream = evoice->epcm->substream; - runtime = substream->runtime; - voice = evoice->number; - - pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8; - if (emu->card_capabilities->emu_model) - pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */ - else - pitch_target = emu10k1_calc_pitch_target(runtime->rate); - snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target); - if (master || evoice->epcm->type == PLAYBACK_EFX) - snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target); - snd_emu10k1_ptr_write(emu, IP, voice, pitch); - if (extra) - snd_emu10k1_voice_intr_enable(emu, voice); -} - -static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice) -{ - unsigned int voice; - - if (evoice == NULL) - return; - voice = evoice->number; - snd_emu10k1_voice_intr_disable(emu, voice); - snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0); - snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0); - snd_emu10k1_ptr_write(emu, IFATN, voice, 0xffff); - snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff); - snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff); - snd_emu10k1_ptr_write(emu, IP, voice, 0); -} - -static inline void snd_emu10k1_playback_mangle_extra(struct snd_emu10k1 *emu, - struct snd_emu10k1_pcm *epcm, - struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) -{ - unsigned int ptr, period_pos; - - /* try to sychronize the current position for the interrupt - source voice */ - period_pos = runtime->status->hw_ptr - runtime->hw_ptr_interrupt; - period_pos %= runtime->period_size; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->extra->number); - ptr &= ~0x00ffffff; - ptr |= epcm->ccca_start_addr + period_pos; - snd_emu10k1_ptr_write(emu, CCCA, epcm->extra->number, ptr); -} - -static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - struct snd_emu10k1_pcm_mixer *mix; - int result = 0; - - /* - printk(KERN_DEBUG "trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", - (int)emu, cmd, substream->ops->pointer(substream)) - */ - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* do we need this? */ - snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]); - /* follow thru */ - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) - snd_emu10k1_playback_mangle_extra(emu, epcm, substream, runtime); - mix = &emu->pcm_mixer[substream->number]; - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix); - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix); - snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL); - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0); - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0); - snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1); - epcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - epcm->running = 0; - snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]); - snd_emu10k1_playback_stop_voice(emu, epcm->voices[1]); - snd_emu10k1_playback_stop_voice(emu, epcm->extra); - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&emu->reg_lock); - return result; -} - -static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int result = 0; - - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - /* hmm this should cause full and half full interrupt to be raised? */ - outl(epcm->capture_ipr, emu->port + IPR); - snd_emu10k1_intr_enable(emu, epcm->capture_inte); - /* - printk(KERN_DEBUG "adccr = 0x%x, adcbs = 0x%x\n", - epcm->adccr, epcm->adcbs); - */ - switch (epcm->type) { - case CAPTURE_AC97ADC: - snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val); - break; - case CAPTURE_EFX: - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val); - snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2); - snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2); - } else - snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val); - break; - default: - break; - } - snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, epcm->capture_bs_val); - epcm->running = 1; - epcm->first_ptr = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - epcm->running = 0; - snd_emu10k1_intr_disable(emu, epcm->capture_inte); - outl(epcm->capture_ipr, emu->port + IPR); - snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0); - switch (epcm->type) { - case CAPTURE_AC97ADC: - snd_emu10k1_ptr_write(emu, ADCCR, 0, 0); - break; - case CAPTURE_EFX: - if (emu->audigy) { - snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0); - snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0); - } else - snd_emu10k1_ptr_write(emu, FXWC, 0, 0); - break; - default: - break; - } - break; - default: - result = -EINVAL; - } - spin_unlock(&emu->reg_lock); - return result; -} - -static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int ptr; - - if (!epcm->running) - return 0; - ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff; -#if 0 /* Perex's code */ - ptr += runtime->buffer_size; - ptr -= epcm->ccca_start_addr; - ptr %= runtime->buffer_size; -#else /* EMU10K1 Open Source code from Creative */ - if (ptr < epcm->ccca_start_addr) - ptr += runtime->buffer_size - epcm->ccca_start_addr; - else { - ptr -= epcm->ccca_start_addr; - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - } -#endif - /* - printk(KERN_DEBUG - "ptr = 0x%lx, buffer_size = 0x%lx, period_size = 0x%lx\n", - (long)ptr, (long)runtime->buffer_size, - (long)runtime->period_size); - */ - return ptr; -} - - -static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int i; - int result = 0; - - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* prepare voices */ - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]); - } - snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); - - /* follow thru */ - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL); - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0, - &emu->efx_pcm_mixer[0]); - for (i = 1; i < NUM_EFX_PLAYBACK; i++) - snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0, - &emu->efx_pcm_mixer[i]); - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0); - snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1); - for (i = 1; i < NUM_EFX_PLAYBACK; i++) - snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0); - epcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - epcm->running = 0; - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]); - } - snd_emu10k1_playback_stop_voice(emu, epcm->extra); - break; - default: - result = -EINVAL; - break; - } - spin_unlock(&emu->reg_lock); - return result; -} - - -static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - unsigned int ptr; - - if (!epcm->running) - return 0; - if (epcm->first_ptr) { - udelay(50); /* hack, it takes awhile until capture is started */ - epcm->first_ptr = 0; - } - ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff; - return bytes_to_frames(runtime, ptr); -} - -/* - * Playback support device description - */ - -static struct snd_pcm_hardware snd_emu10k1_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000, - .rate_min = 4000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 64, - .period_bytes_max = (128*1024), - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * Capture support device description - */ - -static struct snd_pcm_hardware snd_emu10k1_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_8000_48000, - .rate_min = 8000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 384, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_emu10k1_capture_efx = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000, - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = (64*1024), - .period_bytes_min = 384, - .period_bytes_max = (64*1024), - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -/* - * - */ - -static void snd_emu10k1_pcm_mixer_notify1(struct snd_emu10k1 *emu, struct snd_kcontrol *kctl, int idx, int activate) -{ - struct snd_ctl_elem_id id; - - if (! kctl) - return; - if (activate) - kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - else - kctl->vd[idx].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - snd_ctl_build_ioff(&id, kctl, idx)); -} - -static void snd_emu10k1_pcm_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate) -{ - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate); -} - -static void snd_emu10k1_pcm_efx_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate) -{ - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate); - snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate); -} - -static void snd_emu10k1_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm_mixer *mix; - int i; - - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - mix = &emu->efx_pcm_mixer[i]; - mix->epcm = NULL; - snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0); - } - return 0; -} - -static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_emu10k1_pcm_mixer *mix; - struct snd_pcm_runtime *runtime = substream->runtime; - int i; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = PLAYBACK_EFX; - epcm->substream = substream; - - emu->pcm_playback_efx_substream = substream; - - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_efx_playback; - - for (i = 0; i < NUM_EFX_PLAYBACK; i++) { - mix = &emu->efx_pcm_mixer[i]; - mix->send_routing[0][0] = i; - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = 255; - mix->attn[0] = 0xffff; - mix->epcm = epcm; - snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1); - } - return 0; -} - -static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_emu10k1_pcm_mixer *mix; - struct snd_pcm_runtime *runtime = substream->runtime; - int i, err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = PLAYBACK_EMUVOICE; - epcm->substream = substream; - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_playback; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) { - kfree(epcm); - return err; - } - if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) { - kfree(epcm); - return err; - } - err = snd_pcm_hw_rule_noresample(runtime, 48000); - if (err < 0) { - kfree(epcm); - return err; - } - mix = &emu->pcm_mixer[substream->number]; - for (i = 0; i < 4; i++) - mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i; - memset(&mix->send_volume, 0, sizeof(mix->send_volume)); - mix->send_volume[0][0] = mix->send_volume[0][1] = - mix->send_volume[1][0] = mix->send_volume[2][1] = 255; - mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; - mix->epcm = epcm; - snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1); - return 0; -} - -static int snd_emu10k1_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[substream->number]; - - mix->epcm = NULL; - snd_emu10k1_pcm_mixer_notify(emu, substream->number, 0); - return 0; -} - -static int snd_emu10k1_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = CAPTURE_AC97ADC; - epcm->substream = substream; - epcm->capture_ipr = IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL; - epcm->capture_inte = INTE_ADCBUFENABLE; - epcm->capture_ba_reg = ADCBA; - epcm->capture_bs_reg = ADCBS; - epcm->capture_idx_reg = emu->audigy ? A_ADCIDX : ADCIDX; - runtime->private_data = epcm; - runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_capture; - emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt; - emu->pcm_capture_substream = substream; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes); - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates); - return 0; -} - -static int snd_emu10k1_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - - emu->capture_interrupt = NULL; - emu->pcm_capture_substream = NULL; - return 0; -} - -static int snd_emu10k1_capture_mic_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = CAPTURE_AC97MIC; - epcm->substream = substream; - epcm->capture_ipr = IPR_MICBUFFULL|IPR_MICBUFHALFFULL; - epcm->capture_inte = INTE_MICBUFENABLE; - epcm->capture_ba_reg = MICBA; - epcm->capture_bs_reg = MICBS; - epcm->capture_idx_reg = emu->audigy ? A_MICIDX : MICIDX; - substream->runtime->private_data = epcm; - substream->runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_capture; - runtime->hw.rates = SNDRV_PCM_RATE_8000; - runtime->hw.rate_min = runtime->hw.rate_max = 8000; - runtime->hw.channels_min = 1; - emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt; - emu->pcm_capture_mic_substream = substream; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes); - return 0; -} - -static int snd_emu10k1_capture_mic_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - - emu->capture_interrupt = NULL; - emu->pcm_capture_mic_substream = NULL; - return 0; -} - -static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int nefx = emu->audigy ? 64 : 32; - int idx; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->type = CAPTURE_EFX; - epcm->substream = substream; - epcm->capture_ipr = IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL; - epcm->capture_inte = INTE_EFXBUFENABLE; - epcm->capture_ba_reg = FXBA; - epcm->capture_bs_reg = FXBS; - epcm->capture_idx_reg = FXIDX; - substream->runtime->private_data = epcm; - substream->runtime->private_free = snd_emu10k1_pcm_free_substream; - runtime->hw = snd_emu10k1_capture_efx; - runtime->hw.rates = SNDRV_PCM_RATE_48000; - runtime->hw.rate_min = runtime->hw.rate_max = 48000; - spin_lock_irq(&emu->reg_lock); - if (emu->card_capabilities->emu_model) { - /* Nb. of channels has been increased to 16 */ - /* TODO - * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE - * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | - * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | - * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 - * rate_min = 44100, - * rate_max = 192000, - * channels_min = 16, - * channels_max = 16, - * Need to add mixer control to fix sample rate - * - * There are 32 mono channels of 16bits each. - * 24bit Audio uses 2x channels over 16bit - * 96kHz uses 2x channels over 48kHz - * 192kHz uses 4x channels over 48kHz - * So, for 48kHz 24bit, one has 16 channels - * for 96kHz 24bit, one has 8 channels - * for 192kHz 24bit, one has 4 channels - * - */ -#if 1 - switch (emu->emu1010.internal_clock) { - case 0: - /* For 44.1kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_44100; - runtime->hw.rate_min = runtime->hw.rate_max = 44100; - runtime->hw.channels_min = - runtime->hw.channels_max = 16; - break; - case 1: - /* For 48kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_48000; - runtime->hw.rate_min = runtime->hw.rate_max = 48000; - runtime->hw.channels_min = - runtime->hw.channels_max = 16; - break; - }; -#endif -#if 0 - /* For 96kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_96000; - runtime->hw.rate_min = runtime->hw.rate_max = 96000; - runtime->hw.channels_min = runtime->hw.channels_max = 4; -#endif -#if 0 - /* For 192kHz */ - runtime->hw.rates = SNDRV_PCM_RATE_192000; - runtime->hw.rate_min = runtime->hw.rate_max = 192000; - runtime->hw.channels_min = runtime->hw.channels_max = 2; -#endif - runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; - /* efx_voices_mask[0] is expected to be zero - * efx_voices_mask[1] is expected to have 32bits set - */ - } else { - runtime->hw.channels_min = runtime->hw.channels_max = 0; - for (idx = 0; idx < nefx; idx++) { - if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) { - runtime->hw.channels_min++; - runtime->hw.channels_max++; - } - } - } - epcm->capture_cr_val = emu->efx_voices_mask[0]; - epcm->capture_cr_val2 = emu->efx_voices_mask[1]; - spin_unlock_irq(&emu->reg_lock); - emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt; - emu->pcm_capture_efx_substream = substream; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes); - return 0; -} - -static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - - emu->capture_interrupt = NULL; - emu->pcm_capture_efx_substream = NULL; - return 0; -} - -static struct snd_pcm_ops snd_emu10k1_playback_ops = { - .open = snd_emu10k1_playback_open, - .close = snd_emu10k1_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_playback_hw_params, - .hw_free = snd_emu10k1_playback_hw_free, - .prepare = snd_emu10k1_playback_prepare, - .trigger = snd_emu10k1_playback_trigger, - .pointer = snd_emu10k1_playback_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -static struct snd_pcm_ops snd_emu10k1_capture_ops = { - .open = snd_emu10k1_capture_open, - .close = snd_emu10k1_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_capture_hw_params, - .hw_free = snd_emu10k1_capture_hw_free, - .prepare = snd_emu10k1_capture_prepare, - .trigger = snd_emu10k1_capture_trigger, - .pointer = snd_emu10k1_capture_pointer, -}; - -/* EFX playback */ -static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { - .open = snd_emu10k1_efx_playback_open, - .close = snd_emu10k1_efx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_playback_hw_params, - .hw_free = snd_emu10k1_efx_playback_hw_free, - .prepare = snd_emu10k1_efx_playback_prepare, - .trigger = snd_emu10k1_efx_playback_trigger, - .pointer = snd_emu10k1_efx_playback_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; - -int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_ops); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, "ADC Capture/Standard PCM Playback"); - emu->pcm = pcm; - - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) - return err; - - for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) - snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -int __devinit snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_efx_playback_ops); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, "Multichannel Playback"); - emu->pcm_multi = pcm; - - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0) - return err; - - if (rpcm) - *rpcm = pcm; - - return 0; -} - - -static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = { - .open = snd_emu10k1_capture_mic_open, - .close = snd_emu10k1_capture_mic_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_capture_hw_params, - .hw_free = snd_emu10k1_capture_hw_free, - .prepare = snd_emu10k1_capture_prepare, - .trigger = snd_emu10k1_capture_trigger, - .pointer = snd_emu10k1_capture_pointer, -}; - -int __devinit snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, "Mic Capture"); - emu->pcm_mic = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -static int snd_emu10k1_pcm_efx_voices_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int nefx = emu->audigy ? 64 : 32; - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = nefx; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_emu10k1_pcm_efx_voices_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int nefx = emu->audigy ? 64 : 32; - int idx; - - spin_lock_irq(&emu->reg_lock); - for (idx = 0; idx < nefx; idx++) - ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0; - spin_unlock_irq(&emu->reg_lock); - return 0; -} - -static int snd_emu10k1_pcm_efx_voices_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int nval[2], bits; - int nefx = emu->audigy ? 64 : 32; - int nefxb = emu->audigy ? 7 : 6; - int change, idx; - - nval[0] = nval[1] = 0; - for (idx = 0, bits = 0; idx < nefx; idx++) - if (ucontrol->value.integer.value[idx]) { - nval[idx / 32] |= 1 << (idx % 32); - bits++; - } - - for (idx = 0; idx < nefxb; idx++) - if (1 << idx == bits) - break; - - if (idx >= nefxb) - return -EINVAL; - - spin_lock_irq(&emu->reg_lock); - change = (nval[0] != emu->efx_voices_mask[0]) || - (nval[1] != emu->efx_voices_mask[1]); - emu->efx_voices_mask[0] = nval[0]; - emu->efx_voices_mask[1] = nval[1]; - spin_unlock_irq(&emu->reg_lock); - return change; -} - -static struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "Captured FX8010 Outputs", - .info = snd_emu10k1_pcm_efx_voices_mask_info, - .get = snd_emu10k1_pcm_efx_voices_mask_get, - .put = snd_emu10k1_pcm_efx_voices_mask_put -}; - -static struct snd_pcm_ops snd_emu10k1_capture_efx_ops = { - .open = snd_emu10k1_capture_efx_open, - .close = snd_emu10k1_capture_efx_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_capture_hw_params, - .hw_free = snd_emu10k1_capture_hw_free, - .prepare = snd_emu10k1_capture_prepare, - .trigger = snd_emu10k1_capture_trigger, - .pointer = snd_emu10k1_capture_pointer, -}; - - -/* EFX playback */ - -#define INITIAL_TRAM_SHIFT 14 -#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1) - -static void snd_emu10k1_fx8010_playback_irq(struct snd_emu10k1 *emu, void *private_data) -{ - struct snd_pcm_substream *substream = private_data; - snd_pcm_period_elapsed(substream); -} - -static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left, - unsigned short *dst_right, - unsigned short *src, - unsigned int count, - unsigned int tram_shift) -{ - /* - printk(KERN_DEBUG "tram_poke1: dst_left = 0x%p, dst_right = 0x%p, " - "src = 0x%p, count = 0x%x\n", - dst_left, dst_right, src, count); - */ - if ((tram_shift & 1) == 0) { - while (count--) { - *dst_left-- = *src++; - *dst_right-- = *src++; - } - } else { - while (count--) { - *dst_right-- = *src++; - *dst_left-- = *src++; - } - } -} - -static void fx8010_pb_trans_copy(struct snd_pcm_substream *substream, - struct snd_pcm_indirect *rec, size_t bytes) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - unsigned int tram_size = pcm->buffer_size; - unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data); - unsigned int frames = bytes >> 2, count; - unsigned int tram_pos = pcm->tram_pos; - unsigned int tram_shift = pcm->tram_shift; - - while (frames > tram_pos) { - count = tram_pos + 1; - snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos, - (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2, - src, count, tram_shift); - src += count * 2; - frames -= count; - tram_pos = (tram_size / 2) - 1; - tram_shift++; - } - snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos, - (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2, - src, frames, tram_shift); - tram_pos -= frames; - pcm->tram_pos = tram_pos; - pcm->tram_shift = tram_shift; -} - -static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - - snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy); - return 0; -} - -static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_emu10k1_fx8010_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - unsigned int i; - - for (i = 0; i < pcm->channels; i++) - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0); - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - unsigned int i; - - /* - printk(KERN_DEBUG "prepare: etram_pages = 0x%p, dma_area = 0x%x, " - "buffer_size = 0x%x (0x%x)\n", - emu->fx8010.etram_pages, runtime->dma_area, - runtime->buffer_size, runtime->buffer_size << 2); - */ - memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec)); - pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */ - pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); - pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size); - pcm->tram_shift = 0; - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0); /* reset */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0); /* reset */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size); - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0); /* reset ptr number */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size); - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size); - for (i = 0; i < pcm->channels; i++) - snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels)); - return 0; -} - -static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - int result = 0; - - spin_lock(&emu->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* follow thru */ - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: -#ifdef EMU10K1_SET_AC3_IEC958 - { - int i; - for (i = 0; i < 3; i++) { - unsigned int bits; - bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | - SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | - 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA; - snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits); - } - } -#endif - result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq); - if (result < 0) - goto __err; - snd_emu10k1_fx8010_playback_transfer(substream); /* roll the ball */ - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL; - snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0); - pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size); - pcm->tram_shift = 0; - break; - default: - result = -EINVAL; - break; - } - __err: - spin_unlock(&emu->reg_lock); - return result; -} - -static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - size_t ptr; /* byte pointer */ - - if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0)) - return 0; - ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2; - return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr); -} - -static struct snd_pcm_hardware snd_emu10k1_fx8010_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 1024, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_emu10k1_fx8010_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - - runtime->hw = snd_emu10k1_fx8010_playback; - runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels; - runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2; - spin_lock_irq(&emu->reg_lock); - if (pcm->valid == 0) { - spin_unlock_irq(&emu->reg_lock); - return -ENODEV; - } - pcm->opened = 1; - spin_unlock_irq(&emu->reg_lock); - return 0; -} - -static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - - spin_lock_irq(&emu->reg_lock); - pcm->opened = 0; - spin_unlock_irq(&emu->reg_lock); - return 0; -} - -static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = { - .open = snd_emu10k1_fx8010_playback_open, - .close = snd_emu10k1_fx8010_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_emu10k1_fx8010_playback_hw_params, - .hw_free = snd_emu10k1_fx8010_playback_hw_free, - .prepare = snd_emu10k1_fx8010_playback_prepare, - .trigger = snd_emu10k1_fx8010_playback_trigger, - .pointer = snd_emu10k1_fx8010_playback_pointer, - .ack = snd_emu10k1_fx8010_playback_transfer, -}; - -int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm) -{ - struct snd_pcm *pcm; - struct snd_kcontrol *kctl; - int err; - - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0) - return err; - - pcm->private_data = emu; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops); - - pcm->info_flags = 0; - strcpy(pcm->name, "Multichannel Capture/PT Playback"); - emu->pcm_efx = pcm; - if (rpcm) - *rpcm = pcm; - - /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs - * to these - */ - - /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ - if (emu->audigy) { - emu->efx_voices_mask[0] = 0; - if (emu->card_capabilities->emu_model) - /* Pavel Hofman - 32 voices will be used for - * capture (write mode) - - * each bit = corresponding voice - */ - emu->efx_voices_mask[1] = 0xffffffff; - else - emu->efx_voices_mask[1] = 0xffff; - } else { - emu->efx_voices_mask[0] = 0xffff0000; - emu->efx_voices_mask[1] = 0; - } - /* For emu1010, the control has to set 32 upper bits (voices) - * out of the 64 bits (voices) to true for the 16-channels capture - * to work correctly. Correct A_FXWC2 initial value (0xffffffff) - * is already defined but the snd_emu10k1_pcm_efx_voices_mask - * control can override this register's value. - */ - kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu); - if (!kctl) - return -ENOMEM; - kctl->id.device = device; - snd_ctl_add(emu->card, kctl); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c b/ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c deleted file mode 100644 index bc38dd4d..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips / proc interface routines - * - * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> - * Added EMU 1010 support. - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/slab.h> -#include <linux/init.h> -#include <sound/core.h> -#include <sound/emu10k1.h> -#include "p16v.h" - -#ifdef CONFIG_PROC_FS -static void snd_emu10k1_proc_spdif_status(struct snd_emu10k1 * emu, - struct snd_info_buffer *buffer, - char *title, - int status_reg, - int rate_reg) -{ - static char *clkaccy[4] = { "1000ppm", "50ppm", "variable", "unknown" }; - static int samplerate[16] = { 44100, 1, 48000, 32000, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - static char *channel[16] = { "unspec", "left", "right", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" }; - static char *emphasis[8] = { "none", "50/15 usec 2 channel", "2", "3", "4", "5", "6", "7" }; - unsigned int status, rate = 0; - - status = snd_emu10k1_ptr_read(emu, status_reg, 0); - - snd_iprintf(buffer, "\n%s\n", title); - - if (status != 0xffffffff) { - snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no"); - snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no"); - snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no"); - snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]); - snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6); - snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8); - snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy"); - snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16); - snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]); - snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]); - snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]); - - if (rate_reg > 0) { - rate = snd_emu10k1_ptr_read(emu, rate_reg, 0); - snd_iprintf(buffer, "S/PDIF Valid : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off"); - snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off"); - snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off"); - /* From ((Rate * 48000 ) / 262144); */ - snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11); - } - } else { - snd_iprintf(buffer, "No signal detected.\n"); - } - -} - -static void snd_emu10k1_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - /* FIXME - output names are in emufx.c too */ - static char *creative_outs[32] = { - /* 00 */ "AC97 Left", - /* 01 */ "AC97 Right", - /* 02 */ "Optical IEC958 Left", - /* 03 */ "Optical IEC958 Right", - /* 04 */ "Center", - /* 05 */ "LFE", - /* 06 */ "Headphone Left", - /* 07 */ "Headphone Right", - /* 08 */ "Surround Left", - /* 09 */ "Surround Right", - /* 10 */ "PCM Capture Left", - /* 11 */ "PCM Capture Right", - /* 12 */ "MIC Capture", - /* 13 */ "AC97 Surround Left", - /* 14 */ "AC97 Surround Right", - /* 15 */ "???", - /* 16 */ "???", - /* 17 */ "Analog Center", - /* 18 */ "Analog LFE", - /* 19 */ "???", - /* 20 */ "???", - /* 21 */ "???", - /* 22 */ "???", - /* 23 */ "???", - /* 24 */ "???", - /* 25 */ "???", - /* 26 */ "???", - /* 27 */ "???", - /* 28 */ "???", - /* 29 */ "???", - /* 30 */ "???", - /* 31 */ "???" - }; - - static char *audigy_outs[64] = { - /* 00 */ "Digital Front Left", - /* 01 */ "Digital Front Right", - /* 02 */ "Digital Center", - /* 03 */ "Digital LEF", - /* 04 */ "Headphone Left", - /* 05 */ "Headphone Right", - /* 06 */ "Digital Rear Left", - /* 07 */ "Digital Rear Right", - /* 08 */ "Front Left", - /* 09 */ "Front Right", - /* 10 */ "Center", - /* 11 */ "LFE", - /* 12 */ "???", - /* 13 */ "???", - /* 14 */ "Rear Left", - /* 15 */ "Rear Right", - /* 16 */ "AC97 Front Left", - /* 17 */ "AC97 Front Right", - /* 18 */ "ADC Caputre Left", - /* 19 */ "ADC Capture Right", - /* 20 */ "???", - /* 21 */ "???", - /* 22 */ "???", - /* 23 */ "???", - /* 24 */ "???", - /* 25 */ "???", - /* 26 */ "???", - /* 27 */ "???", - /* 28 */ "???", - /* 29 */ "???", - /* 30 */ "???", - /* 31 */ "???", - /* 32 */ "FXBUS2_0", - /* 33 */ "FXBUS2_1", - /* 34 */ "FXBUS2_2", - /* 35 */ "FXBUS2_3", - /* 36 */ "FXBUS2_4", - /* 37 */ "FXBUS2_5", - /* 38 */ "FXBUS2_6", - /* 39 */ "FXBUS2_7", - /* 40 */ "FXBUS2_8", - /* 41 */ "FXBUS2_9", - /* 42 */ "FXBUS2_10", - /* 43 */ "FXBUS2_11", - /* 44 */ "FXBUS2_12", - /* 45 */ "FXBUS2_13", - /* 46 */ "FXBUS2_14", - /* 47 */ "FXBUS2_15", - /* 48 */ "FXBUS2_16", - /* 49 */ "FXBUS2_17", - /* 50 */ "FXBUS2_18", - /* 51 */ "FXBUS2_19", - /* 52 */ "FXBUS2_20", - /* 53 */ "FXBUS2_21", - /* 54 */ "FXBUS2_22", - /* 55 */ "FXBUS2_23", - /* 56 */ "FXBUS2_24", - /* 57 */ "FXBUS2_25", - /* 58 */ "FXBUS2_26", - /* 59 */ "FXBUS2_27", - /* 60 */ "FXBUS2_28", - /* 61 */ "FXBUS2_29", - /* 62 */ "FXBUS2_30", - /* 63 */ "FXBUS2_31" - }; - - struct snd_emu10k1 *emu = entry->private_data; - unsigned int val, val1; - int nefx = emu->audigy ? 64 : 32; - char **outputs = emu->audigy ? audigy_outs : creative_outs; - int idx; - - snd_iprintf(buffer, "EMU10K1\n\n"); - snd_iprintf(buffer, "Card : %s\n", - emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative")); - snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size); - snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2); - snd_iprintf(buffer, "\n"); - snd_iprintf(buffer, "Effect Send Routing :\n"); - for (idx = 0; idx < NUM_G; idx++) { - val = emu->audigy ? - snd_emu10k1_ptr_read(emu, A_FXRT1, idx) : - snd_emu10k1_ptr_read(emu, FXRT, idx); - val1 = emu->audigy ? - snd_emu10k1_ptr_read(emu, A_FXRT2, idx) : - 0; - if (emu->audigy) { - snd_iprintf(buffer, "Ch%i: A=%i, B=%i, C=%i, D=%i, ", - idx, - val & 0x3f, - (val >> 8) & 0x3f, - (val >> 16) & 0x3f, - (val >> 24) & 0x3f); - snd_iprintf(buffer, "E=%i, F=%i, G=%i, H=%i\n", - val1 & 0x3f, - (val1 >> 8) & 0x3f, - (val1 >> 16) & 0x3f, - (val1 >> 24) & 0x3f); - } else { - snd_iprintf(buffer, "Ch%i: A=%i, B=%i, C=%i, D=%i\n", - idx, - (val >> 16) & 0x0f, - (val >> 20) & 0x0f, - (val >> 24) & 0x0f, - (val >> 28) & 0x0f); - } - } - snd_iprintf(buffer, "\nCaptured FX Outputs :\n"); - for (idx = 0; idx < nefx; idx++) { - if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) - snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); - } - snd_iprintf(buffer, "\nAll FX Outputs :\n"); - for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++) - snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); -} - -static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - u32 value; - u32 value2; - unsigned long flags; - u32 rate; - - if (emu->card_capabilities->emu_model) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x38, &value); - spin_unlock_irqrestore(&emu->emu_lock, flags); - if ((value & 0x1) == 0) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x2a, &value); - snd_emu1010_fpga_read(emu, 0x2b, &value2); - spin_unlock_irqrestore(&emu->emu_lock, flags); - rate = 0x1770000 / (((value << 5) | value2)+1); - snd_iprintf(buffer, "ADAT Locked : %u\n", rate); - } else { - snd_iprintf(buffer, "ADAT Unlocked\n"); - } - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x20, &value); - spin_unlock_irqrestore(&emu->emu_lock, flags); - if ((value & 0x4) == 0) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, 0x28, &value); - snd_emu1010_fpga_read(emu, 0x29, &value2); - spin_unlock_irqrestore(&emu->emu_lock, flags); - rate = 0x1770000 / (((value << 5) | value2)+1); - snd_iprintf(buffer, "SPDIF Locked : %d\n", rate); - } else { - snd_iprintf(buffer, "SPDIF Unlocked\n"); - } - } else { - snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); - snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); - } -#if 0 - val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); - snd_iprintf(buffer, "\nZoomed Video\n"); - snd_iprintf(buffer, "Rate Locked : %s\n", val & SRCS_RATELOCKED ? "on" : "off"); - snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE); -#endif -} - -static void snd_emu10k1_proc_rates_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 }; - struct snd_emu10k1 *emu = entry->private_data; - unsigned int val, tmp, n; - val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0); - tmp = (val >> 16) & 0x8; - for (n = 0; n < 4; n++) { - tmp = val >> (16 + (n*4)); - if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]); - else snd_iprintf(buffer, "Channel %d: No input\n", n); - } -} - -static void snd_emu10k1_proc_acode_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - u32 pc; - struct snd_emu10k1 *emu = entry->private_data; - - snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name); - snd_iprintf(buffer, " Code dump :\n"); - for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) { - u32 low, high; - - low = snd_emu10k1_efx_read(emu, pc * 2); - high = snd_emu10k1_efx_read(emu, pc * 2 + 1); - if (emu->audigy) - snd_iprintf(buffer, " OP(0x%02x, 0x%03x, 0x%03x, 0x%03x, 0x%03x) /* 0x%04x: 0x%08x%08x */\n", - (high >> 24) & 0x0f, - (high >> 12) & 0x7ff, - (high >> 0) & 0x7ff, - (low >> 12) & 0x7ff, - (low >> 0) & 0x7ff, - pc, - high, low); - else - snd_iprintf(buffer, " OP(0x%02x, 0x%03x, 0x%03x, 0x%03x, 0x%03x) /* 0x%04x: 0x%08x%08x */\n", - (high >> 20) & 0x0f, - (high >> 10) & 0x3ff, - (high >> 0) & 0x3ff, - (low >> 10) & 0x3ff, - (low >> 0) & 0x3ff, - pc, - high, low); - } -} - -#define TOTAL_SIZE_GPR (0x100*4) -#define A_TOTAL_SIZE_GPR (0x200*4) -#define TOTAL_SIZE_TANKMEM_DATA (0xa0*4) -#define TOTAL_SIZE_TANKMEM_ADDR (0xa0*4) -#define A_TOTAL_SIZE_TANKMEM_DATA (0x100*4) -#define A_TOTAL_SIZE_TANKMEM_ADDR (0x100*4) -#define TOTAL_SIZE_CODE (0x200*8) -#define A_TOTAL_SIZE_CODE (0x400*8) - -static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned int offset; - int tram_addr = 0; - unsigned int *tmp; - long res; - unsigned int idx; - - if (!strcmp(entry->name, "fx8010_tram_addr")) { - offset = TANKMEMADDRREGBASE; - tram_addr = 1; - } else if (!strcmp(entry->name, "fx8010_tram_data")) { - offset = TANKMEMDATAREGBASE; - } else if (!strcmp(entry->name, "fx8010_code")) { - offset = emu->audigy ? A_MICROCODEBASE : MICROCODEBASE; - } else { - offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; - } - - tmp = kmalloc(count + 8, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - for (idx = 0; idx < ((pos & 3) + count + 3) >> 2; idx++) { - unsigned int val; - val = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); - if (tram_addr && emu->audigy) { - val >>= 11; - val |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20; - } - tmp[idx] = val; - } - if (copy_to_user(buf, ((char *)tmp) + (pos & 3), count)) - res = -EFAULT; - else - res = count; - kfree(tmp); - return res; -} - -static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - struct snd_emu10k1_voice *voice; - int idx; - - snd_iprintf(buffer, "ch\tuse\tpcm\tefx\tsynth\tmidi\n"); - for (idx = 0; idx < NUM_G; idx++) { - voice = &emu->voices[idx]; - snd_iprintf(buffer, "%i\t%i\t%i\t%i\t%i\t%i\n", - idx, - voice->use, - voice->pcm, - voice->efx, - voice->synth, - voice->midi); - } -} - -#ifdef CONFIG_SND_DEBUG -static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - u32 value; - unsigned long flags; - int i; - snd_iprintf(buffer, "EMU1010 Registers:\n\n"); - - for(i = 0; i < 0x40; i+=1) { - spin_lock_irqsave(&emu->emu_lock, flags); - snd_emu1010_fpga_read(emu, i, &value); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f); - } -} - -static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned long value; - unsigned long flags; - int i; - snd_iprintf(buffer, "IO Registers:\n\n"); - for(i = 0; i < 0x40; i+=4) { - spin_lock_irqsave(&emu->emu_lock, flags); - value = inl(emu->port + i); - spin_unlock_irqrestore(&emu->emu_lock, flags); - snd_iprintf(buffer, "%02X: %08lX\n", i, value); - } -} - -static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned long flags; - char line[64]; - u32 reg, val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x", ®, &val) != 2) - continue; - if (reg < 0x40 && val <= 0xffffffff) { - spin_lock_irqsave(&emu->emu_lock, flags); - outl(val, emu->port + (reg & 0xfffffffc)); - spin_unlock_irqrestore(&emu->emu_lock, flags); - } - } -} - -static unsigned int snd_ptr_read(struct snd_emu10k1 * emu, - unsigned int iobase, - unsigned int reg, - unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + iobase + PTR); - val = inl(emu->port + iobase + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -static void snd_ptr_write(struct snd_emu10k1 *emu, - unsigned int iobase, - unsigned int reg, - unsigned int chn, - unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + iobase + PTR); - outl(data, emu->port + iobase + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - - -static void snd_emu_proc_ptr_reg_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer, int iobase, int offset, int length, int voices) -{ - struct snd_emu10k1 *emu = entry->private_data; - unsigned long value; - int i,j; - if (offset+length > 0xa0) { - snd_iprintf(buffer, "Input values out of range\n"); - return; - } - snd_iprintf(buffer, "Registers 0x%x\n", iobase); - for(i = offset; i < offset+length; i++) { - snd_iprintf(buffer, "%02X: ",i); - for (j = 0; j < voices; j++) { - if(iobase == 0) - value = snd_ptr_read(emu, 0, i, j); - else - value = snd_ptr_read(emu, 0x20, i, j); - snd_iprintf(buffer, "%08lX ", value); - } - snd_iprintf(buffer, "\n"); - } -} - -static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry, - struct snd_info_buffer *buffer, int iobase) -{ - struct snd_emu10k1 *emu = entry->private_data; - char line[64]; - unsigned int reg, channel_id , val; - while (!snd_info_get_line(buffer, line, sizeof(line))) { - if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) - continue; - if (reg < 0xa0 && val <= 0xffffffff && channel_id <= 3) - snd_ptr_write(emu, iobase, reg, channel_id, val); - } -} - -static void snd_emu_proc_ptr_reg_write00(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_write(entry, buffer, 0); -} - -static void snd_emu_proc_ptr_reg_write20(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_write(entry, buffer, 0x20); -} - - -static void snd_emu_proc_ptr_reg_read00a(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40, 64); -} - -static void snd_emu_proc_ptr_reg_read00b(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40, 64); -} - -static void snd_emu_proc_ptr_reg_read20a(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40, 4); -} - -static void snd_emu_proc_ptr_reg_read20b(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40, 4); -} - -static void snd_emu_proc_ptr_reg_read20c(struct snd_info_entry *entry, - struct snd_info_buffer * buffer) -{ - snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x80, 0x20, 4); -} -#endif - -static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = { - .read = snd_emu10k1_fx8010_read, -}; - -int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) -{ - struct snd_info_entry *entry; -#ifdef CONFIG_SND_DEBUG - if (emu->card_capabilities->emu_model) { - if (! snd_card_proc_new(emu->card, "emu1010_regs", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read); - } - if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); - entry->c.text.write = snd_emu_proc_io_reg_write; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a); - entry->c.text.write = snd_emu_proc_ptr_reg_write00; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b); - entry->c.text.write = snd_emu_proc_ptr_reg_write00; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a); - entry->c.text.write = snd_emu_proc_ptr_reg_write20; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b); - entry->c.text.write = snd_emu_proc_ptr_reg_write20; - entry->mode |= S_IWUSR; - } - if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) { - snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c); - entry->c.text.write = snd_emu_proc_ptr_reg_write20; - entry->mode |= S_IWUSR; - } -#endif - - if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_read); - - if (emu->card_capabilities->emu10k2_chip) { - if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_spdif_read); - } - if (emu->card_capabilities->ca0151_chip) { - if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_rates_read); - } - - if (! snd_card_proc_new(emu->card, "voices", &entry)) - snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_voices_read); - - if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_GPR : TOTAL_SIZE_GPR; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_tram_data", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_DATA : TOTAL_SIZE_TANKMEM_DATA ; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_tram_addr", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_ADDR : TOTAL_SIZE_TANKMEM_ADDR ; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_code", &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->size = emu->audigy ? A_TOTAL_SIZE_CODE : TOTAL_SIZE_CODE; - entry->c.ops = &snd_emu10k1_proc_ops_fx8010; - } - if (! snd_card_proc_new(emu->card, "fx8010_acode", &entry)) { - entry->content = SNDRV_INFO_CONTENT_TEXT; - entry->private_data = emu; - entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; - entry->c.text.read = snd_emu10k1_proc_acode_read; - } - return 0; -} -#endif /* CONFIG_PROC_FS */ diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/io.c b/ANDROID_3.4.5/sound/pci/emu10k1/io.c deleted file mode 100644 index e4fba49f..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/io.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Creative Labs, Inc. - * Routines for control of EMU10K1 chips - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/time.h> -#include <sound/core.h> -#include <sound/emu10k1.h> -#include <linux/delay.h> -#include <linux/export.h> -#include "p17v.h" - -unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - unsigned int mask; - - mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; - regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); - - if (reg & 0xff000000) { - unsigned char size, offset; - - size = (reg >> 24) & 0x3f; - offset = (reg >> 16) & 0x1f; - mask = ((1 << size) - 1) << offset; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - return (val & mask) >> offset; - } else { - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - val = inl(emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; - } -} - -EXPORT_SYMBOL(snd_emu10k1_ptr_read); - -void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - unsigned int mask; - - if (!emu) { - snd_printk(KERN_ERR "ptr_write: emu is null!\n"); - dump_stack(); - return; - } - mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK; - regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK); - - if (reg & 0xff000000) { - unsigned char size, offset; - - size = (reg >> 24) & 0x3f; - offset = (reg >> 16) & 0x1f; - mask = ((1 << size) - 1) << offset; - data = (data << offset) & mask; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - data |= inl(emu->port + DATA) & ~mask; - outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - } else { - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + PTR); - outl(data, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - } -} - -EXPORT_SYMBOL(snd_emu10k1_ptr_write); - -unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, - unsigned int reg, - unsigned int chn) -{ - unsigned long flags; - unsigned int regptr, val; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + 0x20 + PTR); - val = inl(emu->port + 0x20 + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, - unsigned int reg, - unsigned int chn, - unsigned int data) -{ - unsigned int regptr; - unsigned long flags; - - regptr = (reg << 16) | chn; - - spin_lock_irqsave(&emu->emu_lock, flags); - outl(regptr, emu->port + 0x20 + PTR); - outl(data, emu->port + 0x20 + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, - unsigned int data) -{ - unsigned int reset, set; - unsigned int reg, tmp; - int n, result; - int err = 0; - - /* This function is not re-entrant, so protect against it. */ - spin_lock(&emu->spi_lock); - if (emu->card_capabilities->ca0108_chip) - reg = 0x3c; /* PTR20, reg 0x3c */ - else { - /* For other chip types the SPI register - * is currently unknown. */ - err = 1; - goto spi_write_exit; - } - if (data > 0xffff) { - /* Only 16bit values allowed */ - err = 1; - goto spi_write_exit; - } - - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); - reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */ - set = reset | 0x10000; /* Set xxx1xxxx */ - snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */ - snd_emu10k1_ptr20_write(emu, reg, 0, set | data); - result = 1; - /* Wait for status bit to return to 0 */ - for (n = 0; n < 100; n++) { - udelay(10); - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); - if (!(tmp & 0x10000)) { - result = 0; - break; - } - } - if (result) { - /* Timed out */ - err = 1; - goto spi_write_exit; - } - snd_emu10k1_ptr20_write(emu, reg, 0, reset | data); - tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */ - err = 0; -spi_write_exit: - spin_unlock(&emu->spi_lock); - return err; -} - -/* The ADC does not support i2c read, so only write is implemented */ -int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, - u32 reg, - u32 value) -{ - u32 tmp; - int timeout = 0; - int status; - int retry; - int err = 0; - - if ((reg > 0x7f) || (value > 0x1ff)) { - snd_printk(KERN_ERR "i2c_write: invalid values.\n"); - return -EINVAL; - } - - /* This function is not re-entrant, so protect against it. */ - spin_lock(&emu->i2c_lock); - - tmp = reg << 25 | value << 16; - - /* This controls the I2C connected to the WM8775 ADC Codec */ - snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp); - tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */ - - for (retry = 0; retry < 10; retry++) { - /* Send the data to i2c */ - tmp = 0; - tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); - snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp); - - /* Wait till the transaction ends */ - while (1) { - mdelay(1); - status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0); - timeout++; - if ((status & I2C_A_ADC_START) == 0) - break; - - if (timeout > 1000) { - snd_printk(KERN_WARNING - "emu10k1:I2C:timeout status=0x%x\n", - status); - break; - } - } - //Read back and see if the transaction is successful - if ((status & I2C_A_ADC_ABORT) == 0) - break; - } - - if (retry == 10) { - snd_printk(KERN_ERR "Writing to ADC failed!\n"); - snd_printk(KERN_ERR "status=0x%x, reg=%d, value=%d\n", - status, reg, value); - /* dump_stack(); */ - err = -EINVAL; - } - - spin_unlock(&emu->i2c_lock); - return err; -} - -int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value) -{ - unsigned long flags; - - if (reg > 0x3f) - return 1; - reg += 0x40; /* 0x40 upwards are registers. */ - if (value > 0x3f) /* 0 to 0x3f are values */ - return 1; - spin_lock_irqsave(&emu->emu_lock, flags); - outl(reg, emu->port + A_IOCFG); - udelay(10); - outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ - udelay(10); - outl(value, emu->port + A_IOCFG); - udelay(10); - outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ - spin_unlock_irqrestore(&emu->emu_lock, flags); - - return 0; -} - -int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value) -{ - unsigned long flags; - if (reg > 0x3f) - return 1; - reg += 0x40; /* 0x40 upwards are registers. */ - spin_lock_irqsave(&emu->emu_lock, flags); - outl(reg, emu->port + A_IOCFG); - udelay(10); - outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ - udelay(10); - *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f); - spin_unlock_irqrestore(&emu->emu_lock, flags); - - return 0; -} - -/* Each Destination has one and only one Source, - * but one Source can feed any number of Destinations simultaneously. - */ -int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src) -{ - snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) ); - snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) ); - - return 0; -} - -void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - enable = inl(emu->port + INTE) | intrenb; - outl(enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - enable = inl(emu->port + INTE) & ~intrenb; - outl(enable, emu->port + INTE); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(CLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << (voicenum - 32); - } else { - outl(CLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << voicenum; - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(CLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << (voicenum - 32)); - } else { - outl(CLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << voicenum); - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(CLIPH << 16, emu->port + PTR); - voicenum = 1 << (voicenum - 32); - } else { - outl(CLIPL << 16, emu->port + PTR); - voicenum = 1 << voicenum; - } - outl(voicenum, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(HLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << (voicenum - 32); - } else { - outl(HLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val |= 1 << voicenum; - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(HLIEH << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << (voicenum - 32)); - } else { - outl(HLIEL << 16, emu->port + PTR); - val = inl(emu->port + DATA); - val &= ~(1 << voicenum); - } - outl(val, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(HLIPH << 16, emu->port + PTR); - voicenum = 1 << (voicenum - 32); - } else { - outl(HLIPL << 16, emu->port + PTR); - voicenum = 1 << voicenum; - } - outl(voicenum, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int sol; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(SOLEH << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol |= 1 << (voicenum - 32); - } else { - outl(SOLEL << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol |= 1 << voicenum; - } - outl(sol, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum) -{ - unsigned long flags; - unsigned int sol; - - spin_lock_irqsave(&emu->emu_lock, flags); - /* voice interrupt */ - if (voicenum >= 32) { - outl(SOLEH << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol &= ~(1 << (voicenum - 32)); - } else { - outl(SOLEL << 16, emu->port + PTR); - sol = inl(emu->port + DATA); - sol &= ~(1 << voicenum); - } - outl(sol, emu->port + DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait) -{ - volatile unsigned count; - unsigned int newtime = 0, curtime; - - curtime = inl(emu->port + WC) >> 6; - while (wait-- > 0) { - count = 0; - while (count++ < 16384) { - newtime = inl(emu->port + WC) >> 6; - if (newtime != curtime) - break; - } - if (count > 16384) - break; - curtime = newtime; - } -} - -unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - struct snd_emu10k1 *emu = ac97->private_data; - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - val = inw(emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); - return val; -} - -void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data) -{ - struct snd_emu10k1 *emu = ac97->private_data; - unsigned long flags; - - spin_lock_irqsave(&emu->emu_lock, flags); - outb(reg, emu->port + AC97ADDRESS); - outw(data, emu->port + AC97DATA); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -/* - * convert rate to pitch - */ - -unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate) -{ - static u32 logMagTable[128] = { - 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2, - 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5, - 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081, - 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191, - 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, - 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, - 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e, - 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26, - 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d, - 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885, - 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, - 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, - 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, - 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3, - 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83, - 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df - }; - static char logSlopeTable[128] = { - 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58, - 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53, - 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f, - 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b, - 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, - 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44, - 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41, - 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, - 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, - 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, - 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, - 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35, - 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34, - 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32, - 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f - }; - int i; - - if (rate == 0) - return 0; /* Bail out if no leading "1" */ - rate *= 11185; /* Scale 48000 to 0x20002380 */ - for (i = 31; i > 0; i--) { - if (rate & 0x80000000) { /* Detect leading "1" */ - return (((unsigned int) (i - 15) << 20) + - logMagTable[0x7f & (rate >> 24)] + - (0x7f & (rate >> 17)) * - logSlopeTable[0x7f & (rate >> 24)]); - } - rate <<= 1; - } - - return 0; /* Should never reach this point */ -} - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/irq.c b/ANDROID_3.4.5/sound/pci/emu10k1/irq.c deleted file mode 100644 index 30bfed6f..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/irq.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Creative Labs, Inc. - * Routines for IRQ control of EMU10K1 chips - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/time.h> -#include <sound/core.h> -#include <sound/emu10k1.h> - -irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id) -{ - struct snd_emu10k1 *emu = dev_id; - unsigned int status, status2, orig_status, orig_status2; - int handled = 0; - int timeout = 0; - - while (((status = inl(emu->port + IPR)) != 0) && (timeout < 1000)) { - timeout++; - orig_status = status; - handled = 1; - if ((status & 0xffffffff) == 0xffffffff) { - snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n"); - break; - } - if (status & IPR_PCIERROR) { - snd_printk(KERN_ERR "interrupt: PCI error\n"); - snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE); - status &= ~IPR_PCIERROR; - } - if (status & (IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE)) { - if (emu->hwvol_interrupt) - emu->hwvol_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_VOLINCRENABLE|INTE_VOLDECRENABLE|INTE_MUTEENABLE); - status &= ~(IPR_VOLINCR|IPR_VOLDECR|IPR_MUTE); - } - if (status & IPR_CHANNELLOOP) { - int voice; - int voice_max = status & IPR_CHANNELNUMBERMASK; - u32 val; - struct snd_emu10k1_voice *pvoice = emu->voices; - - val = snd_emu10k1_ptr_read(emu, CLIPL, 0); - for (voice = 0; voice <= voice_max; voice++) { - if (voice == 0x20) - val = snd_emu10k1_ptr_read(emu, CLIPH, 0); - if (val & 1) { - if (pvoice->use && pvoice->interrupt != NULL) { - pvoice->interrupt(emu, pvoice); - snd_emu10k1_voice_intr_ack(emu, voice); - } else { - snd_emu10k1_voice_intr_disable(emu, voice); - } - } - val >>= 1; - pvoice++; - } - val = snd_emu10k1_ptr_read(emu, HLIPL, 0); - for (voice = 0; voice <= voice_max; voice++) { - if (voice == 0x20) - val = snd_emu10k1_ptr_read(emu, HLIPH, 0); - if (val & 1) { - if (pvoice->use && pvoice->interrupt != NULL) { - pvoice->interrupt(emu, pvoice); - snd_emu10k1_voice_half_loop_intr_ack(emu, voice); - } else { - snd_emu10k1_voice_half_loop_intr_disable(emu, voice); - } - } - val >>= 1; - pvoice++; - } - status &= ~IPR_CHANNELLOOP; - } - status &= ~IPR_CHANNELNUMBERMASK; - if (status & (IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL)) { - if (emu->capture_interrupt) - emu->capture_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_ADCBUFENABLE); - status &= ~(IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL); - } - if (status & (IPR_MICBUFFULL|IPR_MICBUFHALFFULL)) { - if (emu->capture_mic_interrupt) - emu->capture_mic_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_MICBUFENABLE); - status &= ~(IPR_MICBUFFULL|IPR_MICBUFHALFFULL); - } - if (status & (IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL)) { - if (emu->capture_efx_interrupt) - emu->capture_efx_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_EFXBUFENABLE); - status &= ~(IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL); - } - if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) { - if (emu->midi.interrupt) - emu->midi.interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_MIDITXENABLE|INTE_MIDIRXENABLE); - status &= ~(IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY); - } - if (status & (IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2)) { - if (emu->midi2.interrupt) - emu->midi2.interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_A_MIDITXENABLE2|INTE_A_MIDIRXENABLE2); - status &= ~(IPR_A_MIDITRANSBUFEMPTY2|IPR_A_MIDIRECVBUFEMPTY2); - } - if (status & IPR_INTERVALTIMER) { - if (emu->timer) - snd_timer_interrupt(emu->timer, emu->timer->sticks); - else - snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB); - status &= ~IPR_INTERVALTIMER; - } - if (status & (IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE)) { - if (emu->spdif_interrupt) - emu->spdif_interrupt(emu, status); - else - snd_emu10k1_intr_disable(emu, INTE_GPSPDIFENABLE|INTE_CDSPDIFENABLE); - status &= ~(IPR_GPSPDIFSTATUSCHANGE|IPR_CDROMSTATUSCHANGE); - } - if (status & IPR_FXDSP) { - if (emu->dsp_interrupt) - emu->dsp_interrupt(emu); - else - snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); - status &= ~IPR_FXDSP; - } - if (status & IPR_P16V) { - while ((status2 = inl(emu->port + IPR2)) != 0) { - u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ - struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]); - struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice); - - //printk(KERN_INFO "status2=0x%x\n", status2); - orig_status2 = status2; - if(status2 & mask) { - if(pvoice->use) { - snd_pcm_period_elapsed(pvoice->epcm->substream); - } else { - snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); - } - } - if(status2 & 0x110000) { - //printk(KERN_INFO "capture int found\n"); - if(cvoice->use) { - //printk(KERN_INFO "capture period_elapsed\n"); - snd_pcm_period_elapsed(cvoice->epcm->substream); - } - } - outl(orig_status2, emu->port + IPR2); /* ack all */ - } - status &= ~IPR_P16V; - } - - if (status) { - unsigned int bits; - snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status); - //make sure any interrupts we don't handle are disabled: - bits = INTE_FXDSPENABLE | - INTE_PCIERRORENABLE | - INTE_VOLINCRENABLE | - INTE_VOLDECRENABLE | - INTE_MUTEENABLE | - INTE_MICBUFENABLE | - INTE_ADCBUFENABLE | - INTE_EFXBUFENABLE | - INTE_GPSPDIFENABLE | - INTE_CDSPDIFENABLE | - INTE_INTERVALTIMERENB | - INTE_MIDITXENABLE | - INTE_MIDIRXENABLE; - if (emu->audigy) - bits |= INTE_A_MIDITXENABLE2 | INTE_A_MIDIRXENABLE2; - snd_emu10k1_intr_disable(emu, bits); - } - outl(orig_status, emu->port + IPR); /* ack all */ - } - if (timeout == 1000) - snd_printk(KERN_INFO "emu10k1 irq routine failure\n"); - - return IRQ_RETVAL(handled); -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/memory.c b/ANDROID_3.4.5/sound/pci/emu10k1/memory.c deleted file mode 100644 index 4f502a2b..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/memory.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Copyright (c) by Takashi Iwai <tiwai@suse.de> - * - * EMU10K1 memory page allocation (PTB area) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/pci.h> -#include <linux/gfp.h> -#include <linux/time.h> -#include <linux/mutex.h> -#include <linux/export.h> - -#include <sound/core.h> -#include <sound/emu10k1.h> - -/* page arguments of these two macros are Emu page (4096 bytes), not like - * aligned pages in others - */ -#define __set_ptb_entry(emu,page,addr) \ - (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page))) - -#define UNIT_PAGES (PAGE_SIZE / EMUPAGESIZE) -#define MAX_ALIGN_PAGES (MAXPAGES / UNIT_PAGES) -/* get aligned page from offset address */ -#define get_aligned_page(offset) ((offset) >> PAGE_SHIFT) -/* get offset address from aligned page */ -#define aligned_page_offset(page) ((page) << PAGE_SHIFT) - -#if PAGE_SIZE == 4096 -/* page size == EMUPAGESIZE */ -/* fill PTB entrie(s) corresponding to page with addr */ -#define set_ptb_entry(emu,page,addr) __set_ptb_entry(emu,page,addr) -/* fill PTB entrie(s) corresponding to page with silence pointer */ -#define set_silent_ptb(emu,page) __set_ptb_entry(emu,page,emu->silent_page.addr) -#else -/* fill PTB entries -- we need to fill UNIT_PAGES entries */ -static inline void set_ptb_entry(struct snd_emu10k1 *emu, int page, dma_addr_t addr) -{ - int i; - page *= UNIT_PAGES; - for (i = 0; i < UNIT_PAGES; i++, page++) { - __set_ptb_entry(emu, page, addr); - addr += EMUPAGESIZE; - } -} -static inline void set_silent_ptb(struct snd_emu10k1 *emu, int page) -{ - int i; - page *= UNIT_PAGES; - for (i = 0; i < UNIT_PAGES; i++, page++) - /* do not increment ptr */ - __set_ptb_entry(emu, page, emu->silent_page.addr); -} -#endif /* PAGE_SIZE */ - - -/* - */ -static int synth_alloc_pages(struct snd_emu10k1 *hw, struct snd_emu10k1_memblk *blk); -static int synth_free_pages(struct snd_emu10k1 *hw, struct snd_emu10k1_memblk *blk); - -#define get_emu10k1_memblk(l,member) list_entry(l, struct snd_emu10k1_memblk, member) - - -/* initialize emu10k1 part */ -static void emu10k1_memblk_init(struct snd_emu10k1_memblk *blk) -{ - blk->mapped_page = -1; - INIT_LIST_HEAD(&blk->mapped_link); - INIT_LIST_HEAD(&blk->mapped_order_link); - blk->map_locked = 0; - - blk->first_page = get_aligned_page(blk->mem.offset); - blk->last_page = get_aligned_page(blk->mem.offset + blk->mem.size - 1); - blk->pages = blk->last_page - blk->first_page + 1; -} - -/* - * search empty region on PTB with the given size - * - * if an empty region is found, return the page and store the next mapped block - * in nextp - * if not found, return a negative error code. - */ -static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct list_head **nextp) -{ - int page = 0, found_page = -ENOMEM; - int max_size = npages; - int size; - struct list_head *candidate = &emu->mapped_link_head; - struct list_head *pos; - - list_for_each (pos, &emu->mapped_link_head) { - struct snd_emu10k1_memblk *blk = get_emu10k1_memblk(pos, mapped_link); - if (blk->mapped_page < 0) - continue; - size = blk->mapped_page - page; - if (size == npages) { - *nextp = pos; - return page; - } - else if (size > max_size) { - /* we look for the maximum empty hole */ - max_size = size; - candidate = pos; - found_page = page; - } - page = blk->mapped_page + blk->pages; - } - size = MAX_ALIGN_PAGES - page; - if (size >= max_size) { - *nextp = pos; - return page; - } - *nextp = candidate; - return found_page; -} - -/* - * map a memory block onto emu10k1's PTB - * - * call with memblk_lock held - */ -static int map_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int page, pg; - struct list_head *next; - - page = search_empty_map_area(emu, blk->pages, &next); - if (page < 0) /* not found */ - return page; - /* insert this block in the proper position of mapped list */ - list_add_tail(&blk->mapped_link, next); - /* append this as a newest block in order list */ - list_add_tail(&blk->mapped_order_link, &emu->mapped_order_link_head); - blk->mapped_page = page; - /* fill PTB */ - for (pg = blk->first_page; pg <= blk->last_page; pg++) { - set_ptb_entry(emu, page, emu->page_addr_table[pg]); - page++; - } - return 0; -} - -/* - * unmap the block - * return the size of resultant empty pages - * - * call with memblk_lock held - */ -static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int start_page, end_page, mpage, pg; - struct list_head *p; - struct snd_emu10k1_memblk *q; - - /* calculate the expected size of empty region */ - if ((p = blk->mapped_link.prev) != &emu->mapped_link_head) { - q = get_emu10k1_memblk(p, mapped_link); - start_page = q->mapped_page + q->pages; - } else - start_page = 0; - if ((p = blk->mapped_link.next) != &emu->mapped_link_head) { - q = get_emu10k1_memblk(p, mapped_link); - end_page = q->mapped_page; - } else - end_page = MAX_ALIGN_PAGES; - - /* remove links */ - list_del(&blk->mapped_link); - list_del(&blk->mapped_order_link); - /* clear PTB */ - mpage = blk->mapped_page; - for (pg = blk->first_page; pg <= blk->last_page; pg++) { - set_silent_ptb(emu, mpage); - mpage++; - } - blk->mapped_page = -1; - return end_page - start_page; /* return the new empty size */ -} - -/* - * search empty pages with the given size, and create a memory block - * - * unlike synth_alloc the memory block is aligned to the page start - */ -static struct snd_emu10k1_memblk * -search_empty(struct snd_emu10k1 *emu, int size) -{ - struct list_head *p; - struct snd_emu10k1_memblk *blk; - int page, psize; - - psize = get_aligned_page(size + PAGE_SIZE -1); - page = 0; - list_for_each(p, &emu->memhdr->block) { - blk = get_emu10k1_memblk(p, mem.list); - if (page + psize <= blk->first_page) - goto __found_pages; - page = blk->last_page + 1; - } - if (page + psize > emu->max_cache_pages) - return NULL; - -__found_pages: - /* create a new memory block */ - blk = (struct snd_emu10k1_memblk *)__snd_util_memblk_new(emu->memhdr, psize << PAGE_SHIFT, p->prev); - if (blk == NULL) - return NULL; - blk->mem.offset = aligned_page_offset(page); /* set aligned offset */ - emu10k1_memblk_init(blk); - return blk; -} - - -/* - * check if the given pointer is valid for pages - */ -static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr) -{ - if (addr & ~emu->dma_mask) { - snd_printk(KERN_ERR "max memory size is 0x%lx (addr = 0x%lx)!!\n", emu->dma_mask, (unsigned long)addr); - return 0; - } - if (addr & (EMUPAGESIZE-1)) { - snd_printk(KERN_ERR "page is not aligned\n"); - return 0; - } - return 1; -} - -/* - * map the given memory block on PTB. - * if the block is already mapped, update the link order. - * if no empty pages are found, tries to release unused memory blocks - * and retry the mapping. - */ -int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int err; - int size; - struct list_head *p, *nextp; - struct snd_emu10k1_memblk *deleted; - unsigned long flags; - - spin_lock_irqsave(&emu->memblk_lock, flags); - if (blk->mapped_page >= 0) { - /* update order link */ - list_del(&blk->mapped_order_link); - list_add_tail(&blk->mapped_order_link, &emu->mapped_order_link_head); - spin_unlock_irqrestore(&emu->memblk_lock, flags); - return 0; - } - if ((err = map_memblk(emu, blk)) < 0) { - /* no enough page - try to unmap some blocks */ - /* starting from the oldest block */ - p = emu->mapped_order_link_head.next; - for (; p != &emu->mapped_order_link_head; p = nextp) { - nextp = p->next; - deleted = get_emu10k1_memblk(p, mapped_order_link); - if (deleted->map_locked) - continue; - size = unmap_memblk(emu, deleted); - if (size >= blk->pages) { - /* ok the empty region is enough large */ - err = map_memblk(emu, blk); - break; - } - } - } - spin_unlock_irqrestore(&emu->memblk_lock, flags); - return err; -} - -EXPORT_SYMBOL(snd_emu10k1_memblk_map); - -/* - * page allocation for DMA - */ -struct snd_util_memblk * -snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_util_memhdr *hdr; - struct snd_emu10k1_memblk *blk; - int page, err, idx; - - if (snd_BUG_ON(!emu)) - return NULL; - if (snd_BUG_ON(runtime->dma_bytes <= 0 || - runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE)) - return NULL; - hdr = emu->memhdr; - if (snd_BUG_ON(!hdr)) - return NULL; - - idx = runtime->period_size >= runtime->buffer_size ? - (emu->delay_pcm_irq * 2) : 0; - mutex_lock(&hdr->block_mutex); - blk = search_empty(emu, runtime->dma_bytes + idx); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); - return NULL; - } - /* fill buffer addresses but pointers are not stored so that - * snd_free_pci_page() is not called in in synth_free() - */ - idx = 0; - for (page = blk->first_page; page <= blk->last_page; page++, idx++) { - unsigned long ofs = idx << PAGE_SHIFT; - dma_addr_t addr; - addr = snd_pcm_sgbuf_get_addr(substream, ofs); - if (! is_valid_page(emu, addr)) { - printk(KERN_ERR "emu: failure page = %d\n", idx); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - emu->page_addr_table[page] = addr; - emu->page_ptr_table[page] = NULL; - } - - /* set PTB entries */ - blk->map_locked = 1; /* do not unmap this block! */ - err = snd_emu10k1_memblk_map(emu, blk); - if (err < 0) { - __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - mutex_unlock(&hdr->block_mutex); - return (struct snd_util_memblk *)blk; -} - - -/* - * release DMA buffer from page table - */ -int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk) -{ - if (snd_BUG_ON(!emu || !blk)) - return -EINVAL; - return snd_emu10k1_synth_free(emu, blk); -} - - -/* - * memory allocation using multiple pages (for synth) - * Unlike the DMA allocation above, non-contiguous pages are assined. - */ - -/* - * allocate a synth sample area - */ -struct snd_util_memblk * -snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size) -{ - struct snd_emu10k1_memblk *blk; - struct snd_util_memhdr *hdr = hw->memhdr; - - mutex_lock(&hdr->block_mutex); - blk = (struct snd_emu10k1_memblk *)__snd_util_mem_alloc(hdr, size); - if (blk == NULL) { - mutex_unlock(&hdr->block_mutex); - return NULL; - } - if (synth_alloc_pages(hw, blk)) { - __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk); - mutex_unlock(&hdr->block_mutex); - return NULL; - } - snd_emu10k1_memblk_map(hw, blk); - mutex_unlock(&hdr->block_mutex); - return (struct snd_util_memblk *)blk; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_alloc); - -/* - * free a synth sample area - */ -int -snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk) -{ - struct snd_util_memhdr *hdr = emu->memhdr; - struct snd_emu10k1_memblk *blk = (struct snd_emu10k1_memblk *)memblk; - unsigned long flags; - - mutex_lock(&hdr->block_mutex); - spin_lock_irqsave(&emu->memblk_lock, flags); - if (blk->mapped_page >= 0) - unmap_memblk(emu, blk); - spin_unlock_irqrestore(&emu->memblk_lock, flags); - synth_free_pages(emu, blk); - __snd_util_mem_free(hdr, memblk); - mutex_unlock(&hdr->block_mutex); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_free); - -/* check new allocation range */ -static void get_single_page_range(struct snd_util_memhdr *hdr, - struct snd_emu10k1_memblk *blk, - int *first_page_ret, int *last_page_ret) -{ - struct list_head *p; - struct snd_emu10k1_memblk *q; - int first_page, last_page; - first_page = blk->first_page; - if ((p = blk->mem.list.prev) != &hdr->block) { - q = get_emu10k1_memblk(p, mem.list); - if (q->last_page == first_page) - first_page++; /* first page was already allocated */ - } - last_page = blk->last_page; - if ((p = blk->mem.list.next) != &hdr->block) { - q = get_emu10k1_memblk(p, mem.list); - if (q->first_page == last_page) - last_page--; /* last page was already allocated */ - } - *first_page_ret = first_page; - *last_page_ret = last_page; -} - -/* release allocated pages */ -static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page, - int last_page) -{ - int page; - - for (page = first_page; page <= last_page; page++) { - free_page((unsigned long)emu->page_ptr_table[page]); - emu->page_addr_table[page] = 0; - emu->page_ptr_table[page] = NULL; - } -} - -/* - * allocate kernel pages - */ -static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int page, first_page, last_page; - - emu10k1_memblk_init(blk); - get_single_page_range(emu->memhdr, blk, &first_page, &last_page); - /* allocate kernel pages */ - for (page = first_page; page <= last_page; page++) { - /* first try to allocate from <4GB zone */ - struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 | - __GFP_NOWARN); - if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) { - if (p) - __free_page(p); - /* try to allocate from <16MB zone */ - p = alloc_page(GFP_ATOMIC | GFP_DMA | - __GFP_NORETRY | /* no OOM-killer */ - __GFP_NOWARN); - } - if (!p) { - __synth_free_pages(emu, first_page, page - 1); - return -ENOMEM; - } - emu->page_addr_table[page] = page_to_phys(p); - emu->page_ptr_table[page] = page_address(p); - } - return 0; -} - -/* - * free pages - */ -static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) -{ - int first_page, last_page; - - get_single_page_range(emu->memhdr, blk, &first_page, &last_page); - __synth_free_pages(emu, first_page, last_page); - return 0; -} - -/* calculate buffer pointer from offset address */ -static inline void *offset_ptr(struct snd_emu10k1 *emu, int page, int offset) -{ - char *ptr; - if (snd_BUG_ON(page < 0 || page >= emu->max_cache_pages)) - return NULL; - ptr = emu->page_ptr_table[page]; - if (! ptr) { - printk(KERN_ERR "emu10k1: access to NULL ptr: page = %d\n", page); - return NULL; - } - ptr += offset & (PAGE_SIZE - 1); - return (void*)ptr; -} - -/* - * bzero(blk + offset, size) - */ -int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, - int offset, int size) -{ - int page, nextofs, end_offset, temp, temp1; - void *ptr; - struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk; - - offset += blk->offset & (PAGE_SIZE - 1); - end_offset = offset + size; - page = get_aligned_page(offset); - do { - nextofs = aligned_page_offset(page + 1); - temp = nextofs - offset; - temp1 = end_offset - offset; - if (temp1 < temp) - temp = temp1; - ptr = offset_ptr(emu, page + p->first_page, offset); - if (ptr) - memset(ptr, 0, temp); - offset = nextofs; - page++; - } while (offset < end_offset); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_bzero); - -/* - * copy_from_user(blk + offset, data, size) - */ -int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, - int offset, const char __user *data, int size) -{ - int page, nextofs, end_offset, temp, temp1; - void *ptr; - struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk; - - offset += blk->offset & (PAGE_SIZE - 1); - end_offset = offset + size; - page = get_aligned_page(offset); - do { - nextofs = aligned_page_offset(page + 1); - temp = nextofs - offset; - temp1 = end_offset - offset; - if (temp1 < temp) - temp = temp1; - ptr = offset_ptr(emu, page + p->first_page, offset); - if (ptr && copy_from_user(ptr, data, temp)) - return -EFAULT; - offset = nextofs; - data += temp; - page++; - } while (offset < end_offset); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user); diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.c b/ANDROID_3.4.5/sound/pci/emu10k1/p16v.c deleted file mode 100644 index a81dc442..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.c +++ /dev/null @@ -1,934 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> - * Driver p16v chips - * Version: 0.25 - * - * FEATURES currently supported: - * Output fixed at S32_LE, 2 channel to hw:0,0 - * Rates: 44.1, 48, 96, 192. - * - * Changelog: - * 0.8 - * Use separate card based buffer for periods table. - * 0.9 - * Use 2 channel output streams instead of 8 channel. - * (8 channel output streams might be good for ASIO type output) - * Corrected speaker output, so Front -> Front etc. - * 0.10 - * Fixed missed interrupts. - * 0.11 - * Add Sound card model number and names. - * Add Analog volume controls. - * 0.12 - * Corrected playback interrupts. Now interrupt per period, instead of half period. - * 0.13 - * Use single trigger for multichannel. - * 0.14 - * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo. - * 0.15 - * Force buffer_size / period_size == INTEGER. - * 0.16 - * Update p16v.c to work with changed alsa api. - * 0.17 - * Update p16v.c to work with changed alsa api. Removed boot_devs. - * 0.18 - * Merging with snd-emu10k1 driver. - * 0.19 - * One stereo channel at 24bit now works. - * 0.20 - * Added better register defines. - * 0.21 - * Integrated with snd-emu10k1 driver. - * 0.22 - * Removed #if 0 ... #endif - * 0.23 - * Implement different capture rates. - * 0.24 - * Implement different capture source channels. - * e.g. When HD Capture source is set to SPDIF, - * setting HD Capture channel to 0 captures from CDROM digital input. - * setting HD Capture channel to 1 captures from SPDIF in. - * 0.25 - * Include capture buffer sizes. - * - * BUGS: - * Some stability problems when unloading the snd-p16v kernel module. - * -- - * - * TODO: - * SPDIF out. - * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz. - * Currently capture fixed at 48000Hz. - * - * -- - * GENERAL INFO: - * Model: SB0240 - * P16V Chip: CA0151-DBS - * Audigy 2 Chip: CA0102-IAT - * AC97 Codec: STAC 9721 - * ADC: Philips 1361T (Stereo 24bit) - * DAC: CS4382-K (8-channel, 24bit, 192Khz) - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> -#include <linux/moduleparam.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <sound/ac97_codec.h> -#include <sound/info.h> -#include <sound/tlv.h> -#include <sound/emu10k1.h> -#include "p16v.h" - -#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ -#define PCM_FRONT_CHANNEL 0 -#define PCM_REAR_CHANNEL 1 -#define PCM_CENTER_LFE_CHANNEL 2 -#define PCM_SIDE_CHANNEL 3 -#define CONTROL_FRONT_CHANNEL 0 -#define CONTROL_REAR_CHANNEL 3 -#define CONTROL_CENTER_LFE_CHANNEL 1 -#define CONTROL_SIDE_CHANNEL 2 - -/* Card IDs: - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350 - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240 - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb0240230009266 - * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E - * - */ - - /* hardware definition */ -static struct snd_pcm_hardware snd_p16v_playback_hw = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ - .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 8, - .channels_max = 8, - .buffer_bytes_max = ((65536 - 64) * 8), - .period_bytes_min = 64, - .period_bytes_max = (65536 - 64), - .periods_min = 2, - .periods_max = 8, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_p16v_capture_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, - .rate_min = 44100, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = (65536 - 64), - .period_bytes_min = 64, - .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */ - .periods_min = 2, - .periods_max = 2, - .fifo_size = 0, -}; - -static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime) -{ - struct snd_emu10k1_pcm *epcm = runtime->private_data; - - if (epcm) { - /* snd_printk(KERN_DEBUG "epcm free: %p\n", epcm); */ - kfree(epcm); - } -} - -/* open_playback callback */ -static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->substream = substream; - /* - snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", - substream->pcm->device, channel_id); - */ - runtime->private_data = epcm; - runtime->private_free = snd_p16v_pcm_free_substream; - - runtime->hw = snd_p16v_playback_hw; - - channel->emu = emu; - channel->number = channel_id; - - channel->use=1; -#if 0 /* debug */ - snd_printk(KERN_DEBUG - "p16v: open channel_id=%d, channel=%p, use=0x%x\n", - channel_id, channel, channel->use); - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", - channel_id, chip, channel); -#endif /* debug */ - /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ - channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - runtime->sync.id32[0] = substream->pcm->card->number; - runtime->sync.id32[1] = 'P'; - runtime->sync.id32[2] = 16; - runtime->sync.id32[3] = 'V'; - - return 0; -} -/* open_capture callback */ -static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice); - struct snd_emu10k1_pcm *epcm; - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); - /* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */ - - if (epcm == NULL) - return -ENOMEM; - epcm->emu = emu; - epcm->substream = substream; - /* - snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n", - substream->pcm->device, channel_id); - */ - runtime->private_data = epcm; - runtime->private_free = snd_p16v_pcm_free_substream; - - runtime->hw = snd_p16v_capture_hw; - - channel->emu = emu; - channel->number = channel_id; - - channel->use=1; -#if 0 /* debug */ - snd_printk(KERN_DEBUG - "p16v: open channel_id=%d, channel=%p, use=0x%x\n", - channel_id, channel, channel->use); - printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n", - channel_id, chip, channel); -#endif /* debug */ - /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ - channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - return 0; -} - - -/* close callback */ -static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - //struct snd_pcm_runtime *runtime = substream->runtime; - //struct snd_emu10k1_pcm *epcm = runtime->private_data; - emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0; - /* FIXME: maybe zero others */ - return 0; -} - -/* close callback */ -static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - //struct snd_pcm_runtime *runtime = substream->runtime; - //struct snd_emu10k1_pcm *epcm = runtime->private_data; - emu->p16v_capture_voice.use = 0; - /* FIXME: maybe zero others */ - return 0; -} - -static int snd_p16v_pcm_open_playback_front(struct snd_pcm_substream *substream) -{ - return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL); -} - -static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream) -{ - // Only using channel 0 for now, but the card has 2 channels. - return snd_p16v_pcm_open_capture_channel(substream, 0); -} - -/* hw_params callback */ -static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int result; - result = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - return result; -} - -/* hw_params callback */ -static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - int result; - result = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - return result; -} - - -/* hw_free callback */ -static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream) -{ - int result; - result = snd_pcm_lib_free_pages(substream); - return result; -} - -/* hw_free callback */ -static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream) -{ - int result; - result = snd_pcm_lib_free_pages(substream); - return result; -} - - -/* prepare playback callback */ -static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int channel = substream->pcm->device - emu->p16v_device_offset; - u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel)); - u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); - int i; - u32 tmp; - -#if 0 /* debug */ - snd_printk(KERN_DEBUG "prepare:channel_number=%d, rate=%d, " - "format=0x%x, channels=%d, buffer_size=%ld, " - "period_size=%ld, periods=%u, frames_to_bytes=%d\n", - channel, runtime->rate, runtime->format, runtime->channels, - runtime->buffer_size, runtime->period_size, - runtime->periods, frames_to_bytes(runtime, 1)); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n", - runtime->dma_addr, runtime->dma_area, table_base); - snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n", - emu->p16v_buffer.addr, emu->p16v_buffer.area, - emu->p16v_buffer.bytes); -#endif /* debug */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); - switch (runtime->rate) { - case 44100: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080); - break; - case 96000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040); - break; - case 192000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020); - break; - case 48000: - default: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000); - break; - } - /* FIXME: Check emu->buffer.size before actually writing to it. */ - for(i = 0; i < runtime->periods; i++) { - table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); - table_base[(i*2)+1]=period_size_bytes<<16; - } - - snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel)); - snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); - snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); - snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); - //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0); - snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0); - snd_emu10k1_ptr20_write(emu, 0x08, channel, 0); - - return 0; -} - -/* prepare capture callback */ -static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int channel = substream->pcm->device - emu->p16v_device_offset; - u32 tmp; - - /* - printk(KERN_DEBUG "prepare capture:channel_number=%d, rate=%d, " - "format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, " - "frames_to_bytes=%d\n", - channel, runtime->rate, runtime->format, runtime->channels, - runtime->buffer_size, runtime->period_size, - frames_to_bytes(runtime, 1)); - */ - tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); - switch (runtime->rate) { - case 44100: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800); - break; - case 96000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400); - break; - case 192000: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200); - break; - case 48000: - default: - snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000); - break; - } - /* FIXME: Check emu->buffer.size before actually writing to it. */ - snd_emu10k1_ptr20_write(emu, 0x13, channel, 0); - snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); - snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes - snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0); - //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */ - //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel)); - - return 0; -} - -static void snd_p16v_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int enable; - - spin_lock_irqsave(&emu->emu_lock, flags); - enable = inl(emu->port + INTE2) | intrenb; - outl(enable, emu->port + INTE2); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb) -{ - unsigned long flags; - unsigned int disable; - - spin_lock_irqsave(&emu->emu_lock, flags); - disable = inl(emu->port + INTE2) & (~intrenb); - outl(disable, emu->port + INTE2); - spin_unlock_irqrestore(&emu->emu_lock, flags); -} - -/* trigger_playback callback */ -static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime; - struct snd_emu10k1_pcm *epcm; - int channel; - int result = 0; - struct snd_pcm_substream *s; - u32 basic = 0; - u32 inte = 0; - int running = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - running=1; - break; - case SNDRV_PCM_TRIGGER_STOP: - default: - running = 0; - break; - } - snd_pcm_group_for_each_entry(s, substream) { - if (snd_pcm_substream_chip(s) != emu || - s->stream != SNDRV_PCM_STREAM_PLAYBACK) - continue; - runtime = s->runtime; - epcm = runtime->private_data; - channel = substream->pcm->device-emu->p16v_device_offset; - /* snd_printk(KERN_DEBUG "p16v channel=%d\n", channel); */ - epcm->running = running; - basic |= (0x1<<channel); - inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel); - snd_pcm_trigger_done(s, substream); - } - /* snd_printk(KERN_DEBUG "basic=0x%x, inte=0x%x\n", basic, inte); */ - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_p16v_intr_enable(emu, inte); - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)| (basic)); - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(basic)); - snd_p16v_intr_disable(emu, inte); - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* trigger_capture callback */ -static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - int channel = 0; - int result = 0; - u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_p16v_intr_enable(emu, inte); - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel)); - epcm->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel)); - snd_p16v_intr_disable(emu, inte); - //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel)); - epcm->running = 0; - break; - default: - result = -EINVAL; - break; - } - return result; -} - -/* pointer_playback callback */ -static snd_pcm_uframes_t -snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; - int channel = substream->pcm->device - emu->p16v_device_offset; - if (!epcm->running) - return 0; - - ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); - ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel); - ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel); - if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr2+= (ptr4 >> 3) * runtime->period_size; - ptr=ptr2; - if (ptr >= runtime->buffer_size) - ptr -= runtime->buffer_size; - - return ptr; -} - -/* pointer_capture callback */ -static snd_pcm_uframes_t -snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) -{ - struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_emu10k1_pcm *epcm = runtime->private_data; - snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; - int channel = 0; - - if (!epcm->running) - return 0; - - ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); - ptr2 = bytes_to_frames(runtime, ptr1); - ptr=ptr2; - if (ptr >= runtime->buffer_size) { - ptr -= runtime->buffer_size; - printk(KERN_WARNING "buffer capture limited!\n"); - } - /* - printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " - "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", - ptr1, ptr2, ptr, (int)runtime->buffer_size, - (int)runtime->period_size, (int)runtime->frame_bits, - (int)runtime->rate); - */ - return ptr; -} - -/* operators */ -static struct snd_pcm_ops snd_p16v_playback_front_ops = { - .open = snd_p16v_pcm_open_playback_front, - .close = snd_p16v_pcm_close_playback, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_p16v_pcm_hw_params_playback, - .hw_free = snd_p16v_pcm_hw_free_playback, - .prepare = snd_p16v_pcm_prepare_playback, - .trigger = snd_p16v_pcm_trigger_playback, - .pointer = snd_p16v_pcm_pointer_playback, -}; - -static struct snd_pcm_ops snd_p16v_capture_ops = { - .open = snd_p16v_pcm_open_capture, - .close = snd_p16v_pcm_close_capture, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_p16v_pcm_hw_params_capture, - .hw_free = snd_p16v_pcm_hw_free_capture, - .prepare = snd_p16v_pcm_prepare_capture, - .trigger = snd_p16v_pcm_trigger_capture, - .pointer = snd_p16v_pcm_pointer_capture, -}; - - -int snd_p16v_free(struct snd_emu10k1 *chip) -{ - // release the data - if (chip->p16v_buffer.area) { - snd_dma_free_pages(&chip->p16v_buffer); - /* - snd_printk(KERN_DEBUG "period lables free: %p\n", - &chip->p16v_buffer); - */ - } - return 0; -} - -int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int err; - int capture=1; - - /* snd_printk(KERN_DEBUG "snd_p16v_pcm called. device=%d\n", device); */ - emu->p16v_device_offset = device; - if (rpcm) - *rpcm = NULL; - - if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) - return err; - - pcm->private_data = emu; - // Single playback 8 channel device. - // Single capture 2 channel device. - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - strcpy(pcm->name, "p16v"); - emu->pcm_p16v = pcm; - - for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - substream; - substream = substream->next) { - if ((err = snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) - return err; - /* - snd_printk(KERN_DEBUG - "preallocate playback substream: err=%d\n", err); - */ - } - - for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - substream; - substream = substream->next) { - if ((err = snd_pcm_lib_preallocate_pages(substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(emu->pci), - 65536 - 64, 65536 - 64)) < 0) - return err; - /* - snd_printk(KERN_DEBUG - "preallocate capture substream: err=%d\n", err); - */ - } - - if (rpcm) - *rpcm = pcm; - - return 0; -} - -static int snd_p16v_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 255; - return 0; -} - -static int snd_p16v_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int high_low = (kcontrol->private_value >> 8) & 0xff; - int reg = kcontrol->private_value & 0xff; - u32 value; - - value = snd_emu10k1_ptr20_read(emu, reg, high_low); - if (high_low) { - ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */ - ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */ - } else { - ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */ - ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */ - } - return 0; -} - -static int snd_p16v_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int high_low = (kcontrol->private_value >> 8) & 0xff; - int reg = kcontrol->private_value & 0xff; - u32 value, oval; - - oval = value = snd_emu10k1_ptr20_read(emu, reg, 0); - if (high_low == 1) { - value &= 0xffff; - value |= ((0xff - ucontrol->value.integer.value[0]) << 24) | - ((0xff - ucontrol->value.integer.value[1]) << 16); - } else { - value &= 0xffff0000; - value |= ((0xff - ucontrol->value.integer.value[0]) << 8) | - ((0xff - ucontrol->value.integer.value[1]) ); - } - if (value != oval) { - snd_emu10k1_ptr20_write(emu, reg, 0, value); - return 1; - } - return 0; -} - -static int snd_p16v_capture_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[8] = { - "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", - "CDIF", "FX", "AC97" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item > 7) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_p16v_capture_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->p16v_capture_source; - return 0; -} - -static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - u32 mask; - u32 source; - - val = ucontrol->value.enumerated.item[0] ; - if (val > 7) - return -EINVAL; - change = (emu->p16v_capture_source != val); - if (change) { - emu->p16v_capture_source = val; - source = (val << 28) | (val << 24) | (val << 20) | (val << 16); - mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff; - snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask); - } - return change; -} - -static int snd_p16v_capture_channel_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { "0", "1", "2", "3", }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_p16v_capture_channel_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel; - return 0; -} - -static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - unsigned int val; - int change = 0; - u32 tmp; - - val = ucontrol->value.enumerated.item[0] ; - if (val > 3) - return -EINVAL; - change = (emu->p16v_capture_channel != val); - if (change) { - emu->p16v_capture_channel = val; - tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc; - snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val); - } - return change; -} -static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1); - -#define P16V_VOL(xname,xreg,xhl) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_p16v_volume_info, \ - .get = snd_p16v_volume_get, \ - .put = snd_p16v_volume_put, \ - .tlv = { .p = snd_p16v_db_scale1 }, \ - .private_value = ((xreg) | ((xhl) << 8)) \ -} - -static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = { - P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0), - P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1), - P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1), - P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0), - P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0), - P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1), - P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1), - P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HD source Capture", - .info = snd_p16v_capture_source_info, - .get = snd_p16v_capture_source_get, - .put = snd_p16v_capture_source_put - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HD channel Capture", - .info = snd_p16v_capture_channel_info, - .get = snd_p16v_capture_channel_get, - .put = snd_p16v_capture_channel_put - }, -}; - - -int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu) -{ - int i, err; - struct snd_card *card = emu->card; - - for (i = 0; i < ARRAY_SIZE(p16v_mixer_controls); i++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i], - emu))) < 0) - return err; - } - return 0; -} - -#ifdef CONFIG_PM - -#define NUM_CHS 1 /* up to 4, but only first channel is used */ - -int __devinit snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu) -{ - emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80); - if (! emu->p16v_saved) - return -ENOMEM; - return 0; -} - -void snd_p16v_free_pm_buffer(struct snd_emu10k1 *emu) -{ - vfree(emu->p16v_saved); -} - -void snd_p16v_suspend(struct snd_emu10k1 *emu) -{ - int i, ch; - unsigned int *val; - - val = emu->p16v_saved; - for (ch = 0; ch < NUM_CHS; ch++) - for (i = 0; i < 0x80; i++, val++) - *val = snd_emu10k1_ptr20_read(emu, i, ch); -} - -void snd_p16v_resume(struct snd_emu10k1 *emu) -{ - int i, ch; - unsigned int *val; - - val = emu->p16v_saved; - for (ch = 0; ch < NUM_CHS; ch++) - for (i = 0; i < 0x80; i++, val++) - snd_emu10k1_ptr20_write(emu, i, ch, *val); -} -#endif diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.h b/ANDROID_3.4.5/sound/pci/emu10k1/p16v.h deleted file mode 100644 index 4e0ee1a9..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/p16v.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> - * Driver p16v chips - * Version: 0.21 - * - * FEATURES currently supported: - * Output fixed at S32_LE, 2 channel to hw:0,0 - * Rates: 44.1, 48, 96, 192. - * - * Changelog: - * 0.8 - * Use separate card based buffer for periods table. - * 0.9 - * Use 2 channel output streams instead of 8 channel. - * (8 channel output streams might be good for ASIO type output) - * Corrected speaker output, so Front -> Front etc. - * 0.10 - * Fixed missed interrupts. - * 0.11 - * Add Sound card model number and names. - * Add Analog volume controls. - * 0.12 - * Corrected playback interrupts. Now interrupt per period, instead of half period. - * 0.13 - * Use single trigger for multichannel. - * 0.14 - * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo. - * 0.15 - * Force buffer_size / period_size == INTEGER. - * 0.16 - * Update p16v.c to work with changed alsa api. - * 0.17 - * Update p16v.c to work with changed alsa api. Removed boot_devs. - * 0.18 - * Merging with snd-emu10k1 driver. - * 0.19 - * One stereo channel at 24bit now works. - * 0.20 - * Added better register defines. - * 0.21 - * Split from p16v.c - * - * - * BUGS: - * Some stability problems when unloading the snd-p16v kernel module. - * -- - * - * TODO: - * SPDIF out. - * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz. - * Currently capture fixed at 48000Hz. - * - * -- - * GENERAL INFO: - * Model: SB0240 - * P16V Chip: CA0151-DBS - * Audigy 2 Chip: CA0102-IAT - * AC97 Codec: STAC 9721 - * ADC: Philips 1361T (Stereo 24bit) - * DAC: CS4382-K (8-channel, 24bit, 192Khz) - * - * This code was initially based on code from ALSA's emu10k1x.c which is: - * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/********************************************************************************************************/ -/* Audigy2 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */ -/********************************************************************************************************/ - -/* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE. - * The sample rate is also controlled by the same registers that control the rate of the EMU10K2 sample rate converters. - */ - -/* Initially all registers from 0x00 to 0x3f have zero contents. */ -#define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */ - /* One list entry: 4 bytes for DMA address, - * 4 bytes for period_size << 16. - * One list entry is 8 bytes long. - * One list entry for each period in the buffer. - */ -#define PLAYBACK_LIST_SIZE 0x01 /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000 */ -#define PLAYBACK_LIST_PTR 0x02 /* Pointer to the current period being played */ -#define PLAYBACK_UNKNOWN3 0x03 /* Not used */ -#define PLAYBACK_DMA_ADDR 0x04 /* Playback DMA address */ -#define PLAYBACK_PERIOD_SIZE 0x05 /* Playback period size. win2000 uses 0x04000000 */ -#define PLAYBACK_POINTER 0x06 /* Playback period pointer. Used with PLAYBACK_LIST_PTR to determine buffer position currently in DAC */ -#define PLAYBACK_FIFO_END_ADDRESS 0x07 /* Playback FIFO end address */ -#define PLAYBACK_FIFO_POINTER 0x08 /* Playback FIFO pointer and number of valid sound samples in cache */ -#define PLAYBACK_UNKNOWN9 0x09 /* Not used */ -#define CAPTURE_DMA_ADDR 0x10 /* Capture DMA address */ -#define CAPTURE_BUFFER_SIZE 0x11 /* Capture buffer size */ -#define CAPTURE_POINTER 0x12 /* Capture buffer pointer. Sample currently in ADC */ -#define CAPTURE_FIFO_POINTER 0x13 /* Capture FIFO pointer and number of valid sound samples in cache */ -#define CAPTURE_P16V_VOLUME1 0x14 /* Low: Capture volume 0xXXXX3030 */ -#define CAPTURE_P16V_VOLUME2 0x15 /* High:Has no effect on capture volume */ -#define CAPTURE_P16V_SOURCE 0x16 /* P16V source select. Set to 0x0700E4E5 for AC97 CAPTURE */ - /* [0:1] Capture input 0 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [3:2] Capture input 1 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [5:4] Capture input 2 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [7:6] Capture input 3 channel select. 0 = Capture output 0. - * 1 = Capture output 1. - * 2 = Capture output 2. - * 3 = Capture output 3. - * [9:8] Playback input 0 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [11:10] Playback input 1 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [13:12] Playback input 2 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [15:14] Playback input 3 channel select. 0 = Play output 0. - * 1 = Play output 1. - * 2 = Play output 2. - * 3 = Play output 3. - * [19:16] Playback mixer output enable. 1 bit per channel. - * [23:20] Capture mixer output enable. 1 bit per channel. - * [26:24] FX engine channel capture 0 = 0x60-0x67. - * 1 = 0x68-0x6f. - * 2 = 0x70-0x77. - * 3 = 0x78-0x7f. - * 4 = 0x80-0x87. - * 5 = 0x88-0x8f. - * 6 = 0x90-0x97. - * 7 = 0x98-0x9f. - * [31:27] Not used. - */ - - /* 0x1 = capture on. - * 0x100 = capture off. - * 0x200 = capture off. - * 0x1000 = capture off. - */ -#define CAPTURE_RATE_STATUS 0x17 /* Capture sample rate. Read only */ - /* [15:0] Not used. - * [18:16] Channel 0 Detected sample rate. 0 - 44.1khz - * 1 - 48 khz - * 2 - 96 khz - * 3 - 192 khz - * 7 - undefined rate. - * [19] Channel 0. 1 - Valid, 0 - Not Valid. - * [22:20] Channel 1 Detected sample rate. - * [23] Channel 1. 1 - Valid, 0 - Not Valid. - * [26:24] Channel 2 Detected sample rate. - * [27] Channel 2. 1 - Valid, 0 - Not Valid. - * [30:28] Channel 3 Detected sample rate. - * [31] Channel 3. 1 - Valid, 0 - Not Valid. - */ -/* 0x18 - 0x1f unused */ -#define PLAYBACK_LAST_SAMPLE 0x20 /* The sample currently being played. Read only */ -/* 0x21 - 0x3f unused */ -#define BASIC_INTERRUPT 0x40 /* Used by both playback and capture interrupt handler */ - /* Playback (0x1<<channel_id) Don't touch high 16bits. */ - /* Capture (0x100<<channel_id). not tested */ - /* Start Playback [3:0] (one bit per channel) - * Start Capture [11:8] (one bit per channel) - * Record source select for channel 0 [18:16] - * Record source select for channel 1 [22:20] - * Record source select for channel 2 [26:24] - * Record source select for channel 3 [30:28] - * 0 - SPDIF channel. - * 1 - I2S channel. - * 2 - SRC48 channel. - * 3 - SRCMulti_SPDIF channel. - * 4 - SRCMulti_I2S channel. - * 5 - SPDIF channel. - * 6 - fxengine capture. - * 7 - AC97 capture. - */ - /* Default 41110000. - * Writing 0xffffffff hangs the PC. - * Writing 0xffff0000 -> 77770000 so it must be some sort of route. - * bit 0x1 starts DMA playback on channel_id 0 - */ -/* 0x41,42 take values from 0 - 0xffffffff, but have no effect on playback */ -/* 0x43,0x48 do not remember settings */ -/* 0x41-45 unused */ -#define WATERMARK 0x46 /* Test bit to indicate cache level usage */ - /* Values it can have while playing on channel 0. - * 0000f000, 0000f004, 0000f008, 0000f00c. - * Readonly. - */ -/* 0x47-0x4f unused */ -/* 0x50-0x5f Capture cache data */ -#define SRCSel 0x60 /* SRCSel. Default 0x4. Bypass P16V 0x14 */ - /* [0] 0 = 10K2 audio, 1 = SRC48 mixer output. - * [2] 0 = 10K2 audio, 1 = SRCMulti SPDIF mixer output. - * [4] 0 = 10K2 audio, 1 = SRCMulti I2S mixer output. - */ - /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */ - /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */ - /* SRC48 and SRCMULTI sample rate select and output select. */ - /* 0xffffffff -> 0xC0000015 - * 0xXXXXXXX4 = Enable Front Left/Right - * Enable PCMs - */ - -/* 0x61 -> 0x6c are Volume controls */ -#define PLAYBACK_VOLUME_MIXER1 0x61 /* SRC48 Low to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER2 0x62 /* SRC48 High to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER3 0x63 /* SRCMULTI SPDIF Low to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER4 0x64 /* SRCMULTI SPDIF High to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER5 0x65 /* SRCMULTI I2S Low to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER6 0x66 /* SRCMULTI I2S High to mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER7 0x67 /* P16V Low to SRCMULTI SPDIF mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER8 0x68 /* P16V High to SRCMULTI SPDIF mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER9 0x69 /* P16V Low to SRCMULTI I2S mixer input volume control. */ - /* 0xXXXX3030 = PCM0 Volume (Front). - * 0x3030XXXX = PCM1 Volume (Center) - */ -#define PLAYBACK_VOLUME_MIXER10 0x6a /* P16V High to SRCMULTI I2S mixer input volume control. */ - /* 0x3030XXXX = PCM3 Volume (Rear). */ -#define PLAYBACK_VOLUME_MIXER11 0x6b /* E10K2 Low to SRC48 mixer input volume control. */ -#define PLAYBACK_VOLUME_MIXER12 0x6c /* E10K2 High to SRC48 mixer input volume control. */ - -#define SRC48_ENABLE 0x6d /* SRC48 input audio enable */ - /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */ - /* [23:16] The corresponding P16V channel to SRC48 enabled if == 1. - * [31:24] The corresponding E10K2 channel to SRC48 enabled. - */ -#define SRCMULTI_ENABLE 0x6e /* SRCMulti input audio enable. Default 0xffffffff */ - /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */ - /* [7:0] The corresponding P16V channel to SRCMulti_I2S enabled if == 1. - * [15:8] The corresponding E10K2 channel to SRCMulti I2S enabled. - * [23:16] The corresponding P16V channel to SRCMulti SPDIF enabled. - * [31:24] The corresponding E10K2 channel to SRCMulti SPDIF enabled. - */ - /* Bypass P16V 0xff00ff00 - * Bitmap. 0 = Off, 1 = On. - * P16V playback outputs: - * 0xXXXXXXX1 = PCM0 Left. (Front) - * 0xXXXXXXX2 = PCM0 Right. - * 0xXXXXXXX4 = PCM1 Left. (Center/LFE) - * 0xXXXXXXX8 = PCM1 Right. - * 0xXXXXXX1X = PCM2 Left. (Unknown) - * 0xXXXXXX2X = PCM2 Right. - * 0xXXXXXX4X = PCM3 Left. (Rear) - * 0xXXXXXX8X = PCM3 Right. - */ -#define AUDIO_OUT_ENABLE 0x6f /* Default: 000100FF */ - /* [3:0] Does something, but not documented. Probably capture enable. - * [7:4] Playback channels enable. not documented. - * [16] AC97 output enable if == 1 - * [30] 0 = SRCMulti_I2S input from fxengine 0x68-0x6f. - * 1 = SRCMulti_I2S input from SRC48 output. - * [31] 0 = SRCMulti_SPDIF input from fxengine 0x60-0x67. - * 1 = SRCMulti_SPDIF input from SRC48 output. - */ - /* 0xffffffff -> C00100FF */ - /* 0 -> Not playback sound, irq still running */ - /* 0xXXXXXX10 = PCM0 Left/Right On. (Front) - * 0xXXXXXX20 = PCM1 Left/Right On. (Center/LFE) - * 0xXXXXXX40 = PCM2 Left/Right On. (Unknown) - * 0xXXXXXX80 = PCM3 Left/Right On. (Rear) - */ -#define PLAYBACK_SPDIF_SELECT 0x70 /* Default: 12030F00 */ - /* 0xffffffff -> 3FF30FFF */ - /* 0x00000001 pauses stream/irq fail. */ - /* All other bits do not effect playback */ -#define PLAYBACK_SPDIF_SRC_SELECT 0x71 /* Default: 0000E4E4 */ - /* 0xffffffff -> F33FFFFF */ - /* All bits do not effect playback */ -#define PLAYBACK_SPDIF_USER_DATA0 0x72 /* SPDIF out user data 0 */ -#define PLAYBACK_SPDIF_USER_DATA1 0x73 /* SPDIF out user data 1 */ -/* 0x74-0x75 unknown */ -#define CAPTURE_SPDIF_CONTROL 0x76 /* SPDIF in control setting */ -#define CAPTURE_SPDIF_STATUS 0x77 /* SPDIF in status */ -#define CAPURE_SPDIF_USER_DATA0 0x78 /* SPDIF in user data 0 */ -#define CAPURE_SPDIF_USER_DATA1 0x79 /* SPDIF in user data 1 */ -#define CAPURE_SPDIF_USER_DATA2 0x7a /* SPDIF in user data 2 */ - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/p17v.h b/ANDROID_3.4.5/sound/pci/emu10k1/p17v.h deleted file mode 100644 index 4ef5f68a..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/p17v.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> - * Driver p17v chips - * Version: 0.01 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/******************************************************************************/ -/* Audigy2Value Tina (P17V) pointer-offset register set, - * accessed through the PTR20 and DATA24 registers */ -/******************************************************************************/ - -/* 00 - 07: Not used */ -#define P17V_PLAYBACK_FIFO_PTR 0x08 /* Current playback fifo pointer - * and number of sound samples in cache. - */ -/* 09 - 12: Not used */ -#define P17V_CAPTURE_FIFO_PTR 0x13 /* Current capture fifo pointer - * and number of sound samples in cache. - */ -/* 14 - 17: Not used */ -#define P17V_PB_CHN_SEL 0x18 /* P17v playback channel select */ -#define P17V_SE_SLOT_SEL_L 0x19 /* Sound Engine slot select low */ -#define P17V_SE_SLOT_SEL_H 0x1a /* Sound Engine slot select high */ -/* 1b - 1f: Not used */ -/* 20 - 2f: Not used */ -/* 30 - 3b: Not used */ -#define P17V_SPI 0x3c /* SPI interface register */ -#define P17V_I2C_ADDR 0x3d /* I2C Address */ -#define P17V_I2C_0 0x3e /* I2C Data */ -#define P17V_I2C_1 0x3f /* I2C Data */ -/* I2C values */ -#define I2C_A_ADC_ADD_MASK 0x000000fe /*The address is a 7 bit address */ -#define I2C_A_ADC_RW_MASK 0x00000001 /*bit mask for R/W */ -#define I2C_A_ADC_TRANS_MASK 0x00000010 /*Bit mask for I2c address DAC value */ -#define I2C_A_ADC_ABORT_MASK 0x00000020 /*Bit mask for I2C transaction abort flag */ -#define I2C_A_ADC_LAST_MASK 0x00000040 /*Bit mask for Last word transaction */ -#define I2C_A_ADC_BYTE_MASK 0x00000080 /*Bit mask for Byte Mode */ - -#define I2C_A_ADC_ADD 0x00000034 /*This is the Device address for ADC */ -#define I2C_A_ADC_READ 0x00000001 /*To perform a read operation */ -#define I2C_A_ADC_START 0x00000100 /*Start I2C transaction */ -#define I2C_A_ADC_ABORT 0x00000200 /*I2C transaction abort */ -#define I2C_A_ADC_LAST 0x00000400 /*I2C last transaction */ -#define I2C_A_ADC_BYTE 0x00000800 /*I2C one byte mode */ - -#define I2C_D_ADC_REG_MASK 0xfe000000 /*ADC address register */ -#define I2C_D_ADC_DAT_MASK 0x01ff0000 /*ADC data register */ - -#define ADC_TIMEOUT 0x00000007 /*ADC Timeout Clock Disable */ -#define ADC_IFC_CTRL 0x0000000b /*ADC Interface Control */ -#define ADC_MASTER 0x0000000c /*ADC Master Mode Control */ -#define ADC_POWER 0x0000000d /*ADC PowerDown Control */ -#define ADC_ATTEN_ADCL 0x0000000e /*ADC Attenuation ADCL */ -#define ADC_ATTEN_ADCR 0x0000000f /*ADC Attenuation ADCR */ -#define ADC_ALC_CTRL1 0x00000010 /*ADC ALC Control 1 */ -#define ADC_ALC_CTRL2 0x00000011 /*ADC ALC Control 2 */ -#define ADC_ALC_CTRL3 0x00000012 /*ADC ALC Control 3 */ -#define ADC_NOISE_CTRL 0x00000013 /*ADC Noise Gate Control */ -#define ADC_LIMIT_CTRL 0x00000014 /*ADC Limiter Control */ -#define ADC_MUX 0x00000015 /*ADC Mux offset */ -#if 0 -/* FIXME: Not tested yet. */ -#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain -#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB -#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute -#define ADC_MUTE 0x000000c0 //Value to mute ADC -#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select -#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock -#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter -#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window -#endif - -#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux -#define ADC_MUX_0 0x00000001 //Value to select Unknown at ADC Mux (Not used) -#define ADC_MUX_1 0x00000002 //Value to select Unknown at ADC Mux (Not used) -#define ADC_MUX_2 0x00000004 //Value to select Mic at ADC Mux -#define ADC_MUX_3 0x00000008 //Value to select Line-In at ADC Mux - -#define P17V_START_AUDIO 0x40 /* Start Audio bit */ -/* 41 - 47: Reserved */ -#define P17V_START_CAPTURE 0x48 /* Start Capture bit */ -#define P17V_CAPTURE_FIFO_BASE 0x49 /* Record FIFO base address */ -#define P17V_CAPTURE_FIFO_SIZE 0x4a /* Record FIFO buffer size */ -#define P17V_CAPTURE_FIFO_INDEX 0x4b /* Record FIFO capture index */ -#define P17V_CAPTURE_VOL_H 0x4c /* P17v capture volume control */ -#define P17V_CAPTURE_VOL_L 0x4d /* P17v capture volume control */ -/* 4e - 4f: Not used */ -/* 50 - 5f: Not used */ -#define P17V_SRCSel 0x60 /* SRC48 and SRCMulti sample rate select - * and output select - */ -#define P17V_MIXER_AC97_10K1_VOL_L 0x61 /* 10K to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_10K1_VOL_H 0x62 /* 10K to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_P17V_VOL_L 0x63 /* P17V to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_P17V_VOL_H 0x64 /* P17V to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_SRP_REC_VOL_L 0x65 /* SRP Record to Mixer_AC97 input volume control */ -#define P17V_MIXER_AC97_SRP_REC_VOL_H 0x66 /* SRP Record to Mixer_AC97 input volume control */ -/* 67 - 68: Reserved */ -#define P17V_MIXER_Spdif_10K1_VOL_L 0x69 /* 10K to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_10K1_VOL_H 0x6A /* 10K to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_P17V_VOL_L 0x6B /* P17V to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_P17V_VOL_H 0x6C /* P17V to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_SRP_REC_VOL_L 0x6D /* SRP Record to Mixer_Spdif input volume control */ -#define P17V_MIXER_Spdif_SRP_REC_VOL_H 0x6E /* SRP Record to Mixer_Spdif input volume control */ -/* 6f - 70: Reserved */ -#define P17V_MIXER_I2S_10K1_VOL_L 0x71 /* 10K to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_10K1_VOL_H 0x72 /* 10K to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_P17V_VOL_L 0x73 /* P17V to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_P17V_VOL_H 0x74 /* P17V to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_SRP_REC_VOL_L 0x75 /* SRP Record to Mixer_I2S input volume control */ -#define P17V_MIXER_I2S_SRP_REC_VOL_H 0x76 /* SRP Record to Mixer_I2S input volume control */ -/* 77 - 78: Reserved */ -#define P17V_MIXER_AC97_ENABLE 0x79 /* Mixer AC97 input audio enable */ -#define P17V_MIXER_SPDIF_ENABLE 0x7A /* Mixer SPDIF input audio enable */ -#define P17V_MIXER_I2S_ENABLE 0x7B /* Mixer I2S input audio enable */ -#define P17V_AUDIO_OUT_ENABLE 0x7C /* Audio out enable */ -#define P17V_MIXER_ATT 0x7D /* SRP Mixer Attenuation Select */ -#define P17V_SRP_RECORD_SRR 0x7E /* SRP Record channel source Select */ -#define P17V_SOFT_RESET_SRP_MIXER 0x7F /* SRP and mixer soft reset */ - -#define P17V_AC97_OUT_MASTER_VOL_L 0x80 /* AC97 Output master volume control */ -#define P17V_AC97_OUT_MASTER_VOL_H 0x81 /* AC97 Output master volume control */ -#define P17V_SPDIF_OUT_MASTER_VOL_L 0x82 /* SPDIF Output master volume control */ -#define P17V_SPDIF_OUT_MASTER_VOL_H 0x83 /* SPDIF Output master volume control */ -#define P17V_I2S_OUT_MASTER_VOL_L 0x84 /* I2S Output master volume control */ -#define P17V_I2S_OUT_MASTER_VOL_H 0x85 /* I2S Output master volume control */ -/* 86 - 87: Not used */ -#define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE 0x88 /* I2S out mono channel swap - * and phase inverse */ -#define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE 0x89 /* SPDIF out mono channel swap - * and phase inverse */ -/* 8A: Not used */ -#define P17V_SRP_P17V_ESR 0x8B /* SRP_P17V estimated sample rate and rate lock */ -#define P17V_SRP_REC_ESR 0x8C /* SRP_REC estimated sample rate and rate lock */ -#define P17V_SRP_BYPASS 0x8D /* srps channel bypass and srps bypass */ -/* 8E - 92: Not used */ -#define P17V_I2S_SRC_SEL 0x93 /* I2SIN mode sel */ - - - - - - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/timer.c b/ANDROID_3.4.5/sound/pci/emu10k1/timer.c deleted file mode 100644 index 72321e94..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/timer.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) by Lee Revell <rlrevell@joe-job.com> - * Clemens Ladisch <clemens@ladisch.de> - * Routines for control of EMU10K1 chips - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/time.h> -#include <sound/core.h> -#include <sound/emu10k1.h> - -static int snd_emu10k1_timer_start(struct snd_timer *timer) -{ - struct snd_emu10k1 *emu; - unsigned long flags; - unsigned int delay; - - emu = snd_timer_chip(timer); - delay = timer->sticks - 1; - if (delay < 5 ) /* minimum time is 5 ticks */ - delay = 5; - spin_lock_irqsave(&emu->reg_lock, flags); - snd_emu10k1_intr_enable(emu, INTE_INTERVALTIMERENB); - outw(delay & TIMER_RATE_MASK, emu->port + TIMER); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_timer_stop(struct snd_timer *timer) -{ - struct snd_emu10k1 *emu; - unsigned long flags; - - emu = snd_timer_chip(timer); - spin_lock_irqsave(&emu->reg_lock, flags); - snd_emu10k1_intr_disable(emu, INTE_INTERVALTIMERENB); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return 0; -} - -static int snd_emu10k1_timer_precise_resolution(struct snd_timer *timer, - unsigned long *num, unsigned long *den) -{ - *num = 1; - *den = 48000; - return 0; -} - -static struct snd_timer_hardware snd_emu10k1_timer_hw = { - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 20833, /* 1 sample @ 48KHZ = 20.833...us */ - .ticks = 1024, - .start = snd_emu10k1_timer_start, - .stop = snd_emu10k1_timer_stop, - .precise_resolution = snd_emu10k1_timer_precise_resolution, -}; - -int __devinit snd_emu10k1_timer(struct snd_emu10k1 *emu, int device) -{ - struct snd_timer *timer = NULL; - struct snd_timer_id tid; - int err; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = emu->card->number; - tid.device = device; - tid.subdevice = 0; - if ((err = snd_timer_new(emu->card, "EMU10K1", &tid, &timer)) >= 0) { - strcpy(timer->name, "EMU10K1 timer"); - timer->private_data = emu; - timer->hw = snd_emu10k1_timer_hw; - } - emu->timer = timer; - return err; -} diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/tina2.h b/ANDROID_3.4.5/sound/pci/emu10k1/tina2.h deleted file mode 100644 index f2d8eb6c..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/tina2.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> - * Driver tina2 chips - * Version: 0.1 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/********************************************************************************************************/ -/* Audigy2 Tina2 (notebook) pointer-offset register set, accessed through the PTR2 and DATA2 registers */ -/********************************************************************************************************/ - -#define TINA2_VOLUME 0x71 /* Attenuate playback volume to prevent distortion. */ - /* The windows driver does not use this register, - * so it must use some other attenuation method. - * Without this, the output is 12dB too loud, - * resulting in distortion. - */ - diff --git a/ANDROID_3.4.5/sound/pci/emu10k1/voice.c b/ANDROID_3.4.5/sound/pci/emu10k1/voice.c deleted file mode 100644 index 101e7cb7..00000000 --- a/ANDROID_3.4.5/sound/pci/emu10k1/voice.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Creative Labs, Inc. - * Lee Revell <rlrevell@joe-job.com> - * Routines for control of EMU10K1 chips - voice manager - * - * Rewrote voice allocator for multichannel support - rlrevell 12/2004 - * - * BUGS: - * -- - * - * TODO: - * -- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/time.h> -#include <linux/export.h> -#include <sound/core.h> -#include <sound/emu10k1.h> - -/* Previously the voice allocator started at 0 every time. The new voice - * allocator uses a round robin scheme. The next free voice is tracked in - * the card record and each allocation begins where the last left off. The - * hardware requires stereo interleaved voices be aligned to an even/odd - * boundary. For multichannel voice allocation we ensure than the block of - * voices does not cross the 32 voice boundary. This simplifies the - * multichannel support and ensures we can use a single write to the - * (set|clear)_loop_stop registers. Otherwise (for example) the voices would - * get out of sync when pausing/resuming a stream. - * --rlrevell - */ - -static int voice_alloc(struct snd_emu10k1 *emu, int type, int number, - struct snd_emu10k1_voice **rvoice) -{ - struct snd_emu10k1_voice *voice; - int i, j, k, first_voice, last_voice, skip; - - *rvoice = NULL; - first_voice = last_voice = 0; - for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) { - /* - printk(KERN_DEBUG "i %d j %d next free %d!\n", - i, j, emu->next_free_voice); - */ - i %= NUM_G; - - /* stereo voices must be even/odd */ - if ((number == 2) && (i % 2)) { - i++; - continue; - } - - skip = 0; - for (k = 0; k < number; k++) { - voice = &emu->voices[(i+k) % NUM_G]; - if (voice->use) { - skip = 1; - break; - } - } - if (!skip) { - /* printk(KERN_DEBUG "allocated voice %d\n", i); */ - first_voice = i; - last_voice = (i + number) % NUM_G; - emu->next_free_voice = last_voice; - break; - } - } - - if (first_voice == last_voice) - return -ENOMEM; - - for (i = 0; i < number; i++) { - voice = &emu->voices[(first_voice + i) % NUM_G]; - /* - printk(kERN_DEBUG "voice alloc - %i, %i of %i\n", - voice->number, idx-first_voice+1, number); - */ - voice->use = 1; - switch (type) { - case EMU10K1_PCM: - voice->pcm = 1; - break; - case EMU10K1_SYNTH: - voice->synth = 1; - break; - case EMU10K1_MIDI: - voice->midi = 1; - break; - case EMU10K1_EFX: - voice->efx = 1; - break; - } - } - *rvoice = &emu->voices[first_voice]; - return 0; -} - -int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number, - struct snd_emu10k1_voice **rvoice) -{ - unsigned long flags; - int result; - - if (snd_BUG_ON(!rvoice)) - return -EINVAL; - if (snd_BUG_ON(!number)) - return -EINVAL; - - spin_lock_irqsave(&emu->voice_lock, flags); - for (;;) { - result = voice_alloc(emu, type, number, rvoice); - if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI) - break; - - /* free a voice from synth */ - if (emu->get_synth_voice) { - result = emu->get_synth_voice(emu); - if (result >= 0) { - struct snd_emu10k1_voice *pvoice = &emu->voices[result]; - pvoice->interrupt = NULL; - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0; - pvoice->epcm = NULL; - } - } - if (result < 0) - break; - } - spin_unlock_irqrestore(&emu->voice_lock, flags); - - return result; -} - -EXPORT_SYMBOL(snd_emu10k1_voice_alloc); - -int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, - struct snd_emu10k1_voice *pvoice) -{ - unsigned long flags; - - if (snd_BUG_ON(!pvoice)) - return -EINVAL; - spin_lock_irqsave(&emu->voice_lock, flags); - pvoice->interrupt = NULL; - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0; - pvoice->epcm = NULL; - snd_emu10k1_voice_init(emu, pvoice->number); - spin_unlock_irqrestore(&emu->voice_lock, flags); - return 0; -} - -EXPORT_SYMBOL(snd_emu10k1_voice_free); |