summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/sound/pci/emu10k1
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/sound/pci/emu10k1')
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/Makefile15
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emu10k1.c288
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_callback.c552
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_main.c2101
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_patch.c229
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth.c124
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emu10k1_synth_local.h42
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emu10k1x.c1635
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emufx.c2758
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emumixer.c2143
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emumpu401.c396
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emupcm.c1870
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/emuproc.c671
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/io.c583
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/irq.c208
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/memory.c573
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/p16v.c934
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/p16v.h299
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/p17v.h158
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/timer.c96
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/tina2.h32
-rw-r--r--ANDROID_3.4.5/sound/pci/emu10k1/voice.c168
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, &reg); /* 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, &reg);
- 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, &reg);
- 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, &reg);
- 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, &reg);
- 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, &reg);
- 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, &reg);
- snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
- 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, &reg);
- 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", &reg, &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", &reg, &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", &reg, &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);