diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/isa')
85 files changed, 0 insertions, 40530 deletions
diff --git a/ANDROID_3.4.5/sound/isa/Kconfig b/ANDROID_3.4.5/sound/isa/Kconfig deleted file mode 100644 index 52064cfa..00000000 --- a/ANDROID_3.4.5/sound/isa/Kconfig +++ /dev/null @@ -1,446 +0,0 @@ -# ALSA ISA drivers - -config SND_WSS_LIB - tristate - select SND_PCM - -config SND_SB_COMMON - tristate - -config SND_SB8_DSP - tristate - select SND_PCM - select SND_SB_COMMON - -config SND_SB16_DSP - tristate - select SND_PCM - select SND_SB_COMMON - -menuconfig SND_ISA - bool "ISA sound devices" - depends on ISA && ISA_DMA_API - default y - help - Support for sound devices connected via the ISA bus. - -if SND_ISA - -config SND_ADLIB - tristate "AdLib FM card" - select SND_OPL3_LIB - help - Say Y here to include support for AdLib FM cards. - - To compile this driver as a module, choose M here: the module - will be called snd-adlib. - -config SND_AD1816A - tristate "Analog Devices SoundPort AD1816A" - depends on PNP - select ISAPNP - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for Analog Devices SoundPort - AD1816A or compatible sound chips. - - To compile this driver as a module, choose M here: the module - will be called snd-ad1816a. - -config SND_AD1848 - tristate "Generic AD1848/CS4248 driver" - select SND_WSS_LIB - help - Say Y here to include support for AD1848 (Analog Devices) or - CS4248 (Cirrus Logic - Crystal Semiconductors) chips. - - For newer chips from Cirrus Logic, use the CS4231 or CS4232+ - drivers. - - To compile this driver as a module, choose M here: the module - will be called snd-ad1848. - -config SND_ALS100 - tristate "Diamond Tech. DT-019x and Avance Logic ALSxxx" - depends on PNP - select ISAPNP - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB16_DSP - help - Say Y here to include support for soundcards based on the - Diamond Technologies DT-019X or Avance Logic chips: ALS007, - ALS100, ALS110, ALS120 and ALS200 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-als100. - -config SND_AZT1605 - tristate "Aztech AZT1605 Driver" - depends on SND - select SND_WSS_LIB - select SND_MPU401_UART - select SND_OPL3_LIB - help - Say Y here to include support for Aztech Sound Galaxy cards - based on the AZT1605 chipset. - - To compile this driver as a module, choose M here: the module - will be called snd-azt1605. - -config SND_AZT2316 - tristate "Aztech AZT2316 Driver" - depends on SND - select SND_WSS_LIB - select SND_MPU401_UART - select SND_OPL3_LIB - help - Say Y here to include support for Aztech Sound Galaxy cards - based on the AZT2316 chipset. - - To compile this driver as a module, choose M here: the module - will be called snd-azt2316. - -config SND_AZT2320 - tristate "Aztech Systems AZT2320" - depends on PNP - select ISAPNP - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on the - Aztech Systems AZT2320 chip. - - To compile this driver as a module, choose M here: the module - will be called snd-azt2320. - -config SND_CMI8330 - tristate "C-Media CMI8330" - select SND_WSS_LIB - select SND_SB16_DSP - select SND_OPL3_LIB - select SND_MPU401_UART - help - Say Y here to include support for soundcards based on the - C-Media CMI8330 chip. - - To compile this driver as a module, choose M here: the module - will be called snd-cmi8330. - -config SND_CS4231 - tristate "Generic Cirrus Logic CS4231 driver" - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for CS4231 chips from Cirrus - Logic - Crystal Semiconductors. - - To compile this driver as a module, choose M here: the module - will be called snd-cs4231. - -config SND_CS4236 - tristate "Generic Cirrus Logic CS4232/CS4236+ driver" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y to include support for CS4232,CS4235,CS4236,CS4237B, - CS4238B,CS4239 chips from Cirrus Logic - Crystal - Semiconductors. - - To compile this driver as a module, choose M here: the module - will be called snd-cs4236. - -config SND_ES1688 - tristate "Generic ESS ES688/ES1688 and ES968 PnP driver" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for ESS AudioDrive ES688 or - ES1688 chips. Also, this module support cards with ES968 PnP chip. - - To compile this driver as a module, choose M here: the module - will be called snd-es1688. - -config SND_ES18XX - tristate "Generic ESS ES18xx driver" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for ESS AudioDrive ES18xx chips. - - To compile this driver as a module, choose M here: the module - will be called snd-es18xx. - -config SND_SC6000 - tristate "Gallant SC-6000/6600/7000 and Audio Excel DSP 16" - depends on HAS_IOPORT - select SND_WSS_LIB - select SND_OPL3_LIB - select SND_MPU401_UART - help - Say Y here to include support for Gallant SC-6000, SC-6600, SC-7000 - cards and clones: - Audio Excel DSP 16 and Zoltrix AV302. - - These cards are based on CompuMedia ASC-9308 or ASC-9408 chips. - - To compile this driver as a module, choose M here: the module - will be called snd-sc6000. - -config SND_GUSCLASSIC - tristate "Gravis UltraSound Classic" - select SND_RAWMIDI - select SND_PCM - help - Say Y here to include support for Gravis UltraSound Classic - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-gusclassic. - -config SND_GUSEXTREME - tristate "Gravis UltraSound Extreme" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_PCM - help - Say Y here to include support for Gravis UltraSound Extreme - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-gusextreme. - -config SND_GUSMAX - tristate "Gravis UltraSound MAX" - select SND_RAWMIDI - select SND_WSS_LIB - help - Say Y here to include support for Gravis UltraSound MAX - soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-gusmax. - -config SND_INTERWAVE - tristate "AMD InterWave, Gravis UltraSound PnP" - depends on PNP - select SND_RAWMIDI - select SND_WSS_LIB - help - Say Y here to include support for AMD InterWave based - soundcards (Gravis UltraSound Plug & Play, STB SoundRage32, - MED3210, Dynasonic Pro, Panasonic PCA761AW). - - To compile this driver as a module, choose M here: the module - will be called snd-interwave. - -config SND_INTERWAVE_STB - tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)" - depends on PNP - select SND_RAWMIDI - select SND_WSS_LIB - help - Say Y here to include support for AMD InterWave based - soundcards with a TEA6330T bass and treble regulator - (UltraSound 32-Pro). - - To compile this driver as a module, choose M here: the module - will be called snd-interwave-stb. - -config SND_JAZZ16 - tristate "Media Vision Jazz16 card and compatibles" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB8_DSP - help - Say Y here to include support for soundcards based on the - Media Vision Jazz16 chipset: digital chip MVD1216 (Jazz16), - codec MVA416 (CS4216) and mixer MVA514 (ICS2514). - Media Vision's Jazz16 cards were sold under names Pro Sonic 16, - Premium 3-D and Pro 3-D. There were also OEMs cards with the - Jazz16 chipset. - - To compile this driver as a module, choose M here: the module - will be called snd-jazz16. - -config SND_OPL3SA2 - tristate "Yamaha OPL3-SA2/SA3" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3 - chips. - - To compile this driver as a module, choose M here: the module - will be called snd-opl3sa2. - -config SND_OPTI92X_AD1848 - tristate "OPTi 82C92x - AD1848" - select SND_OPL3_LIB - select SND_OPL4_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on Opti - 82C92x or OTI-601 chips and using an AD1848 codec. - - To compile this driver as a module, choose M here: the module - will be called snd-opti92x-ad1848. - -config SND_OPTI92X_CS4231 - tristate "OPTi 82C92x - CS4231" - select SND_OPL3_LIB - select SND_OPL4_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on Opti - 82C92x chips and using a CS4231 codec. - - To compile this driver as a module, choose M here: the module - will be called snd-opti92x-cs4231. - -config SND_OPTI93X - tristate "OPTi 82C93x" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for soundcards based on Opti - 82C93x chips. - - To compile this driver as a module, choose M here: the module - will be called snd-opti93x. - -config SND_MIRO - tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver" - select SND_OPL4_LIB - select SND_WSS_LIB - select SND_MPU401_UART - select SND_PCM - help - Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro, - miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-miro. - -config SND_SB8 - tristate "Sound Blaster 1.0/2.0/Pro (8-bit)" - select SND_OPL3_LIB - select SND_RAWMIDI - select SND_SB8_DSP - help - Say Y here to include support for Creative Sound Blaster 1.0/ - 2.0/Pro (8-bit) or 100% compatible soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-sb8. - -config SND_SB16 - tristate "Sound Blaster 16 (PnP)" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB16_DSP - help - Say Y here to include support for Sound Blaster 16 soundcards - (including the Plug and Play version). - - To compile this driver as a module, choose M here: the module - will be called snd-sb16. - -config SND_SBAWE - tristate "Sound Blaster AWE (32,64) (PnP)" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_SB16_DSP - help - Say Y here to include support for Sound Blaster AWE soundcards - (including the Plug and Play version). - - To compile this driver as a module, choose M here: the module - will be called snd-sbawe. - -config SND_SB16_CSP - bool "Sound Blaster 16/AWE CSP support" - depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) - select FW_LOADER - help - Say Y here to include support for the CSP core. This special - coprocessor can do variable tasks like various compression and - decompression algorithms. - -config SND_SSCAPE - tristate "Ensoniq SoundScape driver" - select SND_MPU401_UART - select SND_WSS_LIB - select FW_LOADER - help - Say Y here to include support for Ensoniq SoundScape - and Ensoniq OEM soundcards. - - The PCM audio is supported on SoundScape Classic, Elite, PnP - and VIVO cards. The supported OEM cards are SPEA Media FX and - Reveal SC-600. - The MIDI support is very experimental and requires binary - firmware files called "scope.cod" and "sndscape.co?" where the - ? is digit 0, 1, 2, 3 or 4. The firmware files can be found - in DOS or Windows driver packages. One has to put the firmware - files into the /lib/firmware directory. - - To compile this driver as a module, choose M here: the module - will be called snd-sscape. - -config SND_WAVEFRONT - tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" - select FW_LOADER - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for Turtle Beach Maui, Tropez - and Tropez+ soundcards based on the Wavefront chip. - - To compile this driver as a module, choose M here: the module - will be called snd-wavefront. - -config SND_MSND_PINNACLE - tristate "Turtle Beach MultiSound Pinnacle/Fiji driver" - depends on X86 && EXPERIMENTAL - select FW_LOADER - select SND_MPU401_UART - select SND_PCM - help - Say Y to include support for Turtle Beach MultiSound Pinnacle/ - Fiji soundcards. - - To compile this driver as a module, choose M here: the module - will be called snd-msnd-pinnacle. - -config SND_MSND_CLASSIC - tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" - depends on X86 && EXPERIMENTAL - select FW_LOADER - select SND_MPU401_UART - select SND_PCM - help - Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or - Monterey (not for the Pinnacle or Fiji). - - See <file:Documentation/sound/oss/MultiSound> for important information - about this driver. Note that it has been discontinued, but the - Voyetra Turtle Beach knowledge base entry for it is still available - at <http://www.turtlebeach.com/site/kb_ftp/790.asp>. - - To compile this driver as a module, choose M here: the module - will be called snd-msnd-classic. - -endif # SND_ISA - diff --git a/ANDROID_3.4.5/sound/isa/Makefile b/ANDROID_3.4.5/sound/isa/Makefile deleted file mode 100644 index 8d781e41..00000000 --- a/ANDROID_3.4.5/sound/isa/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-adlib-objs := adlib.o -snd-als100-objs := als100.o -snd-azt2320-objs := azt2320.o -snd-cmi8330-objs := cmi8330.o -snd-es18xx-objs := es18xx.o -snd-opl3sa2-objs := opl3sa2.o -snd-sc6000-objs := sc6000.o -snd-sscape-objs := sscape.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_ADLIB) += snd-adlib.o -obj-$(CONFIG_SND_ALS100) += snd-als100.o -obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o -obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o -obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o -obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o -obj-$(CONFIG_SND_SC6000) += snd-sc6000.o -obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o - -obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \ - sb/ wavefront/ wss/ diff --git a/ANDROID_3.4.5/sound/isa/ad1816a/Makefile b/ANDROID_3.4.5/sound/isa/ad1816a/Makefile deleted file mode 100644 index 487ab238..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1816a/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-ad1816a-objs := ad1816a.o ad1816a_lib.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AD1816A) += snd-ad1816a.o diff --git a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c b/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c deleted file mode 100644 index 94b83b6e..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a.c +++ /dev/null @@ -1,294 +0,0 @@ - -/* - card-ad1816a.c - driver for ADI SoundPort AD1816A based soundcards. - Copyright (C) 2000 by Massimo Piccioni <dafastidio@libero.it> - - 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/time.h> -#include <linux/wait.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/ad1816a.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> - -#define PFX "ad1816a: " - -MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>"); -MODULE_DESCRIPTION("AD1816A, AD1815"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Highscreen,Sound-Boostar 16 3D}," - "{Analog Devices,AD1815}," - "{Analog Devices,AD1816A}," - "{TerraTec,Base 64}," - "{TerraTec,AudioSystem EWS64S}," - "{Aztech/Newcom SC-16 3D}," - "{Shark Predator ISA}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int clockfreq[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ad1816a based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ad1816a based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ad1816a based soundcard."); -module_param_array(clockfreq, int, NULL, 0444); -MODULE_PARM_DESC(clockfreq, "Clock frequency for ad1816a driver (default = 0)."); - -struct snd_card_ad1816a { - struct pnp_dev *dev; - struct pnp_dev *devmpu; -}; - -static struct pnp_card_device_id snd_ad1816a_pnpids[] = { - /* Analog Devices AD1815 */ - { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, - /* Analog Device AD1816? */ - { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */ - { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */ - { .id = "AZT1022", .devs = { { .id = "AZT1018" }, { .id = "AZT2002" } } }, - /* Highscreen Sound-Boostar 16 3D - added by Stefan Behnel */ - { .id = "LWC1061", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Highscreen Sound-Boostar 16 3D */ - { .id = "MDK1605", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Shark Predator ISA - added by Ken Arromdee */ - { .id = "SMM7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */ - { .id = "TER1112", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* Analog Devices AD1816A - Terratec AudioSystem EWS64 S */ - { .id = "TER1112", .devs = { { .id = "TER1100" }, { .id = "TER1101" } } }, - /* Analog Devices AD1816A - Terratec Base 64 */ - { .id = "TER1411", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, - /* end */ - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids); - - -#define DRIVER_NAME "snd-card-ad1816a" - - -static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -EBUSY; - - acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL); - if (acard->devmpu == NULL) { - mpu_port[dev] = -1; - snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n"); - } - - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - printk(KERN_ERR PFX "AUDIO PnP configure failure\n"); - return -EBUSY; - } - - port[dev] = pnp_port_start(pdev, 2); - fm_port[dev] = pnp_port_start(pdev, 1); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - - if (acard->devmpu == NULL) - return 0; - - pdev = acard->devmpu; - - err = pnp_activate_dev(pdev); - if (err < 0) { - printk(KERN_ERR PFX "MPU401 PnP configure failure\n"); - mpu_port[dev] = -1; - acard->devmpu = NULL; - } else { - mpu_port[dev] = pnp_port_start(pdev, 0); - mpu_irq[dev] = pnp_irq(pdev, 0); - } - - return 0; -} - -static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - int error; - struct snd_card *card; - struct snd_card_ad1816a *acard; - struct snd_ad1816a *chip; - struct snd_opl3 *opl3; - struct snd_timer *timer; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_ad1816a), &card); - if (error < 0) - return error; - acard = card->private_data; - - if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - - if ((error = snd_ad1816a_create(card, port[dev], - irq[dev], - dma1[dev], - dma2[dev], - &chip)) < 0) { - snd_card_free(card); - return error; - } - if (clockfreq[dev] >= 5000 && clockfreq[dev] <= 100000) - chip->clock_freq = clockfreq[dev]; - - strcpy(card->driver, "AD1816A"); - strcpy(card->shortname, "ADI SoundPort AD1816A"); - sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d", - card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); - - if ((error = snd_ad1816a_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return error; - } - - if ((error = snd_ad1816a_mixer(chip)) < 0) { - snd_card_free(card); - return error; - } - - error = snd_ad1816a_timer(chip, 0, &timer); - if (error < 0) { - snd_card_free(card); - return error; - } - - if (mpu_port[dev] > 0) { - if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port[dev], 0, mpu_irq[dev], - NULL) < 0) - printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]); - } - - if (fm_port[dev] > 0) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx.\n", fm_port[dev], fm_port[dev] + 2); - } else { - error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (error < 0) { - snd_card_free(card); - return error; - } - } - } - - if ((error = snd_card_register(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - return 0; -} - -static unsigned int __devinitdata ad1816a_devices; - -static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - static int dev; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev]) - continue; - res = snd_card_ad1816a_probe(dev, card, id); - if (res < 0) - return res; - dev++; - ad1816a_devices++; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver ad1816a_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "ad1816a", - .id_table = snd_ad1816a_pnpids, - .probe = snd_ad1816a_pnp_detect, - .remove = __devexit_p(snd_ad1816a_pnp_remove), - /* FIXME: suspend/resume */ -}; - -static int __init alsa_card_ad1816a_init(void) -{ - int err; - - err = pnp_register_card_driver(&ad1816a_pnpc_driver); - if (err) - return err; - - if (!ad1816a_devices) { - pnp_unregister_card_driver(&ad1816a_pnpc_driver); -#ifdef MODULE - printk(KERN_ERR "no AD1816A based soundcards found.\n"); -#endif /* MODULE */ - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_ad1816a_exit(void) -{ - pnp_unregister_card_driver(&ad1816a_pnpc_driver); -} - -module_init(alsa_card_ad1816a_init) -module_exit(alsa_card_ad1816a_exit) diff --git a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c b/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c deleted file mode 100644 index 177eed32..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1816a/ad1816a_lib.c +++ /dev/null @@ -1,972 +0,0 @@ -/* - ad1816a.c - lowlevel code for Analog Devices AD1816A chip. - Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it> - - 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/slab.h> -#include <linux/ioport.h> -#include <sound/core.h> -#include <sound/tlv.h> -#include <sound/ad1816a.h> - -#include <asm/io.h> -#include <asm/dma.h> - -static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip) -{ - int timeout; - - for (timeout = 1000; timeout-- > 0; udelay(10)) - if (inb(AD1816A_REG(AD1816A_CHIP_STATUS)) & AD1816A_READY) - return 0; - - snd_printk(KERN_WARNING "chip busy.\n"); - return -EBUSY; -} - -static inline unsigned char snd_ad1816a_in(struct snd_ad1816a *chip, unsigned char reg) -{ - snd_ad1816a_busy_wait(chip); - return inb(AD1816A_REG(reg)); -} - -static inline void snd_ad1816a_out(struct snd_ad1816a *chip, unsigned char reg, - unsigned char value) -{ - snd_ad1816a_busy_wait(chip); - outb(value, AD1816A_REG(reg)); -} - -static inline void snd_ad1816a_out_mask(struct snd_ad1816a *chip, unsigned char reg, - unsigned char mask, unsigned char value) -{ - snd_ad1816a_out(chip, reg, - (value & mask) | (snd_ad1816a_in(chip, reg) & ~mask)); -} - -static unsigned short snd_ad1816a_read(struct snd_ad1816a *chip, unsigned char reg) -{ - snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f); - return snd_ad1816a_in(chip, AD1816A_INDIR_DATA_LOW) | - (snd_ad1816a_in(chip, AD1816A_INDIR_DATA_HIGH) << 8); -} - -static void snd_ad1816a_write(struct snd_ad1816a *chip, unsigned char reg, - unsigned short value) -{ - snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f); - snd_ad1816a_out(chip, AD1816A_INDIR_DATA_LOW, value & 0xff); - snd_ad1816a_out(chip, AD1816A_INDIR_DATA_HIGH, (value >> 8) & 0xff); -} - -static void snd_ad1816a_write_mask(struct snd_ad1816a *chip, unsigned char reg, - unsigned short mask, unsigned short value) -{ - snd_ad1816a_write(chip, reg, - (value & mask) | (snd_ad1816a_read(chip, reg) & ~mask)); -} - - -static unsigned char snd_ad1816a_get_format(struct snd_ad1816a *chip, - unsigned int format, int channels) -{ - unsigned char retval = AD1816A_FMT_LINEAR_8; - - switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: - retval = AD1816A_FMT_ULAW_8; - break; - case SNDRV_PCM_FORMAT_A_LAW: - retval = AD1816A_FMT_ALAW_8; - break; - case SNDRV_PCM_FORMAT_S16_LE: - retval = AD1816A_FMT_LINEAR_16_LIT; - break; - case SNDRV_PCM_FORMAT_S16_BE: - retval = AD1816A_FMT_LINEAR_16_BIG; - } - return (channels > 1) ? (retval | AD1816A_FMT_STEREO) : retval; -} - -static int snd_ad1816a_open(struct snd_ad1816a *chip, unsigned int mode) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - if (chip->mode & mode) { - spin_unlock_irqrestore(&chip->lock, flags); - return -EAGAIN; - } - - switch ((mode &= AD1816A_MODE_OPEN)) { - case AD1816A_MODE_PLAYBACK: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_PLAYBACK_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_PLAYBACK_IRQ_ENABLE, 0xffff); - break; - case AD1816A_MODE_CAPTURE: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_CAPTURE_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_CAPTURE_IRQ_ENABLE, 0xffff); - break; - case AD1816A_MODE_TIMER: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_TIMER_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_IRQ_ENABLE, 0xffff); - } - chip->mode |= mode; - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static void snd_ad1816a_close(struct snd_ad1816a *chip, unsigned int mode) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - switch ((mode &= AD1816A_MODE_OPEN)) { - case AD1816A_MODE_PLAYBACK: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_PLAYBACK_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_PLAYBACK_IRQ_ENABLE, 0x0000); - break; - case AD1816A_MODE_CAPTURE: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_CAPTURE_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_CAPTURE_IRQ_ENABLE, 0x0000); - break; - case AD1816A_MODE_TIMER: - snd_ad1816a_out_mask(chip, AD1816A_INTERRUPT_STATUS, - AD1816A_TIMER_IRQ_PENDING, 0x00); - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_IRQ_ENABLE, 0x0000); - } - if (!((chip->mode &= ~mode) & AD1816A_MODE_OPEN)) - chip->mode = 0; - - spin_unlock_irqrestore(&chip->lock, flags); -} - - -static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what, - int channel, int cmd, int iscapture) -{ - int error = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_STOP: - spin_lock(&chip->lock); - cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00; - /* if (what & AD1816A_PLAYBACK_ENABLE) */ - /* That is not valid, because playback and capture enable - * are the same bit pattern, just to different addresses - */ - if (! iscapture) - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_PLAYBACK_ENABLE, cmd); - else - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_CAPTURE_ENABLE, cmd); - spin_unlock(&chip->lock); - break; - default: - snd_printk(KERN_WARNING "invalid trigger mode 0x%x.\n", what); - error = -EINVAL; - } - - return error; -} - -static int snd_ad1816a_playback_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - return snd_ad1816a_trigger(chip, AD1816A_PLAYBACK_ENABLE, - SNDRV_PCM_STREAM_PLAYBACK, cmd, 0); -} - -static int snd_ad1816a_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - return snd_ad1816a_trigger(chip, AD1816A_CAPTURE_ENABLE, - SNDRV_PCM_STREAM_CAPTURE, cmd, 1); -} - -static int snd_ad1816a_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_ad1816a_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_ad1816a_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - unsigned long flags; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size, rate; - - spin_lock_irqsave(&chip->lock, flags); - - chip->p_dma_size = size = snd_pcm_lib_buffer_bytes(substream); - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00); - - snd_dma_program(chip->dma1, runtime->dma_addr, size, - DMA_MODE_WRITE | DMA_AUTOINIT); - - rate = runtime->rate; - if (chip->clock_freq) - rate = (rate * 33000) / chip->clock_freq; - snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, rate); - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_FMT_ALL | AD1816A_FMT_STEREO, - snd_ad1816a_get_format(chip, runtime->format, - runtime->channels)); - - snd_ad1816a_write(chip, AD1816A_PLAYBACK_BASE_COUNT, - snd_pcm_lib_period_bytes(substream) / 4 - 1); - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static int snd_ad1816a_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - unsigned long flags; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size, rate; - - spin_lock_irqsave(&chip->lock, flags); - - chip->c_dma_size = size = snd_pcm_lib_buffer_bytes(substream); - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00); - - snd_dma_program(chip->dma2, runtime->dma_addr, size, - DMA_MODE_READ | DMA_AUTOINIT); - - rate = runtime->rate; - if (chip->clock_freq) - rate = (rate * 33000) / chip->clock_freq; - snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, rate); - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_FMT_ALL | AD1816A_FMT_STEREO, - snd_ad1816a_get_format(chip, runtime->format, - runtime->channels)); - - snd_ad1816a_write(chip, AD1816A_CAPTURE_BASE_COUNT, - snd_pcm_lib_period_bytes(substream) / 4 - 1); - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - - -static snd_pcm_uframes_t snd_ad1816a_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - size_t ptr; - if (!(chip->mode & AD1816A_MODE_PLAYBACK)) - return 0; - ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_ad1816a_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - size_t ptr; - if (!(chip->mode & AD1816A_MODE_CAPTURE)) - return 0; - ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - - -static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id) -{ - struct snd_ad1816a *chip = dev_id; - unsigned char status; - - spin_lock(&chip->lock); - status = snd_ad1816a_in(chip, AD1816A_INTERRUPT_STATUS); - spin_unlock(&chip->lock); - - if ((status & AD1816A_PLAYBACK_IRQ_PENDING) && chip->playback_substream) - snd_pcm_period_elapsed(chip->playback_substream); - - if ((status & AD1816A_CAPTURE_IRQ_PENDING) && chip->capture_substream) - snd_pcm_period_elapsed(chip->capture_substream); - - if ((status & AD1816A_TIMER_IRQ_PENDING) && chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - - spin_lock(&chip->lock); - snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); - spin_unlock(&chip->lock); - return IRQ_HANDLED; -} - - -static struct snd_pcm_hardware snd_ad1816a_playback = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 55200, - .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, -}; - -static struct snd_pcm_hardware snd_ad1816a_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 55200, - .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, -}; - -static int snd_ad1816a_timer_close(struct snd_timer *timer) -{ - struct snd_ad1816a *chip = snd_timer_chip(timer); - snd_ad1816a_close(chip, AD1816A_MODE_TIMER); - return 0; -} - -static int snd_ad1816a_timer_open(struct snd_timer *timer) -{ - struct snd_ad1816a *chip = snd_timer_chip(timer); - snd_ad1816a_open(chip, AD1816A_MODE_TIMER); - return 0; -} - -static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer) -{ - if (snd_BUG_ON(!timer)) - return 0; - - return 10000; -} - -static int snd_ad1816a_timer_start(struct snd_timer *timer) -{ - unsigned short bits; - unsigned long flags; - struct snd_ad1816a *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); - bits = snd_ad1816a_read(chip, AD1816A_INTERRUPT_ENABLE); - - if (!(bits & AD1816A_TIMER_ENABLE)) { - snd_ad1816a_write(chip, AD1816A_TIMER_BASE_COUNT, - timer->sticks & 0xffff); - - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_ENABLE, 0xffff); - } - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static int snd_ad1816a_timer_stop(struct snd_timer *timer) -{ - unsigned long flags; - struct snd_ad1816a *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->lock, flags); - - snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, - AD1816A_TIMER_ENABLE, 0x0000); - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static struct snd_timer_hardware snd_ad1816a_timer_table = { - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 10000, - .ticks = 65535, - .open = snd_ad1816a_timer_open, - .close = snd_ad1816a_timer_close, - .c_resolution = snd_ad1816a_timer_resolution, - .start = snd_ad1816a_timer_start, - .stop = snd_ad1816a_timer_stop, -}; - -static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int error; - - if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) - return error; - runtime->hw = snd_ad1816a_playback; - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); - chip->playback_substream = substream; - return 0; -} - -static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int error; - - if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) - return error; - runtime->hw = snd_ad1816a_capture; - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); - chip->capture_substream = substream; - return 0; -} - -static int snd_ad1816a_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - snd_ad1816a_close(chip, AD1816A_MODE_PLAYBACK); - return 0; -} - -static int snd_ad1816a_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_ad1816a *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - snd_ad1816a_close(chip, AD1816A_MODE_CAPTURE); - return 0; -} - - -static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - snd_ad1816a_out(chip, AD1816A_INTERRUPT_STATUS, 0x00); - snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG, - AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00); - snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG, - AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00); - snd_ad1816a_write(chip, AD1816A_INTERRUPT_ENABLE, 0x0000); - snd_ad1816a_write_mask(chip, AD1816A_CHIP_CONFIG, - AD1816A_CAPTURE_NOT_EQUAL | AD1816A_WSS_ENABLE, 0xffff); - snd_ad1816a_write(chip, AD1816A_DSP_CONFIG, 0x0000); - snd_ad1816a_write(chip, AD1816A_POWERDOWN_CTRL, 0x0000); - - spin_unlock_irqrestore(&chip->lock, flags); -} - -static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - - switch (chip->version = snd_ad1816a_read(chip, AD1816A_VERSION_ID)) { - case 0: - chip->hardware = AD1816A_HW_AD1815; - break; - case 1: - chip->hardware = AD1816A_HW_AD18MAX10; - break; - case 3: - chip->hardware = AD1816A_HW_AD1816A; - break; - default: - chip->hardware = AD1816A_HW_AUTO; - } - - spin_unlock_irqrestore(&chip->lock, flags); - return 0; -} - -static int snd_ad1816a_free(struct snd_ad1816a *chip) -{ - release_and_free_resource(chip->res_port); - if (chip->irq >= 0) - free_irq(chip->irq, (void *) chip); - if (chip->dma1 >= 0) { - snd_dma_disable(chip->dma1); - free_dma(chip->dma1); - } - if (chip->dma2 >= 0) { - snd_dma_disable(chip->dma2); - free_dma(chip->dma2); - } - kfree(chip); - return 0; -} - -static int snd_ad1816a_dev_free(struct snd_device *device) -{ - struct snd_ad1816a *chip = device->device_data; - return snd_ad1816a_free(chip); -} - -static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip) -{ - switch (chip->hardware) { - case AD1816A_HW_AD1816A: return "AD1816A"; - case AD1816A_HW_AD1815: return "AD1815"; - case AD1816A_HW_AD18MAX10: return "AD18max10"; - default: - snd_printk(KERN_WARNING "Unknown chip version %d:%d.\n", - chip->version, chip->hardware); - return "AD1816A - unknown"; - } -} - -int __devinit snd_ad1816a_create(struct snd_card *card, - unsigned long port, int irq, int dma1, int dma2, - struct snd_ad1816a **rchip) -{ - static struct snd_device_ops ops = { - .dev_free = snd_ad1816a_dev_free, - }; - int error; - struct snd_ad1816a *chip; - - *rchip = NULL; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - - if ((chip->res_port = request_region(port, 16, "AD1816A")) == NULL) { - snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port); - snd_ad1816a_free(chip); - return -EBUSY; - } - if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) { - snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq); - snd_ad1816a_free(chip); - return -EBUSY; - } - chip->irq = irq; - if (request_dma(dma1, "AD1816A - 1")) { - snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1); - snd_ad1816a_free(chip); - return -EBUSY; - } - chip->dma1 = dma1; - if (request_dma(dma2, "AD1816A - 2")) { - snd_printk(KERN_ERR "ad1816a: can't grab DMA2 %d\n", dma2); - snd_ad1816a_free(chip); - return -EBUSY; - } - chip->dma2 = dma2; - - chip->card = card; - chip->port = port; - spin_lock_init(&chip->lock); - - if ((error = snd_ad1816a_probe(chip))) { - snd_ad1816a_free(chip); - return error; - } - - snd_ad1816a_init(chip); - - /* Register device */ - if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_ad1816a_free(chip); - return error; - } - - *rchip = chip; - return 0; -} - -static struct snd_pcm_ops snd_ad1816a_playback_ops = { - .open = snd_ad1816a_playback_open, - .close = snd_ad1816a_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ad1816a_hw_params, - .hw_free = snd_ad1816a_hw_free, - .prepare = snd_ad1816a_playback_prepare, - .trigger = snd_ad1816a_playback_trigger, - .pointer = snd_ad1816a_playback_pointer, -}; - -static struct snd_pcm_ops snd_ad1816a_capture_ops = { - .open = snd_ad1816a_capture_open, - .close = snd_ad1816a_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_ad1816a_hw_params, - .hw_free = snd_ad1816a_hw_free, - .prepare = snd_ad1816a_capture_prepare, - .trigger = snd_ad1816a_capture_trigger, - .pointer = snd_ad1816a_capture_pointer, -}; - -int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm) -{ - int error; - struct snd_pcm *pcm; - - if ((error = snd_pcm_new(chip->card, "AD1816A", device, 1, 1, &pcm))) - return error; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1816a_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1816a_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = (chip->dma1 == chip->dma2 ) ? SNDRV_PCM_INFO_JOINT_DUPLEX : 0; - - strcpy(pcm->name, snd_ad1816a_chip_id(chip)); - snd_ad1816a_init(chip); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); - - chip->pcm = pcm; - if (rpcm) - *rpcm = pcm; - return 0; -} - -int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer) -{ - struct snd_timer *timer; - struct snd_timer_id tid; - int error; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; - tid.device = device; - tid.subdevice = 0; - if ((error = snd_timer_new(chip->card, "AD1816A", &tid, &timer)) < 0) - return error; - strcpy(timer->name, snd_ad1816a_chip_id(chip)); - timer->private_data = chip; - chip->timer = timer; - timer->hw = snd_ad1816a_timer_table; - if (rtimer) - *rtimer = timer; - return 0; -} - -/* - * - */ - -static int snd_ad1816a_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[8] = { - "Line", "Mix", "CD", "Synth", "Video", - "Mic", "Phone", - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - uinfo->value.enumerated.items = 7; - if (uinfo->value.enumerated.item > 6) - uinfo->value.enumerated.item = 6; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_ad1816a_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&chip->lock, flags); - val = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL); - spin_unlock_irqrestore(&chip->lock, flags); - ucontrol->value.enumerated.item[0] = (val >> 12) & 7; - ucontrol->value.enumerated.item[1] = (val >> 4) & 7; - return 0; -} - -static int snd_ad1816a_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned short val; - int change; - - if (ucontrol->value.enumerated.item[0] > 6 || - ucontrol->value.enumerated.item[1] > 6) - return -EINVAL; - val = (ucontrol->value.enumerated.item[0] << 12) | - (ucontrol->value.enumerated.item[1] << 4); - spin_lock_irqsave(&chip->lock, flags); - change = snd_ad1816a_read(chip, AD1816A_ADC_SOURCE_SEL) != val; - snd_ad1816a_write(chip, AD1816A_ADC_SOURCE_SEL, val); - spin_unlock_irqrestore(&chip->lock, flags); - return change; -} - -#define AD1816A_SINGLE_TLV(xname, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_ad1816a_info_single, \ - .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } -#define AD1816A_SINGLE(xname, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_single, \ - .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_ad1816a_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ad1816a_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->lock, flags); - ucontrol->value.integer.value[0] = (snd_ad1816a_read(chip, reg) >> shift) & mask; - spin_unlock_irqrestore(&chip->lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_ad1816a_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short old_val, val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->lock, flags); - old_val = snd_ad1816a_read(chip, reg); - val = (old_val & ~(mask << shift)) | val; - change = val != old_val; - snd_ad1816a_write(chip, reg, val); - spin_unlock_irqrestore(&chip->lock, flags); - return change; -} - -#define AD1816A_DOUBLE_TLV(xname, reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_ad1816a_info_double, \ - .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -#define AD1816A_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_double, \ - .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) } - -static int snd_ad1816a_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_ad1816a_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned short val; - - spin_lock_irqsave(&chip->lock, flags); - val = snd_ad1816a_read(chip, reg); - ucontrol->value.integer.value[0] = (val >> shift_left) & mask; - ucontrol->value.integer.value[1] = (val >> shift_right) & mask; - spin_unlock_irqrestore(&chip->lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift_left = (kcontrol->private_value >> 8) & 0x0f; - int shift_right = (kcontrol->private_value >> 12) & 0x0f; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short old_val, val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->lock, flags); - old_val = snd_ad1816a_read(chip, reg); - val1 = (old_val & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != old_val; - snd_ad1816a_write(chip, reg, val1); - spin_unlock_irqrestore(&chip->lock, flags); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - -static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = { -AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1, - db_scale_5bit), -AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1, - db_scale_6bit), -AD1816A_DOUBLE("Line Playback Switch", AD1816A_LINE_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_DOUBLE("CD Playback Switch", AD1816A_CD_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_DOUBLE("Synth Playback Switch", AD1816A_SYNTH_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_DOUBLE("FM Playback Switch", AD1816A_FM_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1, - db_scale_6bit), -AD1816A_SINGLE("Mic Playback Switch", AD1816A_MIC_GAIN_ATT, 15, 1, 1), -AD1816A_SINGLE_TLV("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1, - db_scale_5bit_12db_max), -AD1816A_SINGLE("Mic Boost", AD1816A_MIC_GAIN_ATT, 14, 1, 0), -AD1816A_DOUBLE("Video Playback Switch", AD1816A_VID_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), -AD1816A_SINGLE("Phone Capture Switch", AD1816A_PHONE_IN_GAIN_ATT, 15, 1, 1), -AD1816A_SINGLE_TLV("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1, - db_scale_4bit), -AD1816A_SINGLE("Phone Playback Switch", AD1816A_PHONE_OUT_ATT, 7, 1, 1), -AD1816A_SINGLE_TLV("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1, - db_scale_5bit), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_ad1816a_info_mux, - .get = snd_ad1816a_get_mux, - .put = snd_ad1816a_put_mux, -}, -AD1816A_DOUBLE("Capture Switch", AD1816A_ADC_PGA, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0, - db_scale_rec_gain), -AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1), -AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0), -}; - -int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip) -{ - struct snd_card *card; - unsigned int idx; - int err; - - if (snd_BUG_ON(!chip || !chip->card)) - return -EINVAL; - - card = chip->card; - - strcpy(card->mixername, snd_ad1816a_chip_id(chip)); - - for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0) - return err; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/ad1848/Makefile b/ANDROID_3.4.5/sound/isa/ad1848/Makefile deleted file mode 100644 index 3d6dea3f..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1848/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-ad1848-objs := ad1848.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_AD1848) += snd-ad1848.o - diff --git a/ANDROID_3.4.5/sound/isa/ad1848/ad1848.c b/ANDROID_3.4.5/sound/isa/ad1848/ad1848.c deleted file mode 100644 index 2af77fae..00000000 --- a/ANDROID_3.4.5/sound/isa/ad1848/ad1848.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Generic driver for AD1848/AD1847/CS4248 chips (0.1 Alpha) - * Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>, - * Jaroslav Kysela <perex@perex.cz> - * Based on card-4232.c by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/initval.h> - -#define CRD_NAME "Generic AD1848/AD1847/CS4248" -#define DEV_NAME "ad1848" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848}," - "{Analog Devices,AD1847}," - "{Crystal Semiconductors,CS4248}}"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static bool thinkpad[SNDRV_CARDS]; /* Thinkpad special case */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); -module_param_array(thinkpad, bool, NULL, 0444); -MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series."); - -static int __devinit snd_ad1848_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - if (port[n] == SNDRV_AUTO_PORT) { - dev_err(dev, "please specify port\n"); - return 0; - } - if (irq[n] == SNDRV_AUTO_IRQ) { - dev_err(dev, "please specify irq\n"); - return 0; - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dev_err(dev, "please specify dma1\n"); - return 0; - } - return 1; -} - -static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_wss *chip; - struct snd_pcm *pcm; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) - return error; - - error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1, - thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, - 0, &chip); - if (error < 0) - goto out; - - card->private_data = chip; - - error = snd_wss_pcm(chip, 0, &pcm); - if (error < 0) - goto out; - - error = snd_wss_mixer(chip); - if (error < 0) - goto out; - - strcpy(card->driver, "AD1848"); - strcpy(card->shortname, pcm->name); - - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - pcm->name, chip->port, irq[n], dma1[n]); - if (thinkpad[n]) - strcat(card->longname, " [Thinkpad]"); - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->suspend(chip); - return 0; -} - -static int snd_ad1848_resume(struct device *dev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - chip->resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct isa_driver snd_ad1848_driver = { - .match = snd_ad1848_match, - .probe = snd_ad1848_probe, - .remove = __devexit_p(snd_ad1848_remove), -#ifdef CONFIG_PM - .suspend = snd_ad1848_suspend, - .resume = snd_ad1848_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_ad1848_init(void) -{ - return isa_register_driver(&snd_ad1848_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_ad1848_exit(void) -{ - isa_unregister_driver(&snd_ad1848_driver); -} - -module_init(alsa_card_ad1848_init); -module_exit(alsa_card_ad1848_exit); diff --git a/ANDROID_3.4.5/sound/isa/adlib.c b/ANDROID_3.4.5/sound/isa/adlib.c deleted file mode 100644 index 4d50c69f..00000000 --- a/ANDROID_3.4.5/sound/isa/adlib.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * AdLib FM card driver. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/isa.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/opl3.h> - -#define CRD_NAME "AdLib FM" -#define DEV_NAME "adlib" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Rene Herman"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); - -static int __devinit snd_adlib_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - if (port[n] == SNDRV_AUTO_PORT) { - dev_err(dev, "please specify port\n"); - return 0; - } - return 1; -} - -static void snd_adlib_free(struct snd_card *card) -{ - release_and_free_resource(card->private_data); -} - -static int __devinit snd_adlib_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_opl3 *opl3; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) { - dev_err(dev, "could not create card\n"); - return error; - } - - card->private_data = request_region(port[n], 4, CRD_NAME); - if (!card->private_data) { - dev_err(dev, "could not grab ports\n"); - error = -EBUSY; - goto out; - } - card->private_free = snd_adlib_free; - - strcpy(card->driver, DEV_NAME); - strcpy(card->shortname, CRD_NAME); - sprintf(card->longname, CRD_NAME " at %#lx", port[n]); - - error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3); - if (error < 0) { - dev_err(dev, "could not create OPL\n"); - goto out; - } - - error = snd_opl3_hwdep_new(opl3, 0, 0, NULL); - if (error < 0) { - dev_err(dev, "could not create FM\n"); - goto out; - } - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) { - dev_err(dev, "could not register card\n"); - goto out; - } - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_adlib_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_adlib_driver = { - .match = snd_adlib_match, - .probe = snd_adlib_probe, - .remove = __devexit_p(snd_adlib_remove), - - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_adlib_init(void) -{ - return isa_register_driver(&snd_adlib_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_adlib_exit(void) -{ - isa_unregister_driver(&snd_adlib_driver); -} - -module_init(alsa_card_adlib_init); -module_exit(alsa_card_adlib_exit); diff --git a/ANDROID_3.4.5/sound/isa/als100.c b/ANDROID_3.4.5/sound/isa/als100.c deleted file mode 100644 index d1f4351f..00000000 --- a/ANDROID_3.4.5/sound/isa/als100.c +++ /dev/null @@ -1,378 +0,0 @@ - -/* - card-als100.c - driver for Avance Logic ALS100 based soundcards. - Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it> - Copyright (C) 1999-2002 by Massimo Piccioni <dafastidio@libero.it> - - Thanks to Pierfrancesco 'qM2' Passerini. - - Generalised for soundcards based on DT-0196 and ALS-007 chips - by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>: June 2002. - - 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/wait.h> -#include <linux/time.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#include <sound/sb.h> - -#define PFX "als100: " - -MODULE_DESCRIPTION("Avance Logic ALS007/ALS1X0"); -MODULE_SUPPORTED_DEVICE("{{Diamond Technologies DT-019X}," - "{Avance Logic ALS-007}}" - "{{Avance Logic,ALS100 - PRO16PNP}," - "{Avance Logic,ALS110}," - "{Avance Logic,ALS120}," - "{Avance Logic,ALS200}," - "{3D Melody,MF1000}," - "{Digimate,3D Sound}," - "{Avance Logic,ALS120}," - "{RTL,RTL3000}}"); - -MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>"); -MODULE_LICENSE("GPL"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* PnP setup */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Avance Logic based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Avance Logic based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Avance Logic based soundcard."); - -MODULE_ALIAS("snd-dt019x"); - -struct snd_card_als100 { - struct pnp_dev *dev; - struct pnp_dev *devmpu; - struct pnp_dev *devopl; - struct snd_sb *chip; -}; - -static struct pnp_card_device_id snd_als100_pnpids[] = { - /* DT197A30 */ - { .id = "RWB1688", - .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } }, - .driver_data = SB_HW_DT019X }, - /* DT0196 / ALS-007 */ - { .id = "ALS0007", - .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } }, - .driver_data = SB_HW_DT019X }, - /* ALS100 - PRO16PNP */ - { .id = "ALS0001", - .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS110 - MF1000 - Digimate 3D Sound */ - { .id = "ALS0110", - .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS120 */ - { .id = "ALS0120", - .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS200 */ - { .id = "ALS0200", - .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" } }, - .driver_data = SB_HW_ALS100 }, - /* ALS200 OEM */ - { .id = "ALS0200", - .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0020" } }, - .driver_data = SB_HW_ALS100 }, - /* RTL3000 */ - { .id = "RTL3000", - .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } }, - .driver_data = SB_HW_ALS100 }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids); - -static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -ENODEV; - - acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev); - acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev); - - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); - return err; - } - port[dev] = pnp_port_start(pdev, 0); - if (id->driver_data == SB_HW_DT019X) - dma8[dev] = pnp_dma(pdev, 0); - else { - dma8[dev] = pnp_dma(pdev, 1); - dma16[dev] = pnp_dma(pdev, 0); - } - irq[dev] = pnp_irq(pdev, 0); - - pdev = acard->devmpu; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) - goto __mpu_error; - mpu_port[dev] = pnp_port_start(pdev, 0); - mpu_irq[dev] = pnp_irq(pdev, 0); - } else { - __mpu_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n"); - } - acard->devmpu = NULL; - mpu_port[dev] = -1; - } - - pdev = acard->devopl; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) - goto __fm_error; - fm_port[dev] = pnp_port_start(pdev, 0); - } else { - __fm_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n"); - } - acard->devopl = NULL; - fm_port[dev] = -1; - } - - return 0; -} - -static int __devinit snd_card_als100_probe(int dev, - struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - int error; - struct snd_sb *chip; - struct snd_card *card; - struct snd_card_als100 *acard; - struct snd_opl3 *opl3; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_als100), &card); - if (error < 0) - return error; - acard = card->private_data; - - if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - - if (pid->driver_data == SB_HW_DT019X) - dma16[dev] = -1; - - error = snd_sbdsp_create(card, port[dev], irq[dev], - snd_sb16dsp_interrupt, - dma8[dev], dma16[dev], - pid->driver_data, - &chip); - if (error < 0) { - snd_card_free(card); - return error; - } - acard->chip = chip; - - if (pid->driver_data == SB_HW_DT019X) { - strcpy(card->driver, "DT-019X"); - strcpy(card->shortname, "Diamond Tech. DT-019X"); - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, chip->name, chip->port, - irq[dev], dma8[dev]); - } else { - strcpy(card->driver, "ALS100"); - strcpy(card->shortname, "Avance Logic ALS100"); - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, chip->name, chip->port, - irq[dev], dma8[dev], dma16[dev]); - } - - if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) { - snd_card_free(card); - return error; - } - - if ((error = snd_sbmixer_new(chip)) < 0) { - snd_card_free(card); - return error; - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - int mpu_type = MPU401_HW_ALS100; - - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - - if (pid->driver_data == SB_HW_DT019X) - mpu_type = MPU401_HW_MPU401; - - if (snd_mpu401_uart_new(card, 0, - mpu_type, - mpu_port[dev], 0, - mpu_irq[dev], - NULL) < 0) - snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); - } - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); - } else { - if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) { - snd_card_free(card); - return error; - } - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return error; - } - } - } - - if ((error = snd_card_register(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - return 0; -} - -static unsigned int __devinitdata als100_devices; - -static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - static int dev; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev]) - continue; - res = snd_card_als100_probe(dev, card, id); - if (res < 0) - return res; - dev++; - als100_devices++; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_als100 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_als100_pnp_resume(struct pnp_card_link *pcard) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_als100 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pnp_card_driver als100_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "als100", - .id_table = snd_als100_pnpids, - .probe = snd_als100_pnp_detect, - .remove = __devexit_p(snd_als100_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_als100_pnp_suspend, - .resume = snd_als100_pnp_resume, -#endif -}; - -static int __init alsa_card_als100_init(void) -{ - int err; - - err = pnp_register_card_driver(&als100_pnpc_driver); - if (err) - return err; - - if (!als100_devices) { - pnp_unregister_card_driver(&als100_pnpc_driver); -#ifdef MODULE - snd_printk(KERN_ERR "no Avance Logic based soundcards found\n"); -#endif - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_als100_exit(void) -{ - pnp_unregister_card_driver(&als100_pnpc_driver); -} - -module_init(alsa_card_als100_init) -module_exit(alsa_card_als100_exit) diff --git a/ANDROID_3.4.5/sound/isa/azt2320.c b/ANDROID_3.4.5/sound/isa/azt2320.c deleted file mode 100644 index 6a2c78ef..00000000 --- a/ANDROID_3.4.5/sound/isa/azt2320.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - card-azt2320.c - driver for Aztech Systems AZT2320 based soundcards. - Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it> - - 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 -*/ - -/* - This driver should provide support for most Aztech AZT2320 based cards. - Several AZT2316 chips are also supported/tested, but autoprobe doesn't - work: all module option have to be set. - - No docs available for us at Aztech headquarters !!! Unbelievable ... - No other help obtained. - - Thanks to Rainer Wiesner <rainer.wiesner@01019freenet.de> for the WSS - activation method (full-duplex audio!). -*/ - -#include <asm/io.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> - -#define PFX "azt2320: " - -MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>"); -MODULE_DESCRIPTION("Aztech Systems AZT2320"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V}," - "{Aztech Systems,AZT2320}," - "{Aztech Systems,AZT3300}," - "{Aztech Systems,AZT2320}," - "{Aztech Systems,AZT3000}}"); - -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_ISAPNP; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* Pnp setup */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* PnP setup */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard."); - -struct snd_card_azt2320 { - int dev_no; - struct pnp_dev *dev; - struct pnp_dev *devmpu; - struct snd_wss *chip; -}; - -static struct pnp_card_device_id snd_azt2320_pnpids[] = { - /* PRO16V */ - { .id = "AZT1008", .devs = { { "AZT1008" }, { "AZT2001" }, } }, - /* Aztech Sound Galaxy 16 */ - { .id = "AZT2320", .devs = { { "AZT0001" }, { "AZT0002" }, } }, - /* Packard Bell Sound III 336 AM/SP */ - { .id = "AZT3000", .devs = { { "AZT1003" }, { "AZT2001" }, } }, - /* AT3300 */ - { .id = "AZT3002", .devs = { { "AZT1004" }, { "AZT2001" }, } }, - /* --- */ - { .id = "AZT3005", .devs = { { "AZT1003" }, { "AZT2001" }, } }, - /* --- */ - { .id = "AZT3011", .devs = { { "AZT1003" }, { "AZT2001" }, } }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids); - -#define DRIVER_NAME "snd-card-azt2320" - -static int __devinit snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -ENODEV; - - acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL); - - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); - return err; - } - port[dev] = pnp_port_start(pdev, 0); - fm_port[dev] = pnp_port_start(pdev, 1); - wss_port[dev] = pnp_port_start(pdev, 2); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - - pdev = acard->devmpu; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) - goto __mpu_error; - mpu_port[dev] = pnp_port_start(pdev, 0); - mpu_irq[dev] = pnp_irq(pdev, 0); - } else { - __mpu_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n"); - } - acard->devmpu = NULL; - mpu_port[dev] = -1; - } - - return 0; -} - -/* same of snd_sbdsp_command by Jaroslav Kysela */ -static int __devinit snd_card_azt2320_command(unsigned long port, unsigned char val) -{ - int i; - unsigned long limit; - - limit = jiffies + HZ / 10; - for (i = 50000; i && time_after(limit, jiffies); i--) - if (!(inb(port + 0x0c) & 0x80)) { - outb(val, port + 0x0c); - return 0; - } - return -EBUSY; -} - -static int __devinit snd_card_azt2320_enable_wss(unsigned long port) -{ - int error; - - if ((error = snd_card_azt2320_command(port, 0x09))) - return error; - if ((error = snd_card_azt2320_command(port, 0x00))) - return error; - - mdelay(5); - return 0; -} - -static int __devinit snd_card_azt2320_probe(int dev, - struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - int error; - struct snd_card *card; - struct snd_card_azt2320 *acard; - struct snd_wss *chip; - struct snd_opl3 *opl3; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_azt2320), &card); - if (error < 0) - return error; - acard = card->private_data; - - if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - - if ((error = snd_card_azt2320_enable_wss(port[dev]))) { - snd_card_free(card); - return error; - } - - error = snd_wss_create(card, wss_port[dev], -1, - irq[dev], - dma1[dev], dma2[dev], - WSS_HW_DETECT, 0, &chip); - if (error < 0) { - snd_card_free(card); - return error; - } - - strcpy(card->driver, "AZT2320"); - strcpy(card->shortname, "Aztech AZT2320"); - sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i", - card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); - - error = snd_wss_pcm(chip, 0, NULL); - if (error < 0) { - snd_card_free(card); - return error; - } - error = snd_wss_mixer(chip); - if (error < 0) { - snd_card_free(card); - return error; - } - error = snd_wss_timer(chip, 0, NULL); - if (error < 0) { - snd_card_free(card); - return error; - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320, - mpu_port[dev], 0, - mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); - } - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); - } else { - if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) { - snd_card_free(card); - return error; - } - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - snd_card_free(card); - return error; - } - } - } - - if ((error = snd_card_register(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - return 0; -} - -static unsigned int __devinitdata azt2320_devices; - -static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - static int dev; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev]) - continue; - res = snd_card_azt2320_probe(dev, card, id); - if (res < 0) - return res; - dev++; - azt2320_devices++; - return 0; - } - return -ENODEV; -} - -static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_azt2320 *acard = card->private_data; - struct snd_wss *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->suspend(chip); - return 0; -} - -static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_card_azt2320 *acard = card->private_data; - struct snd_wss *chip = acard->chip; - - chip->resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pnp_card_driver azt2320_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "azt2320", - .id_table = snd_azt2320_pnpids, - .probe = snd_azt2320_pnp_detect, - .remove = __devexit_p(snd_azt2320_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_azt2320_pnp_suspend, - .resume = snd_azt2320_pnp_resume, -#endif -}; - -static int __init alsa_card_azt2320_init(void) -{ - int err; - - err = pnp_register_card_driver(&azt2320_pnpc_driver); - if (err) - return err; - - if (!azt2320_devices) { - pnp_unregister_card_driver(&azt2320_pnpc_driver); -#ifdef MODULE - snd_printk(KERN_ERR "no AZT2320 based soundcards found\n"); -#endif - return -ENODEV; - } - return 0; -} - -static void __exit alsa_card_azt2320_exit(void) -{ - pnp_unregister_card_driver(&azt2320_pnpc_driver); -} - -module_init(alsa_card_azt2320_init) -module_exit(alsa_card_azt2320_exit) diff --git a/ANDROID_3.4.5/sound/isa/cmi8330.c b/ANDROID_3.4.5/sound/isa/cmi8330.c deleted file mode 100644 index 7bd5e337..00000000 --- a/ANDROID_3.4.5/sound/isa/cmi8330.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Driver for C-Media's CMI8330 and CMI8329 soundcards. - * Copyright (c) by George Talusan <gstalusan@uwaterloo.ca> - * http://www.undergrad.math.uwaterloo.ca/~gstalusa - * - * 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 - * - */ - -/* - * NOTES - * - * The extended registers contain mixer settings which are largely - * untapped for the time being. - * - * MPU401 and SPDIF are not supported yet. I don't have the hardware - * to aid in coding and testing, so I won't bother. - * - * To quickly load the module, - * - * modprobe -a snd-cmi8330 sbport=0x220 sbirq=5 sbdma8=1 - * sbdma16=5 wssport=0x530 wssirq=11 wssdma=0 fmport=0x388 - * - * This card has two mixers and two PCM devices. I've cheesed it such - * that recording and playback can be done through the same device. - * The driver "magically" routes the capturing to the AD1848 codec, - * and playback to the SB16 codec. This allows for full-duplex mode - * to some extent. - * The utilities in alsa-utils are aware of both devices, so passing - * the appropriate parameters to amixer and alsactl will give you - * full control over both mixers. - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/isa.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/opl3.h> -#include <sound/mpu401.h> -#include <sound/sb.h> -#include <sound/initval.h> - -/* - */ -/* #define ENABLE_SB_MIXER */ -#define PLAYBACK_ON_SB - -/* - */ -MODULE_AUTHOR("George Talusan <gstalusan@uwaterloo.ca>"); -MODULE_DESCRIPTION("C-Media CMI8330/CMI8329"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int sbirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int sbdma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int sbdma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int wssirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int wssdma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static long fmport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for CMI8330/CMI8329 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for CMI8330/CMI8329 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable CMI8330/CMI8329 soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif - -module_param_array(sbport, long, NULL, 0444); -MODULE_PARM_DESC(sbport, "Port # for CMI8330/CMI8329 SB driver."); -module_param_array(sbirq, int, NULL, 0444); -MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330/CMI8329 SB driver."); -module_param_array(sbdma8, int, NULL, 0444); -MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330/CMI8329 SB driver."); -module_param_array(sbdma16, int, NULL, 0444); -MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330/CMI8329 SB driver."); - -module_param_array(wssport, long, NULL, 0444); -MODULE_PARM_DESC(wssport, "Port # for CMI8330/CMI8329 WSS driver."); -module_param_array(wssirq, int, NULL, 0444); -MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330/CMI8329 WSS driver."); -module_param_array(wssdma, int, NULL, 0444); -MODULE_PARM_DESC(wssdma, "DMA for CMI8330/CMI8329 WSS driver."); - -module_param_array(fmport, long, NULL, 0444); -MODULE_PARM_DESC(fmport, "FM port # for CMI8330/CMI8329 driver."); -module_param_array(mpuport, long, NULL, 0444); -MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver."); -module_param_array(mpuirq, int, NULL, 0444); -MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port."); -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -#endif - -#define CMI8330_RMUX3D 16 -#define CMI8330_MUTEMUX 17 -#define CMI8330_OUTPUTVOL 18 -#define CMI8330_MASTVOL 19 -#define CMI8330_LINVOL 20 -#define CMI8330_CDINVOL 21 -#define CMI8330_WAVVOL 22 -#define CMI8330_RECMUX 23 -#define CMI8330_WAVGAIN 24 -#define CMI8330_LINGAIN 25 -#define CMI8330_CDINGAIN 26 - -static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] = -{ - 0x40, /* 16 - recording mux (SB-mixer-enabled) */ -#ifdef ENABLE_SB_MIXER - 0x40, /* 17 - mute mux (Mode2) */ -#else - 0x0, /* 17 - mute mux */ -#endif - 0x0, /* 18 - vol */ - 0x0, /* 19 - master volume */ - 0x0, /* 20 - line-in volume */ - 0x0, /* 21 - cd-in volume */ - 0x0, /* 22 - wave volume */ - 0x0, /* 23 - mute/rec mux */ - 0x0, /* 24 - wave rec gain */ - 0x0, /* 25 - line-in rec gain */ - 0x0 /* 26 - cd-in rec gain */ -}; - -typedef int (*snd_pcm_open_callback_t)(struct snd_pcm_substream *); - -enum card_type { - CMI8330, - CMI8329 -}; - -struct snd_cmi8330 { -#ifdef CONFIG_PNP - struct pnp_dev *cap; - struct pnp_dev *play; - struct pnp_dev *mpu; -#endif - struct snd_card *card; - struct snd_wss *wss; - struct snd_sb *sb; - - struct snd_pcm *pcm; - struct snd_cmi8330_stream { - struct snd_pcm_ops ops; - snd_pcm_open_callback_t open; - void *private_data; /* sb or wss */ - } streams[2]; - - enum card_type type; -}; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_cmi8330_pnpids[] = { - { .id = "CMI0001", .devs = { { "@X@0001" }, { "@@@0001" }, { "@H@0001" }, { "A@@0001" } } }, - { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids); - -#endif - - -static struct snd_kcontrol_new snd_cmi8330_controls[] __devinitdata = { -WSS_DOUBLE("Master Playback Volume", 0, - CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), -WSS_SINGLE("Loud Playback Switch", 0, - CMI8330_MUTEMUX, 6, 1, 1), -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), -WSS_DOUBLE("Line Playback Switch", 0, - CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0), -WSS_DOUBLE("Line Playback Volume", 0, - CMI8330_LINVOL, CMI8330_LINVOL, 4, 0, 15, 0), -WSS_DOUBLE("Line Capture Switch", 0, - CMI8330_RMUX3D, CMI8330_RMUX3D, 2, 1, 1, 0), -WSS_DOUBLE("Line Capture Volume", 0, - CMI8330_LINGAIN, CMI8330_LINGAIN, 4, 0, 15, 0), -WSS_DOUBLE("CD Playback Switch", 0, - CMI8330_MUTEMUX, CMI8330_MUTEMUX, 2, 1, 1, 0), -WSS_DOUBLE("CD Capture Switch", 0, - CMI8330_RMUX3D, CMI8330_RMUX3D, 4, 3, 1, 0), -WSS_DOUBLE("CD Playback Volume", 0, - CMI8330_CDINVOL, CMI8330_CDINVOL, 4, 0, 15, 0), -WSS_DOUBLE("CD Capture Volume", 0, - CMI8330_CDINGAIN, CMI8330_CDINGAIN, 4, 0, 15, 0), -WSS_SINGLE("Mic Playback Switch", 0, - CMI8330_MUTEMUX, 0, 1, 0), -WSS_SINGLE("Mic Playback Volume", 0, - CMI8330_OUTPUTVOL, 0, 7, 0), -WSS_SINGLE("Mic Capture Switch", 0, - CMI8330_RMUX3D, 0, 1, 0), -WSS_SINGLE("Mic Capture Volume", 0, - CMI8330_OUTPUTVOL, 5, 7, 0), -WSS_DOUBLE("Wavetable Playback Switch", 0, - CMI8330_RECMUX, CMI8330_RECMUX, 1, 0, 1, 0), -WSS_DOUBLE("Wavetable Playback Volume", 0, - CMI8330_WAVVOL, CMI8330_WAVVOL, 4, 0, 15, 0), -WSS_DOUBLE("Wavetable Capture Switch", 0, - CMI8330_RECMUX, CMI8330_RECMUX, 5, 4, 1, 0), -WSS_DOUBLE("Wavetable Capture Volume", 0, - CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0), -WSS_SINGLE("3D Control - Switch", 0, - CMI8330_RMUX3D, 5, 1, 1), -WSS_SINGLE("Beep Playback Volume", 0, - CMI8330_OUTPUTVOL, 3, 3, 0), -WSS_DOUBLE("FM Playback Switch", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("FM Playback Volume", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), -WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", CAPTURE, SWITCH), 0, - CMI8330_RMUX3D, 7, 1, 1), -WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0, - CMI8330_MUTEMUX, 7, 1, 1), -}; - -#ifdef ENABLE_SB_MIXER -static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = { -SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31), -SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15), -SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15), -SB_DOUBLE("SB PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31), -SB_DOUBLE("SB Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31), -SB_DOUBLE("SB CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1), -SB_DOUBLE("SB CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31), -SB_DOUBLE("SB Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1), -SB_DOUBLE("SB Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31), -SB_SINGLE("SB Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), -SB_SINGLE("SB Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), -SB_SINGLE("SB Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3), -SB_DOUBLE("SB Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3), -SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3), -SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1), -}; - -static unsigned char cmi8330_sb_init_values[][2] __devinitdata = { - { SB_DSP4_MASTER_DEV + 0, 0 }, - { SB_DSP4_MASTER_DEV + 1, 0 }, - { SB_DSP4_PCM_DEV + 0, 0 }, - { SB_DSP4_PCM_DEV + 1, 0 }, - { SB_DSP4_SYNTH_DEV + 0, 0 }, - { SB_DSP4_SYNTH_DEV + 1, 0 }, - { SB_DSP4_INPUT_LEFT, 0 }, - { SB_DSP4_INPUT_RIGHT, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DSP4_SPEAKER_DEV, 0 }, -}; - - -static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip) -{ - int idx, err; - unsigned long flags; - - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, 0x00, 0x00); /* mixer reset */ - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - /* mute and zero volume channels */ - for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_init_values); idx++) { - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, cmi8330_sb_init_values[idx][0], - cmi8330_sb_init_values[idx][1]); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - } - - for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_mixers); idx++) { - if ((err = snd_sbmixer_add_ctl_elem(chip, &cmi8330_sb_mixers[idx])) < 0) - return err; - } - return 0; -} -#endif - -static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard) -{ - unsigned int idx; - int err; - - strcpy(card->mixername, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D"); - - for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_cmi8330_controls[idx], - acard->wss)); - if (err < 0) - return err; - } - -#ifdef ENABLE_SB_MIXER - if ((err = cmi8330_add_sb_mixers(acard->sb)) < 0) - return err; -#endif - return 0; -} - -#ifdef CONFIG_PNP -static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - /* CMI8329 has a device with ID A@@0001, CMI8330 does not */ - acard->type = (id->devs[3].id[0]) ? CMI8329 : CMI8330; - - acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->cap == NULL) - return -EBUSY; - - acard->play = pnp_request_card_device(card, id->devs[1].id, NULL); - if (acard->play == NULL) - return -EBUSY; - - acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); - if (acard->mpu == NULL) - return -EBUSY; - - pdev = acard->cap; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "AD1848 PnP configure failure\n"); - return -EBUSY; - } - wssport[dev] = pnp_port_start(pdev, 0); - wssdma[dev] = pnp_dma(pdev, 0); - wssirq[dev] = pnp_irq(pdev, 0); - if (pnp_port_start(pdev, 1)) - fmport[dev] = pnp_port_start(pdev, 1); - - /* allocate SB16 resources */ - pdev = acard->play; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "SB16 PnP configure failure\n"); - return -EBUSY; - } - sbport[dev] = pnp_port_start(pdev, 0); - sbdma8[dev] = pnp_dma(pdev, 0); - sbdma16[dev] = pnp_dma(pdev, 1); - sbirq[dev] = pnp_irq(pdev, 0); - /* On CMI8239, the OPL3 port might be present in SB16 PnP resources */ - if (fmport[dev] == SNDRV_AUTO_PORT) { - if (pnp_port_start(pdev, 1)) - fmport[dev] = pnp_port_start(pdev, 1); - else - fmport[dev] = 0x388; /* Or hardwired */ - } - - /* allocate MPU-401 resources */ - pdev = acard->mpu; - - err = pnp_activate_dev(pdev); - if (err < 0) - snd_printk(KERN_ERR "MPU-401 PnP configure failure: will be disabled\n"); - else { - mpuport[dev] = pnp_port_start(pdev, 0); - mpuirq[dev] = pnp_irq(pdev, 0); - } - return 0; -} -#endif - -/* - * PCM interface - * - * since we call the different chip interfaces for playback and capture - * directions, we need a trick. - * - * - copy the ops for each direction into a local record. - * - replace the open callback with the new one, which replaces the - * substream->private_data with the corresponding chip instance - * and calls again the original open callback of the chip. - * - */ - -#ifdef PLAYBACK_ON_SB -#define CMI_SB_STREAM SNDRV_PCM_STREAM_PLAYBACK -#define CMI_AD_STREAM SNDRV_PCM_STREAM_CAPTURE -#else -#define CMI_SB_STREAM SNDRV_PCM_STREAM_CAPTURE -#define CMI_AD_STREAM SNDRV_PCM_STREAM_PLAYBACK -#endif - -static int snd_cmi8330_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream); - - /* replace the private_data and call the original open callback */ - substream->private_data = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].private_data; - return chip->streams[SNDRV_PCM_STREAM_PLAYBACK].open(substream); -} - -static int snd_cmi8330_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream); - - /* replace the private_data and call the original open callback */ - substream->private_data = chip->streams[SNDRV_PCM_STREAM_CAPTURE].private_data; - return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream); -} - -static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip) -{ - struct snd_pcm *pcm; - const struct snd_pcm_ops *ops; - int err; - static snd_pcm_open_callback_t cmi_open_callbacks[2] = { - snd_cmi8330_playback_open, - snd_cmi8330_capture_open - }; - - if ((err = snd_pcm_new(card, (chip->type == CMI8329) ? "CMI8329" : "CMI8330", 0, 1, 1, &pcm)) < 0) - return err; - strcpy(pcm->name, (chip->type == CMI8329) ? "CMI8329" : "CMI8330"); - pcm->private_data = chip; - - /* SB16 */ - ops = snd_sb16dsp_get_pcm_ops(CMI_SB_STREAM); - chip->streams[CMI_SB_STREAM].ops = *ops; - chip->streams[CMI_SB_STREAM].open = ops->open; - chip->streams[CMI_SB_STREAM].ops.open = cmi_open_callbacks[CMI_SB_STREAM]; - chip->streams[CMI_SB_STREAM].private_data = chip->sb; - - /* AD1848 */ - ops = snd_wss_get_pcm_ops(CMI_AD_STREAM); - chip->streams[CMI_AD_STREAM].ops = *ops; - chip->streams[CMI_AD_STREAM].open = ops->open; - chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM]; - chip->streams[CMI_AD_STREAM].private_data = chip->wss; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK].ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &chip->streams[SNDRV_PCM_STREAM_CAPTURE].ops); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, 128*1024); - chip->pcm = pcm; - - return 0; -} - - -#ifdef CONFIG_PM -static int snd_cmi8330_suspend(struct snd_card *card) -{ - struct snd_cmi8330 *acard = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(acard->pcm); - acard->wss->suspend(acard->wss); - snd_sbmixer_suspend(acard->sb); - return 0; -} - -static int snd_cmi8330_resume(struct snd_card *card) -{ - struct snd_cmi8330 *acard = card->private_data; - - snd_sbdsp_reset(acard->sb); - snd_sbmixer_suspend(acard->sb); - acard->wss->resume(acard->wss); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - - -/* - */ - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -#define PFX "cmi8330: " - -static int snd_cmi8330_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - struct snd_cmi8330 *acard; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_cmi8330), &card); - if (err < 0) { - snd_printk(KERN_ERR PFX "could not get a new card\n"); - return err; - } - acard = card->private_data; - acard->card = card; - *cardp = card; - return 0; -} - -static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) -{ - struct snd_cmi8330 *acard; - int i, err; - struct snd_opl3 *opl3; - - acard = card->private_data; - err = snd_wss_create(card, wssport[dev] + 4, -1, - wssirq[dev], - wssdma[dev], -1, - WSS_HW_DETECT, 0, &acard->wss); - if (err < 0) { - snd_printk(KERN_ERR PFX "AD1848 device busy??\n"); - return err; - } - if (acard->wss->hardware != WSS_HW_CMI8330) { - snd_printk(KERN_ERR PFX "AD1848 not found during probe\n"); - return -ENODEV; - } - - if ((err = snd_sbdsp_create(card, sbport[dev], - sbirq[dev], - snd_sb16dsp_interrupt, - sbdma8[dev], - sbdma16[dev], - SB_HW_AUTO, &acard->sb)) < 0) { - snd_printk(KERN_ERR PFX "SB16 device busy??\n"); - return err; - } - if (acard->sb->hardware != SB_HW_16) { - snd_printk(KERN_ERR PFX "SB16 not found during probe\n"); - return err; - } - - snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */ - for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++) - snd_wss_out(acard->wss, i, - snd_cmi8330_image[i - CMI8330_RMUX3D]); - - if ((err = snd_cmi8330_mixer(card, acard)) < 0) { - snd_printk(KERN_ERR PFX "failed to create mixers\n"); - return err; - } - - if ((err = snd_cmi8330_pcm(card, acard)) < 0) { - snd_printk(KERN_ERR PFX "failed to create pcms\n"); - return err; - } - if (fmport[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fmport[dev], fmport[dev] + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX - "no OPL device at 0x%lx-0x%lx ?\n", - fmport[dev], fmport[dev] + 2); - } else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - return err; - } - } - - if (mpuport[dev] != SNDRV_AUTO_PORT) { - if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpuport[dev], 0, mpuirq[dev], - NULL) < 0) - printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", - mpuport[dev]); - } - - strcpy(card->driver, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D"); - strcpy(card->shortname, (acard->type == CMI8329) ? "C-Media CMI8329" : "C-Media CMI8330/C3D"); - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - card->shortname, - acard->wss->port, - wssirq[dev], - wssdma[dev]); - - return snd_card_register(card); -} - -static int __devinit snd_cmi8330_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev] || is_isapnp_selected(dev)) - return 0; - if (wssport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify wssport\n"); - return 0; - } - if (sbport[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify sbport\n"); - return 0; - } - return 1; -} - -static int __devinit snd_cmi8330_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_cmi8330_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_cmi8330_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_cmi8330_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_cmi8330_suspend(dev_get_drvdata(dev)); -} - -static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n) -{ - return snd_cmi8330_resume(dev_get_drvdata(dev)); -} -#endif - -#define DEV_NAME "cmi8330" - -static struct isa_driver snd_cmi8330_driver = { - .match = snd_cmi8330_isa_match, - .probe = snd_cmi8330_isa_probe, - .remove = __devexit_p(snd_cmi8330_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_cmi8330_isa_suspend, - .resume = snd_cmi8330_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_cmi8330_card_new(dev, &card); - if (res < 0) - return res; - if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { - snd_printk(KERN_ERR PFX "PnP detection failed\n"); - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_cmi8330_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_cmi8330_suspend(pnp_get_card_drvdata(pcard)); -} - -static int snd_cmi8330_pnp_resume(struct pnp_card_link *pcard) -{ - return snd_cmi8330_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver cmi8330_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "cmi8330", - .id_table = snd_cmi8330_pnpids, - .probe = snd_cmi8330_pnp_detect, - .remove = __devexit_p(snd_cmi8330_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_cmi8330_pnp_suspend, - .resume = snd_cmi8330_pnp_resume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __init alsa_card_cmi8330_init(void) -{ - int err; - - err = isa_register_driver(&snd_cmi8330_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&cmi8330_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_cmi8330_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&cmi8330_pnpc_driver); - - if (isa_registered) -#endif - isa_unregister_driver(&snd_cmi8330_driver); -} - -module_init(alsa_card_cmi8330_init) -module_exit(alsa_card_cmi8330_exit) diff --git a/ANDROID_3.4.5/sound/isa/cs423x/Makefile b/ANDROID_3.4.5/sound/isa/cs423x/Makefile deleted file mode 100644 index 6d397e8d..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-cs4231-objs := cs4231.o -snd-cs4236-objs := cs4236.o cs4236_lib.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_CS4231) += snd-cs4231.o -obj-$(CONFIG_SND_CS4236) += snd-cs4236.o - - diff --git a/ANDROID_3.4.5/sound/isa/cs423x/cs4231.c b/ANDROID_3.4.5/sound/isa/cs423x/cs4231.c deleted file mode 100644 index 99dda45e..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/cs4231.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Generic driver for CS4231 chips - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Originally the CS4232/CS4232A driver, modified for use on CS4231 by - * Tugrul Galatali <galatalt@stuy.edu> - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/initval.h> - -#define CRD_NAME "Generic CS4231" -#define DEV_NAME "cs4231" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver."); - -static int __devinit snd_cs4231_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - if (port[n] == SNDRV_AUTO_PORT) { - dev_err(dev, "please specify port\n"); - return 0; - } - if (irq[n] == SNDRV_AUTO_IRQ) { - dev_err(dev, "please specify irq\n"); - return 0; - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dev_err(dev, "please specify dma1\n"); - return 0; - } - return 1; -} - -static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_wss *chip; - struct snd_pcm *pcm; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) - return error; - - error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], dma2[n], - WSS_HW_DETECT, 0, &chip); - if (error < 0) - goto out; - - card->private_data = chip; - - error = snd_wss_pcm(chip, 0, &pcm); - if (error < 0) - goto out; - - strcpy(card->driver, "CS4231"); - strcpy(card->shortname, pcm->name); - - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - pcm->name, chip->port, irq[n], dma1[n]); - if (dma2[n] >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]); - - error = snd_wss_mixer(chip); - if (error < 0) - goto out; - - error = snd_wss_timer(chip, 0, NULL); - if (error < 0) - goto out; - - if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) { - if (mpu_irq[n] == SNDRV_AUTO_IRQ) - mpu_irq[n] = -1; - if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, - mpu_port[n], 0, mpu_irq[n], - NULL) < 0) - dev_warn(dev, "MPU401 not detected\n"); - } - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->suspend(chip); - return 0; -} - -static int snd_cs4231_resume(struct device *dev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_wss *chip = card->private_data; - - chip->resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct isa_driver snd_cs4231_driver = { - .match = snd_cs4231_match, - .probe = snd_cs4231_probe, - .remove = __devexit_p(snd_cs4231_remove), -#ifdef CONFIG_PM - .suspend = snd_cs4231_suspend, - .resume = snd_cs4231_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_cs4231_init(void) -{ - return isa_register_driver(&snd_cs4231_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_cs4231_exit(void) -{ - isa_unregister_driver(&snd_cs4231_driver); -} - -module_init(alsa_card_cs4231_init); -module_exit(alsa_card_cs4231_exit); diff --git a/ANDROID_3.4.5/sound/isa/cs423x/cs4236.c b/ANDROID_3.4.5/sound/isa/cs423x/cs4236.c deleted file mode 100644 index 740c51a1..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/cs4236.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Driver for generic CS4232/CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 chips - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cirrus Logic CS4232-9"); -MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000}," - "{Turtle Beach,Tropez Plus}," - "{SIC CrystalWave 32}," - "{Hewlett Packard,Omnibook 5500}," - "{TerraTec,Maestro 32/96}," - "{Philips,PCA70PS}}," - "{{Crystal Semiconductors,CS4235}," - "{Crystal Semiconductors,CS4236}," - "{Crystal Semiconductors,CS4237}," - "{Crystal Semiconductors,CS4238}," - "{Crystal Semiconductors,CS4239}," - "{Acer,AW37}," - "{Acer,AW35/Pro}," - "{Crystal,3D}," - "{Crystal Computer,TidalWave128}," - "{Dell,Optiplex GX1}," - "{Dell,Workstation 400 sound}," - "{EliteGroup,P5TX-LA sound}," - "{Gallant,SC-70P}," - "{Gateway,E1000 Onboard CS4236B}," - "{Genius,Sound Maker 3DJ}," - "{Hewlett Packard,HP6330 sound}," - "{IBM,PC 300PL sound}," - "{IBM,Aptiva 2137 E24}," - "{IBM,IntelliStation M Pro}," - "{Intel,Marlin Spike Mobo CS4235}," - "{Intel PR440FX Onboard}," - "{Guillemot,MaxiSound 16 PnP}," - "{NewClear,3D}," - "{TerraTec,AudioSystem EWS64L/XL}," - "{Typhoon Soundsystem,CS4236B}," - "{Turtle Beach,Malibu}," - "{Unknown,Digital PC 5000 Onboard}}"); - -MODULE_ALIAS("snd_cs4232"); - -#define IDENT "CS4232+" -#define DEV_NAME "cs4232+" - -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_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static long sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " IDENT " driver."); -module_param_array(cport, long, NULL, 0444); -MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver."); -module_param_array(sb_port, long, NULL, 0444); -MODULE_PARM_DESC(sb_port, "SB port # for " IDENT " driver (optional)."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnpc_registered; -static int pnp_registered; -#endif /* CONFIG_PNP */ - -struct snd_card_cs4236 { - struct snd_wss *chip; - struct resource *res_sb_port; -#ifdef CONFIG_PNP - struct pnp_dev *wss; - struct pnp_dev *ctrl; - struct pnp_dev *mpu; -#endif -}; - -#ifdef CONFIG_PNP - -/* - * PNP BIOS - */ -static const struct pnp_device_id snd_cs423x_pnpbiosids[] = { - { .id = "CSC0100" }, - { .id = "CSC0000" }, - /* Guillemot Turtlebeach something appears to be cs4232 compatible - * (untested) */ - { .id = "GIM0100" }, - { .id = "" } -}; -MODULE_DEVICE_TABLE(pnp, snd_cs423x_pnpbiosids); - -#define CS423X_ISAPNP_DRIVER "cs4232_isapnp" -static struct pnp_card_device_id snd_cs423x_pnpids[] = { - /* Philips PCA70PS */ - { .id = "CSC0d32", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } }, - /* TerraTec Maestro 32/96 (CS4232) */ - { .id = "CSC1a32", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* HP Omnibook 5500 onboard */ - { .id = "CSC4232", .devs = { { "CSC0000" }, { "CSC0002" }, { "CSC0003" } } }, - /* Unnamed CS4236 card (Made in Taiwan) */ - { .id = "CSC4236", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Turtle Beach TBS-2000 (CS4232) */ - { .id = "CSC7532", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSCb006" } } }, - /* Turtle Beach Tropez Plus (CS4232) */ - { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } }, - /* SIC CrystalWave 32 (CS4232) */ - { .id = "CSCf032", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Netfinity 3000 on-board soundcard */ - { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC010f" } } }, - /* Intel Marlin Spike Motherboard - CS4235 */ - { .id = "CSC0225", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Intel Marlin Spike Motherboard (#2) - CS4235 */ - { .id = "CSC0225", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* Unknown Intel mainboard - CS4235 */ - { .id = "CSC0225", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* Genius Sound Maker 3DJ - CS4237B */ - { .id = "CSC0437", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Digital PC 5000 Onboard - CS4236B */ - { .id = "CSC0735", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* some unknown CS4236B */ - { .id = "CSC0b35", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Intel PR440FX Onboard sound */ - { .id = "CSC0b36", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4235 on mainboard without MPU */ - { .id = "CSC1425", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* Gateway E1000 Onboard CS4236B */ - { .id = "CSC1335", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* HP 6330 Onboard sound */ - { .id = "CSC1525", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* Crystal Computer TidalWave128 */ - { .id = "CSC1e37", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* ACER AW37 - CS4235 */ - { .id = "CSC4236", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* build-in soundcard in EliteGroup P5TX-LA motherboard - CS4237B */ - { .id = "CSC4237", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Crystal 3D - CS4237B */ - { .id = "CSC4336", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Typhoon Soundsystem PnP - CS4236B */ - { .id = "CSC4536", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Crystal CX4235-XQ3 EP - CS4235 */ - { .id = "CSC4625", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* Crystal Semiconductors CS4237B */ - { .id = "CSC4637", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* NewClear 3D - CX4237B-XQ3 */ - { .id = "CSC4837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Dell Optiplex GX1 - CS4236B */ - { .id = "CSC6835", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Dell P410 motherboard - CS4236B */ - { .id = "CSC6835", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* Dell Workstation 400 Onboard - CS4236B */ - { .id = "CSC6836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Turtle Beach Malibu - CS4237B */ - { .id = "CSC7537", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4235 - onboard */ - { .id = "CSC8025", .devs = { { "CSC0100" }, { "CSC0110" }, { "CSC0103" } } }, - /* IBM Aptiva 2137 E24 Onboard - CS4237B */ - { .id = "CSC8037", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* IBM IntelliStation M Pro motherboard */ - { .id = "CSCc835", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* Guillemot MaxiSound 16 PnP - CS4236B */ - { .id = "CSC9836", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Gallant SC-70P */ - { .id = "CSC9837", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* Techmakers MF-4236PW */ - { .id = "CSCa736", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* TerraTec AudioSystem EWS64XL - CS4236B */ - { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" }, { "CSCa803" } } }, - /* TerraTec AudioSystem EWS64XL - CS4236B */ - { .id = "CSCa836", .devs = { { "CSCa800" }, { "CSCa810" } } }, - /* ACER AW37/Pro - CS4235 */ - { .id = "CSCd925", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* ACER AW35/Pro - CS4237B */ - { .id = "CSCd937", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4235 without MPU401 */ - { .id = "CSCe825", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* Unknown SiS530 - CS4235 */ - { .id = "CSC4825", .devs = { { "CSC0100" }, { "CSC0110" } } }, - /* IBM IntelliStation M Pro 6898 11U - CS4236B */ - { .id = "CSCe835", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* IBM PC 300PL Onboard - CS4236B */ - { .id = "CSCe836", .devs = { { "CSC0000" }, { "CSC0010" } } }, - /* Some noname CS4236 based card */ - { .id = "CSCe936", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4236B */ - { .id = "CSCf235", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* CS4236B */ - { .id = "CSCf238", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } }, - /* --- */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids); - -/* WSS initialization */ -static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n"); - return -EBUSY; - } - port[dev] = pnp_port_start(pdev, 0); - if (fm_port[dev] > 0) - fm_port[dev] = pnp_port_start(pdev, 1); - sb_port[dev] = pnp_port_start(pdev, 2); - irq[dev] = pnp_irq(pdev, 0); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1) == 4 ? -1 : (int)pnp_dma(pdev, 1); - snd_printdd("isapnp WSS: wss port=0x%lx, fm port=0x%lx, sb port=0x%lx\n", - port[dev], fm_port[dev], sb_port[dev]); - snd_printdd("isapnp WSS: irq=%i, dma1=%i, dma2=%i\n", - irq[dev], dma1[dev], dma2[dev]); - return 0; -} - -/* CTRL initialization */ -static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n"); - return -EBUSY; - } - cport[dev] = pnp_port_start(pdev, 0); - snd_printdd("isapnp CTRL: control port=0x%lx\n", cport[dev]); - return 0; -} - -/* MPU initialization */ -static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n"); - mpu_port[dev] = SNDRV_AUTO_PORT; - mpu_irq[dev] = SNDRV_AUTO_IRQ; - } else { - mpu_port[dev] = pnp_port_start(pdev, 0); - if (mpu_irq[dev] >= 0 && - pnp_irq_valid(pdev, 0) && pnp_irq(pdev, 0) >= 0) { - mpu_irq[dev] = pnp_irq(pdev, 0); - } else { - mpu_irq[dev] = -1; /* disable interrupt */ - } - } - snd_printdd("isapnp MPU: port=0x%lx, irq=%i\n", mpu_port[dev], mpu_irq[dev]); - return 0; -} - -static int __devinit snd_card_cs423x_pnp(int dev, struct snd_card_cs4236 *acard, - struct pnp_dev *pdev, - struct pnp_dev *cdev) -{ - acard->wss = pdev; - if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0) - return -EBUSY; - if (cdev) - cport[dev] = pnp_port_start(cdev, 0); - else - cport[dev] = -1; - return 0; -} - -static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->wss == NULL) - return -EBUSY; - acard->ctrl = pnp_request_card_device(card, id->devs[1].id, NULL); - if (acard->ctrl == NULL) - return -EBUSY; - if (id->devs[2].id[0]) { - acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); - if (acard->mpu == NULL) - return -EBUSY; - } - - /* WSS initialization */ - if (snd_cs423x_pnp_init_wss(dev, acard->wss) < 0) - return -EBUSY; - - /* CTRL initialization */ - if (acard->ctrl && cport[dev] > 0) { - if (snd_cs423x_pnp_init_ctrl(dev, acard->ctrl) < 0) - return -EBUSY; - } - /* MPU initialization */ - if (acard->mpu && mpu_port[dev] > 0) { - if (snd_cs423x_pnp_init_mpu(dev, acard->mpu) < 0) - return -EBUSY; - } - return 0; -} -#endif /* CONFIG_PNP */ - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static void snd_card_cs4236_free(struct snd_card *card) -{ - struct snd_card_cs4236 *acard = card->private_data; - - release_and_free_resource(acard->res_sb_port); -} - -static int snd_cs423x_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_cs4236), &card); - if (err < 0) - return err; - card->private_free = snd_card_cs4236_free; - *cardp = card; - return 0; -} - -static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) -{ - struct snd_card_cs4236 *acard; - struct snd_pcm *pcm; - struct snd_wss *chip; - struct snd_opl3 *opl3; - int err; - - acard = card->private_data; - if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) - if ((acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB")) == NULL) { - printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]); - return -EBUSY; - } - - err = snd_cs4236_create(card, port[dev], cport[dev], - irq[dev], - dma1[dev], dma2[dev], - WSS_HW_DETECT3, 0, &chip); - if (err < 0) - return err; - - acard->chip = chip; - if (chip->hardware & WSS_HW_CS4236B_MASK) { - - err = snd_cs4236_pcm(chip, 0, &pcm); - if (err < 0) - return err; - - err = snd_cs4236_mixer(chip); - if (err < 0) - return err; - } else { - err = snd_wss_pcm(chip, 0, &pcm); - if (err < 0) - return err; - - err = snd_wss_mixer(chip); - if (err < 0) - return err; - } - strcpy(card->driver, pcm->name); - strcpy(card->shortname, pcm->name); - sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", - pcm->name, - chip->port, - irq[dev], - dma1[dev]); - if (dma2[dev] >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); - - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) - return err; - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, - fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3_CS, 0, &opl3) < 0) { - printk(KERN_WARNING IDENT ": OPL3 not detected\n"); - } else { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) - return err; - } - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, - mpu_port[dev], 0, - mpu_irq[dev], NULL) < 0) - printk(KERN_WARNING IDENT ": MPU401 not detected\n"); - } - - return snd_card_register(card); -} - -static int __devinit snd_cs423x_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev] || is_isapnp_selected(dev)) - return 0; - - if (port[dev] == SNDRV_AUTO_PORT) { - dev_err(pdev, "please specify port\n"); - return 0; - } - if (cport[dev] == SNDRV_AUTO_PORT) { - dev_err(pdev, "please specify cport\n"); - return 0; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - dev_err(pdev, "please specify irq\n"); - return 0; - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - dev_err(pdev, "please specify dma1\n"); - return 0; - } - return 1; -} - -static int __devinit snd_cs423x_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_cs423x_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_cs423x_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_cs423x_isa_remove(struct device *pdev, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_cs423x_suspend(struct snd_card *card) -{ - struct snd_card_cs4236 *acard = card->private_data; - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - acard->chip->suspend(acard->chip); - return 0; -} - -static int snd_cs423x_resume(struct snd_card *card) -{ - struct snd_card_cs4236 *acard = card->private_data; - acard->chip->resume(acard->chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} - -static int snd_cs423x_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_cs423x_suspend(dev_get_drvdata(dev)); -} - -static int snd_cs423x_isa_resume(struct device *dev, unsigned int n) -{ - return snd_cs423x_resume(dev_get_drvdata(dev)); -} -#endif - -static struct isa_driver cs423x_isa_driver = { - .match = snd_cs423x_isa_match, - .probe = snd_cs423x_isa_probe, - .remove = __devexit_p(snd_cs423x_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_cs423x_isa_suspend, - .resume = snd_cs423x_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, - const struct pnp_device_id *id) -{ - static int dev; - int err; - struct snd_card *card; - struct pnp_dev *cdev; - char cid[PNP_ID_LEN]; - - if (pnp_device_is_isapnp(pdev)) - return -ENOENT; /* we have another procedure - card */ - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - /* prepare second id */ - strcpy(cid, pdev->id[0].id); - cid[5] = '1'; - cdev = NULL; - list_for_each_entry(cdev, &(pdev->protocol->devices), protocol_list) { - if (!strcmp(cdev->id[0].id, cid)) - break; - } - err = snd_cs423x_card_new(dev, &card); - if (err < 0) - return err; - err = snd_card_cs423x_pnp(dev, card->private_data, pdev, cdev); - if (err < 0) { - printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n"); - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_cs423x_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_drvdata(pdev, card); - dev++; - return 0; -} - -static void __devexit snd_cs423x_pnp_remove(struct pnp_dev *pdev) -{ - snd_card_free(pnp_get_drvdata(pdev)); - pnp_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM -static int snd_cs423x_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - return snd_cs423x_suspend(pnp_get_drvdata(pdev)); -} - -static int snd_cs423x_pnp_resume(struct pnp_dev *pdev) -{ - return snd_cs423x_resume(pnp_get_drvdata(pdev)); -} -#endif - -static struct pnp_driver cs423x_pnp_driver = { - .name = "cs423x-pnpbios", - .id_table = snd_cs423x_pnpbiosids, - .probe = snd_cs423x_pnpbios_detect, - .remove = __devexit_p(snd_cs423x_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_cs423x_pnp_suspend, - .resume = snd_cs423x_pnp_resume, -#endif -}; - -static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_cs423x_card_new(dev, &card); - if (res < 0) - return res; - if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { - printk(KERN_ERR "isapnp detection failed and probing for " IDENT - " is not supported\n"); - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_cs423x_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_cs423x_suspend(pnp_get_card_drvdata(pcard)); -} - -static int snd_cs423x_pnpc_resume(struct pnp_card_link *pcard) -{ - return snd_cs423x_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver cs423x_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = CS423X_ISAPNP_DRIVER, - .id_table = snd_cs423x_pnpids, - .probe = snd_cs423x_pnpc_detect, - .remove = __devexit_p(snd_cs423x_pnpc_remove), -#ifdef CONFIG_PM - .suspend = snd_cs423x_pnpc_suspend, - .resume = snd_cs423x_pnpc_resume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __init alsa_card_cs423x_init(void) -{ - int err; - - err = isa_register_driver(&cs423x_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - err = pnp_register_driver(&cs423x_pnp_driver); - if (!err) - pnp_registered = 1; - err = pnp_register_card_driver(&cs423x_pnpc_driver); - if (!err) - pnpc_registered = 1; - if (pnp_registered) - err = 0; - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_cs423x_exit(void) -{ -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&cs423x_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&cs423x_pnp_driver); - if (isa_registered) -#endif - isa_unregister_driver(&cs423x_isa_driver); -} - -module_init(alsa_card_cs423x_init) -module_exit(alsa_card_cs423x_exit) diff --git a/ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c b/ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c deleted file mode 100644 index c5adca30..00000000 --- a/ANDROID_3.4.5/sound/isa/cs423x/cs4236_lib.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of CS4235/4236B/4237B/4238B/4239 chips - * - * Note: - * ----- - * - * Bugs: - * ----- - * - * 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 - * - */ - -/* - * Indirect control registers (CS4236B+) - * - * C0 - * D8: WSS reset (all chips) - * - * C1 (all chips except CS4236) - * D7-D5: version - * D4-D0: chip id - * 11101 - CS4235 - * 01011 - CS4236B - * 01000 - CS4237B - * 01001 - CS4238B - * 11110 - CS4239 - * - * C2 - * D7-D4: 3D Space (CS4235,CS4237B,CS4238B,CS4239) - * D3-D0: 3D Center (CS4237B); 3D Volume (CS4238B) - * - * C3 - * D7: 3D Enable (CS4237B) - * D6: 3D Mono Enable (CS4237B) - * D5: 3D Serial Output (CS4237B,CS4238B) - * D4: 3D Enable (CS4235,CS4238B,CS4239) - * - * C4 - * D7: consumer serial port enable (CS4237B,CS4238B) - * D6: channels status block reset (CS4237B,CS4238B) - * D5: user bit in sub-frame of digital audio data (CS4237B,CS4238B) - * D4: validity bit bit in sub-frame of digital audio data (CS4237B,CS4238B) - * - * C5 lower channel status (digital serial data description) (CS4237B,CS4238B) - * D7-D6: first two bits of category code - * D5: lock - * D4-D3: pre-emphasis (0 = none, 1 = 50/15us) - * D2: copy/copyright (0 = copy inhibited) - * D1: 0 = digital audio / 1 = non-digital audio - * - * C6 upper channel status (digital serial data description) (CS4237B,CS4238B) - * D7-D6: sample frequency (0 = 44.1kHz) - * D5: generation status (0 = no indication, 1 = original/commercially precaptureed data) - * D4-D0: category code (upper bits) - * - * C7 reserved (must write 0) - * - * C8 wavetable control - * D7: volume control interrupt enable (CS4235,CS4239) - * D6: hardware volume control format (CS4235,CS4239) - * D3: wavetable serial port enable (all chips) - * D2: DSP serial port switch (all chips) - * D1: disable MCLK (all chips) - * D0: force BRESET low (all chips) - * - */ - -#include <asm/io.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/asoundef.h> -#include <sound/initval.h> -#include <sound/tlv.h> - -/* - * - */ - -static unsigned char snd_cs4236_ext_map[18] = { - /* CS4236_LEFT_LINE */ 0xff, - /* CS4236_RIGHT_LINE */ 0xff, - /* CS4236_LEFT_MIC */ 0xdf, - /* CS4236_RIGHT_MIC */ 0xdf, - /* CS4236_LEFT_MIX_CTRL */ 0xe0 | 0x18, - /* CS4236_RIGHT_MIX_CTRL */ 0xe0, - /* CS4236_LEFT_FM */ 0xbf, - /* CS4236_RIGHT_FM */ 0xbf, - /* CS4236_LEFT_DSP */ 0xbf, - /* CS4236_RIGHT_DSP */ 0xbf, - /* CS4236_RIGHT_LOOPBACK */ 0xbf, - /* CS4236_DAC_MUTE */ 0xe0, - /* CS4236_ADC_RATE */ 0x01, /* 48kHz */ - /* CS4236_DAC_RATE */ 0x01, /* 48kHz */ - /* CS4236_LEFT_MASTER */ 0xbf, - /* CS4236_RIGHT_MASTER */ 0xbf, - /* CS4236_LEFT_WAVE */ 0xbf, - /* CS4236_RIGHT_WAVE */ 0xbf -}; - -/* - * - */ - -static void snd_cs4236_ctrl_out(struct snd_wss *chip, - unsigned char reg, unsigned char val) -{ - outb(reg, chip->cport + 3); - outb(chip->cimage[reg] = val, chip->cport + 4); -} - -static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg) -{ - outb(reg, chip->cport + 3); - return inb(chip->cport + 4); -} - -/* - * PCM - */ - -#define CLOCKS 8 - -static struct snd_ratnum clocks[CLOCKS] = { - { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 }, - { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 }, - { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 }, - { .num = 16934400, .den_min = 1058, .den_max = 1058, .den_step = 1 }, - { .num = 16934400, .den_min = 1764, .den_max = 1764, .den_step = 1 }, - { .num = 16934400, .den_min = 2117, .den_max = 2117, .den_step = 1 }, - { .num = 16934400, .den_min = 2558, .den_max = 2558, .den_step = 1 }, - { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 } -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { - .nrats = CLOCKS, - .rats = clocks, -}; - -static int snd_cs4236_xrate(struct snd_pcm_runtime *runtime) -{ - return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); -} - -static unsigned char divisor_to_rate_register(unsigned int divisor) -{ - switch (divisor) { - case 353: return 1; - case 529: return 2; - case 617: return 3; - case 1058: return 4; - case 1764: return 5; - case 2117: return 6; - case 2558: return 7; - default: - if (divisor < 21 || divisor > 192) { - snd_BUG(); - return 192; - } - return divisor; - } -} - -static void snd_cs4236_playback_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char pdfr) -{ - unsigned long flags; - unsigned char rate = divisor_to_rate_register(params->rate_den); - - spin_lock_irqsave(&chip->reg_lock, flags); - /* set fast playback format change and clean playback FIFO */ - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x10); - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] & ~0x10); - snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_cs4236_capture_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char cdfr) -{ - unsigned long flags; - unsigned char rate = divisor_to_rate_register(params->rate_den); - - spin_lock_irqsave(&chip->reg_lock, flags); - /* set fast capture format change and clean capture FIFO */ - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x20); - snd_wss_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] & ~0x20); - snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -#ifdef CONFIG_PM - -static void snd_cs4236_suspend(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) - chip->image[reg] = snd_wss_in(chip, reg); - for (reg = 0; reg < 18; reg++) - chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg)); - for (reg = 2; reg < 9; reg++) - chip->cimage[reg] = snd_cs4236_ctrl_in(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_cs4236_resume(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) { - switch (reg) { - case CS4236_EXT_REG: - case CS4231_VERSION: - case 27: /* why? CS4235 - master left */ - case 29: /* why? CS4235 - master right */ - break; - default: - snd_wss_out(chip, reg, chip->image[reg]); - break; - } - } - for (reg = 0; reg < 18; reg++) - snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]); - for (reg = 2; reg < 9; reg++) { - switch (reg) { - case 7: - break; - default: - snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]); - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); -} - -#endif /* CONFIG_PM */ -/* - * This function does no fail if the chip is not CS4236B or compatible. - * It just an equivalent to the snd_wss_create() then. - */ -int snd_cs4236_create(struct snd_card *card, - unsigned long port, - unsigned long cport, - int irq, int dma1, int dma2, - unsigned short hardware, - unsigned short hwshare, - struct snd_wss **rchip) -{ - struct snd_wss *chip; - unsigned char ver1, ver2; - unsigned int reg; - int err; - - *rchip = NULL; - if (hardware == WSS_HW_DETECT) - hardware = WSS_HW_DETECT3; - - err = snd_wss_create(card, port, cport, - irq, dma1, dma2, hardware, hwshare, &chip); - if (err < 0) - return err; - - if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) { - snd_printd("chip is not CS4236+, hardware=0x%x\n", - chip->hardware); - *rchip = chip; - return 0; - } -#if 0 - { - int idx; - for (idx = 0; idx < 8; idx++) - snd_printk(KERN_DEBUG "CD%i = 0x%x\n", - idx, inb(chip->cport + idx)); - for (idx = 0; idx < 9; idx++) - snd_printk(KERN_DEBUG "C%i = 0x%x\n", - idx, snd_cs4236_ctrl_in(chip, idx)); - } -#endif - if (cport < 0x100 || cport == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "please, specify control port " - "for CS4236+ chips\n"); - snd_device_free(card, chip); - return -ENODEV; - } - ver1 = snd_cs4236_ctrl_in(chip, 1); - ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); - snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", - cport, ver1, ver2); - if (ver1 != ver2) { - snd_printk(KERN_ERR "CS4236+ chip detected, but " - "control port 0x%lx is not valid\n", cport); - snd_device_free(card, chip); - return -ENODEV; - } - snd_cs4236_ctrl_out(chip, 0, 0x00); - snd_cs4236_ctrl_out(chip, 2, 0xff); - snd_cs4236_ctrl_out(chip, 3, 0x00); - snd_cs4236_ctrl_out(chip, 4, 0x80); - reg = ((IEC958_AES1_CON_PCM_CODER & 3) << 6) | - IEC958_AES0_CON_EMPHASIS_NONE; - snd_cs4236_ctrl_out(chip, 5, reg); - snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2); - snd_cs4236_ctrl_out(chip, 7, 0x00); - /* - * 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958 - * output is working with this setup, other hardware should - * have different signal paths and this value should be - * selectable in the future - */ - snd_cs4236_ctrl_out(chip, 8, 0x8c); - chip->rate_constraint = snd_cs4236_xrate; - chip->set_playback_format = snd_cs4236_playback_format; - chip->set_capture_format = snd_cs4236_capture_format; -#ifdef CONFIG_PM - chip->suspend = snd_cs4236_suspend; - chip->resume = snd_cs4236_resume; -#endif - - /* initialize extended registers */ - for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++) - snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), - snd_cs4236_ext_map[reg]); - - /* initialize compatible but more featured registers */ - snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40); - snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40); - snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff); - snd_wss_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff); - snd_wss_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf); - snd_wss_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf); - snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff); - snd_wss_out(chip, CS4231_LEFT_LINE_IN, 0xff); - snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff); - switch (chip->hardware) { - case WSS_HW_CS4235: - case WSS_HW_CS4239: - snd_wss_out(chip, CS4235_LEFT_MASTER, 0xff); - snd_wss_out(chip, CS4235_RIGHT_MASTER, 0xff); - break; - } - - *rchip = chip; - return 0; -} - -int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - err = snd_wss_pcm(chip, device, &pcm); - if (err < 0) - return err; - pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX; - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * MIXER - */ - -#define CS4236_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -#define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(reg)] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->eimage[CS4236_REG(reg)] & ~(mask << shift)) | val; - change = val != chip->eimage[CS4236_REG(reg)]; - snd_cs4236_ext_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_SINGLEC(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_singlec, .put = snd_cs4236_put_singlec, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->cimage[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->cimage[reg] & ~(mask << shift)) | val; - change = val != chip->cimage[reg]; - snd_cs4236_ctrl_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -#define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \ - shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ - (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(left_reg)] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - val1 = (chip->eimage[CS4236_REG(left_reg)] & ~(mask << shift_left)) | val1; - val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; - change = val1 != chip->eimage[CS4236_REG(left_reg)] || val2 != chip->eimage[CS4236_REG(right_reg)]; - snd_cs4236_ext_out(chip, left_reg, val1); - snd_cs4236_ext_out(chip, right_reg, val2); - } else { - val1 = (chip->eimage[CS4236_REG(left_reg)] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != chip->eimage[CS4236_REG(left_reg)]; - snd_cs4236_ext_out(chip, left_reg, val1); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \ - shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -#define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \ - shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ - (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; - val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)]; - snd_wss_out(chip, left_reg, val1); - snd_cs4236_ext_out(chip, right_reg, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \ - .private_value = 71 << 24, \ - .tlv = { .p = (xtlv) } } - -static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol) -{ - return (vol < 64) ? 63 - vol : 64 + (71 - vol); -} - -static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & 0x7f); - ucontrol->value.integer.value[1] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & 0x7f); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1, val2; - - val1 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[0] & 0x7f); - val2 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[1] & 0x7f); - spin_lock_irqsave(&chip->reg_lock, flags); - val1 = (chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & ~0x7f) | val1; - val2 = (chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & ~0x7f) | val2; - change = val1 != chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] || val2 != chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)]; - snd_cs4236_ext_out(chip, CS4236_LEFT_MASTER, val1); - snd_cs4236_ext_out(chip, CS4236_RIGHT_MASTER, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = snd_cs4236_info_double, \ - .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \ - .private_value = 3 << 24, \ - .tlv = { .p = (xtlv) } } - -static inline int snd_cs4235_mixer_output_accu_get_volume(int vol) -{ - switch ((vol >> 5) & 3) { - case 0: return 1; - case 1: return 3; - case 2: return 2; - case 3: return 0; - } - return 3; -} - -static inline int snd_cs4235_mixer_output_accu_set_volume(int vol) -{ - switch (vol & 3) { - case 0: return 3 << 5; - case 1: return 0 << 5; - case 2: return 2 << 5; - case 3: return 1 << 5; - } - return 1 << 5; -} - -static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]); - ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1, val2; - - val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]); - val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]); - spin_lock_irqsave(&chip->reg_lock, flags); - val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1; - val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2; - change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER]; - snd_wss_out(chip, CS4235_LEFT_MASTER, val1); - snd_wss_out(chip, CS4235_RIGHT_MASTER, val2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - -static struct snd_kcontrol_new snd_cs4236_controls[] = { - -CS4236_DOUBLE("Master Digital Playback Switch", 0, - CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), -CS4236_DOUBLE("Master Digital Capture Switch", 0, - CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), -CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit), - -CS4236_DOUBLE_TLV("Capture Boost Volume", 0, - CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1, - db_scale_2bit), - -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("DSP Playback Switch", 0, - CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("DSP Playback Volume", 0, - CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("FM Playback Switch", 0, - CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("FM Playback Volume", 0, - CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("Wavetable Playback Switch", 0, - CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0, - CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1, - db_scale_6bit_12db_max), - -WSS_DOUBLE("Synth Playback Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Synth Volume", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("Synth Capture Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), -WSS_DOUBLE("Synth Capture Bypass", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1), - -CS4236_DOUBLE("Mic Playback Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), -CS4236_DOUBLE("Mic Capture Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), -CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, - 0, 0, 31, 1, db_scale_5bit_22db_max), -CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), - -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Line Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("Line Capture Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), -WSS_DOUBLE("Line Capture Bypass", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1), - -WSS_DOUBLE("CD Playback Switch", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("CD Volume", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("CD Capture Switch", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), - -CS4236_DOUBLE1("Mono Output Playback Switch", 0, - CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), -CS4236_DOUBLE1("Beep Playback Switch", 0, - CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), -WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1, - db_scale_4bit), -WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0), - -WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, - 0, 0, 15, 0, db_scale_rec_gain), -WSS_DOUBLE("Analog Loopback Capture Switch", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), - -WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), -CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0, - CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1, - db_scale_6bit), -}; - -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0); - -static struct snd_kcontrol_new snd_cs4235_controls[] = { - -WSS_DOUBLE("Master Playback Switch", 0, - CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Master Playback Volume", 0, - CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1, - db_scale_5bit_6db_max), - -CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max), - -WSS_DOUBLE("Synth Playback Switch", 1, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE("Synth Capture Switch", 1, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), -WSS_DOUBLE_TLV("Synth Volume", 1, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1, - db_scale_5bit_12db_max), - -CS4236_DOUBLE_TLV("Capture Volume", 0, - CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1, - db_scale_2bit), - -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE("PCM Capture Switch", 0, - CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), -WSS_DOUBLE_TLV("PCM Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), - -CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), - -CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), - -CS4236_DOUBLE("Wavetable Switch", 0, - CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), - -CS4236_DOUBLE("Mic Capture Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), -CS4236_DOUBLE("Mic Playback Switch", 0, - CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), -CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1, - db_scale_5bit_22db_max), -CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0), - -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("Line Capture Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), -WSS_DOUBLE_TLV("Line Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), - -WSS_DOUBLE("CD Playback Switch", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("CD Capture Switch", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), -WSS_DOUBLE_TLV("CD Volume", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), - -CS4236_DOUBLE1("Beep Playback Switch", 0, - CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), -WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), - -WSS_DOUBLE("Analog Loopback Switch", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), -}; - -#define CS4236_IEC958_ENABLE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4236_info_single, \ - .get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \ - .private_value = 1 << 16 } - -static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0; -#if 0 - printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " - "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_wss_in(chip, CS4231_ALT_FEATURE_1), - snd_cs4236_ctrl_in(chip, 3), - snd_cs4236_ctrl_in(chip, 4), - snd_cs4236_ctrl_in(chip, 5), - snd_cs4236_ctrl_in(chip, 6), - snd_cs4236_ctrl_in(chip, 8)); -#endif - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short enable, val; - - enable = ucontrol->value.integer.value[0] & 1; - - mutex_lock(&chip->mce_mutex); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1); - change = val != chip->image[CS4231_ALT_FEATURE_1]; - snd_wss_out(chip, CS4231_ALT_FEATURE_1, val); - val = snd_cs4236_ctrl_in(chip, 4) | 0xc0; - snd_cs4236_ctrl_out(chip, 4, val); - udelay(100); - val &= ~0x40; - snd_cs4236_ctrl_out(chip, 4, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - mutex_unlock(&chip->mce_mutex); - -#if 0 - printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, " - "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n", - snd_wss_in(chip, CS4231_ALT_FEATURE_1), - snd_cs4236_ctrl_in(chip, 3), - snd_cs4236_ctrl_in(chip, 4), - snd_cs4236_ctrl_in(chip, 5), - snd_cs4236_ctrl_in(chip, 6), - snd_cs4236_ctrl_in(chip, 8)); -#endif - return change; -} - -static struct snd_kcontrol_new snd_cs4236_iec958_controls[] = { -CS4236_IEC958_ENABLE("IEC958 Output Enable", 0), -CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0), -CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0), -CS4236_SINGLEC("IEC958 Output CSBR", 0, 4, 6, 1, 0), -CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0), -CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0) -}; - -static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = { -CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0), -CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1) -}; - -static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = { -CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0), -CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1), -CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1), -CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0), -CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) -}; - -static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = { -CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0), -CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1), -CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1), -CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0) -}; - -int snd_cs4236_mixer(struct snd_wss *chip) -{ - struct snd_card *card; - unsigned int idx, count; - int err; - struct snd_kcontrol_new *kcontrol; - - if (snd_BUG_ON(!chip || !chip->card)) - return -EINVAL; - card = chip->card; - strcpy(card->mixername, snd_wss_chip_id(chip)); - - if (chip->hardware == WSS_HW_CS4235 || - chip->hardware == WSS_HW_CS4239) { - for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0) - return err; - } - } else { - for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0) - return err; - } - } - switch (chip->hardware) { - case WSS_HW_CS4235: - case WSS_HW_CS4239: - count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235); - kcontrol = snd_cs4236_3d_controls_cs4235; - break; - case WSS_HW_CS4237B: - count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237); - kcontrol = snd_cs4236_3d_controls_cs4237; - break; - case WSS_HW_CS4238B: - count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238); - kcontrol = snd_cs4236_3d_controls_cs4238; - break; - default: - count = 0; - kcontrol = NULL; - } - for (idx = 0; idx < count; idx++, kcontrol++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0) - return err; - } - if (chip->hardware == WSS_HW_CS4237B || - chip->hardware == WSS_HW_CS4238B) { - for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0) - return err; - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/es1688/Makefile b/ANDROID_3.4.5/sound/isa/es1688/Makefile deleted file mode 100644 index aee1e4dd..00000000 --- a/ANDROID_3.4.5/sound/isa/es1688/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-es1688-lib-objs := es1688_lib.o -snd-es1688-objs := es1688.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_ES1688) += snd-es1688.o snd-es1688-lib.o -obj-$(CONFIG_SND_GUSEXTREME) += snd-es1688-lib.o diff --git a/ANDROID_3.4.5/sound/isa/es1688/es1688.c b/ANDROID_3.4.5/sound/isa/es1688/es1688.c deleted file mode 100644 index b036e60f..00000000 --- a/ANDROID_3.4.5/sound/isa/es1688/es1688.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Driver for generic ESS AudioDrive ESx688 soundcards - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/isapnp.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/module.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/es1688.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -#define CRD_NAME "Generic ESS ES1688/ES688 AudioDrive" -#define DEV_NAME "es1688" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100}," - "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102}," - "{ESS,ES688 AudioDrive,pnp:ESS6881}," - "{ESS,ES1688 AudioDrive,pnp:ESS1681}}"); - -MODULE_ALIAS("snd_es968"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; -#endif -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* Usually 0x388 */ -static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for ES1688 driver."); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver."); - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static int __devinit snd_es1688_match(struct device *dev, unsigned int n) -{ - return enable[n] && !is_isapnp_selected(n); -} - -static int __devinit snd_es1688_legacy_create(struct snd_card *card, - struct device *dev, unsigned int n) -{ - struct snd_es1688 *chip = card->private_data; - static long possible_ports[] = {0x220, 0x240, 0x260}; - static int possible_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dmas[] = {1, 3, 0, -1}; - - int i, error; - - if (irq[n] == SNDRV_AUTO_IRQ) { - irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma8[n] == SNDRV_AUTO_DMA) { - dma8[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma8[n] < 0) { - dev_err(dev, "unable to find a free DMA\n"); - return -EBUSY; - } - } - - if (port[n] != SNDRV_AUTO_PORT) - return snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_AUTO); - - i = 0; - do { - port[n] = possible_ports[i]; - error = snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_AUTO); - } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); - - return error; -} - -static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n) -{ - struct snd_es1688 *chip = card->private_data; - struct snd_opl3 *opl3; - struct snd_pcm *pcm; - int error; - - error = snd_es1688_pcm(card, chip, 0, &pcm); - if (error < 0) - return error; - - error = snd_es1688_mixer(card, chip); - if (error < 0) - return error; - - strlcpy(card->driver, "ES1688", sizeof(card->driver)); - strlcpy(card->shortname, pcm->name, sizeof(card->shortname)); - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, - chip->irq, chip->dma8); - - if (fm_port[n] == SNDRV_AUTO_PORT) - fm_port[n] = port[n]; /* share the same port */ - - if (fm_port[n] > 0) { - if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) - dev_warn(card->dev, - "opl3 not detected at 0x%lx\n", fm_port[n]); - else { - error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (error < 0) - return error; - } - } - - if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ && - chip->mpu_port > 0) { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, - chip->mpu_port, 0, - mpu_irq[n], NULL); - if (error < 0) - return error; - } - - return snd_card_register(card); -} - -static int __devinit snd_es1688_isa_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, - sizeof(struct snd_es1688), &card); - if (error < 0) - return error; - - error = snd_es1688_legacy_create(card, dev, n); - if (error < 0) - goto out; - - snd_card_set_dev(card, dev); - - error = snd_es1688_probe(card, n); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - - return 0; -out: - snd_card_free(card); - return error; -} - -static int __devexit snd_es1688_isa_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_es1688_driver = { - .match = snd_es1688_match, - .probe = snd_es1688_isa_probe, - .remove = __devexit_p(snd_es1688_isa_remove), -#if 0 /* FIXME */ - .suspend = snd_es1688_suspend, - .resume = snd_es1688_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int snd_es968_pnp_is_probed; - -#ifdef CONFIG_PNP -static int __devinit snd_card_es968_pnp(struct snd_card *card, unsigned int n, - struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_es1688 *chip = card->private_data; - struct pnp_dev *pdev; - int error; - - pdev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); - if (pdev == NULL) - return -ENODEV; - - error = pnp_activate_dev(pdev); - if (error < 0) { - snd_printk(KERN_ERR "ES968 pnp configure failure\n"); - return error; - } - port[n] = pnp_port_start(pdev, 0); - dma8[n] = pnp_dma(pdev, 0); - irq[n] = pnp_irq(pdev, 0); - - return snd_es1688_create(card, chip, port[n], mpu_port[n], irq[n], - mpu_irq[n], dma8[n], ES1688_HW_AUTO); -} - -static int __devinit snd_es968_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_card *card; - static unsigned int dev; - int error; - struct snd_es1688 *chip; - - if (snd_es968_pnp_is_probed) - return -EBUSY; - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev == SNDRV_CARDS) - return -ENODEV; - - error = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_es1688), &card); - if (error < 0) - return error; - chip = card->private_data; - - error = snd_card_es968_pnp(card, dev, pcard, pid); - if (error < 0) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - error = snd_es1688_probe(card, dev); - if (error < 0) - return error; - pnp_set_card_drvdata(pcard, card); - snd_es968_pnp_is_probed = 1; - return 0; -} - -static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); - snd_es968_pnp_is_probed = 0; -} - -#ifdef CONFIG_PM -static int snd_es968_pnp_suspend(struct pnp_card_link *pcard, - pm_message_t state) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_es1688 *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - return 0; -} - -static int snd_es968_pnp_resume(struct pnp_card_link *pcard) -{ - struct snd_card *card = pnp_get_card_drvdata(pcard); - struct snd_es1688 *chip = card->private_data; - - snd_es1688_reset(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct pnp_card_device_id snd_es968_pnpids[] = { - { .id = "ESS0968", .devs = { { "@@@0968" }, } }, - { .id = "ESS0968", .devs = { { "ESS0968" }, } }, - { .id = "", } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids); - -static struct pnp_card_driver es968_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = DEV_NAME " PnP", - .id_table = snd_es968_pnpids, - .probe = snd_es968_pnp_detect, - .remove = __devexit_p(snd_es968_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_es968_pnp_suspend, - .resume = snd_es968_pnp_resume, -#endif -}; -#endif - -static int __init alsa_card_es1688_init(void) -{ -#ifdef CONFIG_PNP - pnp_register_card_driver(&es968_pnpc_driver); - if (snd_es968_pnp_is_probed) - return 0; - pnp_unregister_card_driver(&es968_pnpc_driver); -#endif - return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_es1688_exit(void) -{ - if (!snd_es968_pnp_is_probed) { - isa_unregister_driver(&snd_es1688_driver); - return; - } -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&es968_pnpc_driver); -#endif -} - -module_init(alsa_card_es1688_init); -module_exit(alsa_card_es1688_exit); diff --git a/ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c b/ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c deleted file mode 100644 index 1d47be81..00000000 --- a/ANDROID_3.4.5/sound/isa/es1688/es1688_lib.c +++ /dev/null @@ -1,1046 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of ESS ES1688/688/488 chip - * - * - * 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/delay.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/es1688.h> -#include <sound/initval.h> - -#include <asm/io.h> -#include <asm/dma.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("ESS ESx688 lowlevel module"); -MODULE_LICENSE("GPL"); - -static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val) -{ - int i; - - for (i = 10000; i; i--) - if ((inb(ES1688P(chip, STATUS)) & 0x80) == 0) { - outb(val, ES1688P(chip, COMMAND)); - return 1; - } -#ifdef CONFIG_SND_DEBUG - printk(KERN_DEBUG "snd_es1688_dsp_command: timeout (0x%x)\n", val); -#endif - return 0; -} - -static int snd_es1688_dsp_get_byte(struct snd_es1688 *chip) -{ - int i; - - for (i = 1000; i; i--) - if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) - return inb(ES1688P(chip, READ)); - snd_printd("es1688 get byte failed: 0x%lx = 0x%x!!!\n", ES1688P(chip, DATA_AVAIL), inb(ES1688P(chip, DATA_AVAIL))); - return -ENODEV; -} - -static int snd_es1688_write(struct snd_es1688 *chip, - unsigned char reg, unsigned char data) -{ - if (!snd_es1688_dsp_command(chip, reg)) - return 0; - return snd_es1688_dsp_command(chip, data); -} - -static int snd_es1688_read(struct snd_es1688 *chip, unsigned char reg) -{ - /* Read a byte from an extended mode register of ES1688 */ - if (!snd_es1688_dsp_command(chip, 0xc0)) - return -1; - if (!snd_es1688_dsp_command(chip, reg)) - return -1; - return snd_es1688_dsp_get_byte(chip); -} - -void snd_es1688_mixer_write(struct snd_es1688 *chip, - unsigned char reg, unsigned char data) -{ - outb(reg, ES1688P(chip, MIXER_ADDR)); - udelay(10); - outb(data, ES1688P(chip, MIXER_DATA)); - udelay(10); -} - -static unsigned char snd_es1688_mixer_read(struct snd_es1688 *chip, unsigned char reg) -{ - unsigned char result; - - outb(reg, ES1688P(chip, MIXER_ADDR)); - udelay(10); - result = inb(ES1688P(chip, MIXER_DATA)); - udelay(10); - return result; -} - -int snd_es1688_reset(struct snd_es1688 *chip) -{ - int i; - - outb(3, ES1688P(chip, RESET)); /* valid only for ESS chips, SB -> 1 */ - udelay(10); - outb(0, ES1688P(chip, RESET)); - udelay(30); - for (i = 0; i < 1000 && !(inb(ES1688P(chip, DATA_AVAIL)) & 0x80); i++); - if (inb(ES1688P(chip, READ)) != 0xaa) { - snd_printd("ess_reset at 0x%lx: failed!!!\n", chip->port); - return -ENODEV; - } - snd_es1688_dsp_command(chip, 0xc6); /* enable extended mode */ - return 0; -} -EXPORT_SYMBOL(snd_es1688_reset); - -static int snd_es1688_probe(struct snd_es1688 *chip) -{ - unsigned long flags; - unsigned short major, minor, hw; - int i; - - /* - * initialization sequence - */ - - spin_lock_irqsave(&chip->reg_lock, flags); /* Some ESS1688 cards need this */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE2)); /* ENABLE2 */ - inb(ES1688P(chip, ENABLE1)); /* ENABLE1 */ - inb(ES1688P(chip, ENABLE0)); /* ENABLE0 */ - - if (snd_es1688_reset(chip) < 0) { - snd_printdd("ESS: [0x%lx] reset failed... 0x%x\n", chip->port, inb(ES1688P(chip, READ))); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - snd_es1688_dsp_command(chip, 0xe7); /* return identification */ - - for (i = 1000, major = minor = 0; i; i--) { - if (inb(ES1688P(chip, DATA_AVAIL)) & 0x80) { - if (major == 0) { - major = inb(ES1688P(chip, READ)); - } else { - minor = inb(ES1688P(chip, READ)); - } - } - } - - spin_unlock_irqrestore(&chip->reg_lock, flags); - - snd_printdd("ESS: [0x%lx] found.. major = 0x%x, minor = 0x%x\n", chip->port, major, minor); - - chip->version = (major << 8) | minor; - if (!chip->version) - return -ENODEV; /* probably SB */ - - hw = ES1688_HW_AUTO; - switch (chip->version & 0xfff0) { - case 0x4880: - snd_printk(KERN_ERR "[0x%lx] ESS: AudioDrive ES488 detected, " - "but driver is in another place\n", chip->port); - return -ENODEV; - case 0x6880: - hw = (chip->version & 0x0f) >= 8 ? ES1688_HW_1688 : ES1688_HW_688; - break; - default: - snd_printk(KERN_ERR "[0x%lx] ESS: unknown AudioDrive chip " - "with version 0x%x (Jazz16 soundcard?)\n", - chip->port, chip->version); - return -ENODEV; - } - - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ - snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ - spin_unlock_irqrestore(&chip->reg_lock, flags); - - /* enable joystick, but disable OPL3 */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_es1688_mixer_write(chip, 0x40, 0x01); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - return 0; -} - -static int snd_es1688_init(struct snd_es1688 * chip, int enable) -{ - static int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1}; - unsigned long flags; - int cfg, irq_bits, dma, dma_bits, tmp, tmp1; - - /* ok.. setup MPU-401 port and joystick and OPL3 */ - cfg = 0x01; /* enable joystick, but disable OPL3 */ - if (enable && chip->mpu_port >= 0x300 && chip->mpu_irq > 0 && chip->hardware != ES1688_HW_688) { - tmp = (chip->mpu_port & 0x0f0) >> 4; - if (tmp <= 3) { - switch (chip->mpu_irq) { - case 9: - tmp1 = 4; - break; - case 5: - tmp1 = 5; - break; - case 7: - tmp1 = 6; - break; - case 10: - tmp1 = 7; - break; - default: - tmp1 = 0; - } - if (tmp1) { - cfg |= (tmp << 3) | (tmp1 << 5); - } - } - } -#if 0 - snd_printk(KERN_DEBUG "mpu cfg = 0x%x\n", cfg); -#endif - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_mixer_write(chip, 0x40, cfg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - /* --- */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_read(chip, 0xb1); - snd_es1688_read(chip, 0xb2); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (enable) { - cfg = 0xf0; /* enable only DMA counter interrupt */ - irq_bits = irqs[chip->irq & 0x0f]; - if (irq_bits < 0) { - snd_printk(KERN_ERR "[0x%lx] ESS: bad IRQ %d " - "for ES1688 chip!!\n", - chip->port, chip->irq); -#if 0 - irq_bits = 0; - cfg = 0x10; -#endif - return -EINVAL; - } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, cfg | (irq_bits << 2)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - cfg = 0xf0; /* extended mode DMA enable */ - dma = chip->dma8; - if (dma > 3 || dma == 2) { - snd_printk(KERN_ERR "[0x%lx] ESS: bad DMA channel %d " - "for ES1688 chip!!\n", chip->port, dma); -#if 0 - dma_bits = 0; - cfg = 0x00; /* disable all DMA */ -#endif - return -EINVAL; - } else { - dma_bits = dma; - if (dma != 3) - dma_bits++; - } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb2, cfg | (dma_bits << 2)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - } else { - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xb1, 0x10); /* disable IRQ */ - snd_es1688_write(chip, 0xb2, 0x00); /* disable DMA */ - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_read(chip, 0xb1); - snd_es1688_read(chip, 0xb2); - snd_es1688_reset(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -/* - - */ - -static struct snd_ratnum clocks[2] = { - { - .num = 795444, - .den_min = 1, - .den_max = 128, - .den_step = 1, - }, - { - .num = 397722, - .den_min = 1, - .den_max = 128, - .den_step = 1, - } -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { - .nrats = 2, - .rats = clocks, -}; - -static void snd_es1688_set_rate(struct snd_es1688 *chip, struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int bits, divider; - - if (runtime->rate_num == clocks[0].num) - bits = 256 - runtime->rate_den; - else - bits = 128 - runtime->rate_den; - /* set filter register */ - divider = 256 - 7160000*20/(8*82*runtime->rate); - /* write result to hardware */ - snd_es1688_write(chip, 0xa1, bits); - snd_es1688_write(chip, 0xa2, divider); -} - -static int snd_es1688_ioctl(struct snd_pcm_substream *substream, - unsigned int cmd, void *arg) -{ - return snd_pcm_lib_ioctl(substream, cmd, arg); -} - -static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char value) -{ - int val; - - if (cmd == SNDRV_PCM_TRIGGER_STOP) { - value = 0x00; - } else if (cmd != SNDRV_PCM_TRIGGER_START) { - return -EINVAL; - } - spin_lock(&chip->reg_lock); - chip->trigger_value = value; - val = snd_es1688_read(chip, 0xb8); - if ((val < 0) || (val & 0x0f) == value) { - spin_unlock(&chip->reg_lock); - return -EINVAL; /* something is wrong */ - } -#if 0 - printk(KERN_DEBUG "trigger: val = 0x%x, value = 0x%x\n", val, value); - printk(KERN_DEBUG "trigger: pointer = 0x%x\n", - snd_dma_pointer(chip->dma8, chip->dma_size)); -#endif - snd_es1688_write(chip, 0xb8, (val & 0xf0) | value); - spin_unlock(&chip->reg_lock); - return 0; -} - -static int snd_es1688_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_es1688_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_es1688_playback_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->dma_size = size; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_reset(chip); - snd_es1688_set_rate(chip, substream); - snd_es1688_write(chip, 0xb8, 4); /* auto init DMA mode */ - snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); - snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ - if (runtime->channels == 1) { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit mono */ - snd_es1688_write(chip, 0xb6, 0x80); - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0xd0); - } else { - /* 16. bit mono */ - snd_es1688_write(chip, 0xb6, 0x00); - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xf4); - } - } else { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit stereo */ - snd_es1688_write(chip, 0xb6, 0x80); - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0x98); - } else { - /* 16. bit stereo */ - snd_es1688_write(chip, 0xb6, 0x00); - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xbc); - } - } - snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); - snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); - snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKON); - spin_unlock_irqrestore(&chip->reg_lock, flags); - /* --- */ - count = -count; - snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xa4, (unsigned char) count); - snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_es1688_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - return snd_es1688_trigger(chip, cmd, 0x05); -} - -static int snd_es1688_capture_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - chip->dma_size = size; - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_reset(chip); - snd_es1688_set_rate(chip, substream); - snd_es1688_dsp_command(chip, ES1688_DSP_CMD_SPKOFF); - snd_es1688_write(chip, 0xb8, 0x0e); /* auto init DMA mode */ - snd_es1688_write(chip, 0xa8, (snd_es1688_read(chip, 0xa8) & ~0x03) | (3 - runtime->channels)); - snd_es1688_write(chip, 0xb9, 2); /* demand mode (4 bytes/request) */ - if (runtime->channels == 1) { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit mono */ - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0xd0); - } else { - /* 16. bit mono */ - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xf4); - } - } else { - if (snd_pcm_format_width(runtime->format) == 8) { - /* 8. bit stereo */ - snd_es1688_write(chip, 0xb7, 0x51); - snd_es1688_write(chip, 0xb7, 0x98); - } else { - /* 16. bit stereo */ - snd_es1688_write(chip, 0xb7, 0x71); - snd_es1688_write(chip, 0xb7, 0xbc); - } - } - snd_es1688_write(chip, 0xb1, (snd_es1688_read(chip, 0xb1) & 0x0f) | 0x50); - snd_es1688_write(chip, 0xb2, (snd_es1688_read(chip, 0xb2) & 0x0f) | 0x50); - spin_unlock_irqrestore(&chip->reg_lock, flags); - /* --- */ - count = -count; - snd_dma_program(chip->dma8, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_es1688_write(chip, 0xa4, (unsigned char) count); - snd_es1688_write(chip, 0xa5, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_es1688_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - return snd_es1688_trigger(chip, cmd, 0x0f); -} - -static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id) -{ - struct snd_es1688 *chip = dev_id; - - if (chip->trigger_value == 0x05) /* ok.. playback is active */ - snd_pcm_period_elapsed(chip->playback_substream); - if (chip->trigger_value == 0x0f) /* ok.. capture is active */ - snd_pcm_period_elapsed(chip->capture_substream); - - inb(ES1688P(chip, DATA_AVAIL)); /* ack interrupt */ - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_es1688_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (chip->trigger_value != 0x05) - return 0; - ptr = snd_dma_pointer(chip->dma8, chip->dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_es1688_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (chip->trigger_value != 0x0f) - return 0; - ptr = snd_dma_pointer(chip->dma8, chip->dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static struct snd_pcm_hardware snd_es1688_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_es1688_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - - */ - -static int snd_es1688_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (chip->capture_substream != NULL) - return -EAGAIN; - chip->playback_substream = substream; - runtime->hw = snd_es1688_playback; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - return 0; -} - -static int snd_es1688_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - if (chip->playback_substream != NULL) - return -EAGAIN; - chip->capture_substream = substream; - runtime->hw = snd_es1688_capture; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - return 0; -} - -static int snd_es1688_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - return 0; -} - -static int snd_es1688_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_es1688 *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - return 0; -} - -static int snd_es1688_free(struct snd_es1688 *chip) -{ - if (chip->res_port) { - snd_es1688_init(chip, 0); - release_and_free_resource(chip->res_port); - } - if (chip->irq >= 0) - free_irq(chip->irq, (void *) chip); - if (chip->dma8 >= 0) { - disable_dma(chip->dma8); - free_dma(chip->dma8); - } - return 0; -} - -static int snd_es1688_dev_free(struct snd_device *device) -{ - struct snd_es1688 *chip = device->device_data; - return snd_es1688_free(chip); -} - -static const char *snd_es1688_chip_id(struct snd_es1688 *chip) -{ - static char tmp[16]; - sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f); - return tmp; -} - -int snd_es1688_create(struct snd_card *card, - struct snd_es1688 *chip, - unsigned long port, - unsigned long mpu_port, - int irq, - int mpu_irq, - int dma8, - unsigned short hardware) -{ - static struct snd_device_ops ops = { - .dev_free = snd_es1688_dev_free, - }; - - int err; - - if (chip == NULL) - return -ENOMEM; - chip->irq = -1; - chip->dma8 = -1; - - if ((chip->res_port = request_region(port + 4, 12, "ES1688")) == NULL) { - snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4); - return -EBUSY; - } - if (request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip)) { - snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq); - return -EBUSY; - } - chip->irq = irq; - if (request_dma(dma8, "ES1688")) { - snd_printk(KERN_ERR "es1688: can't grab DMA8 %d\n", dma8); - return -EBUSY; - } - chip->dma8 = dma8; - - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->mixer_lock); - chip->port = port; - mpu_port &= ~0x000f; - if (mpu_port < 0x300 || mpu_port > 0x330) - mpu_port = 0; - chip->mpu_port = mpu_port; - chip->mpu_irq = mpu_irq; - chip->hardware = hardware; - - err = snd_es1688_probe(chip); - if (err < 0) - return err; - - err = snd_es1688_init(chip, 1); - if (err < 0) - return err; - - /* Register device */ - return snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); -} - -static struct snd_pcm_ops snd_es1688_playback_ops = { - .open = snd_es1688_playback_open, - .close = snd_es1688_playback_close, - .ioctl = snd_es1688_ioctl, - .hw_params = snd_es1688_hw_params, - .hw_free = snd_es1688_hw_free, - .prepare = snd_es1688_playback_prepare, - .trigger = snd_es1688_playback_trigger, - .pointer = snd_es1688_playback_pointer, -}; - -static struct snd_pcm_ops snd_es1688_capture_ops = { - .open = snd_es1688_capture_open, - .close = snd_es1688_capture_close, - .ioctl = snd_es1688_ioctl, - .hw_params = snd_es1688_hw_params, - .hw_free = snd_es1688_hw_free, - .prepare = snd_es1688_capture_prepare, - .trigger = snd_es1688_capture_trigger, - .pointer = snd_es1688_capture_pointer, -}; - -int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, - int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(card, "ESx688", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1688_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1688_capture_ops); - - pcm->private_data = chip; - pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - sprintf(pcm->name, snd_es1688_chip_id(chip)); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, 64*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* - * MIXER part - */ - -static int snd_es1688_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[9] = { - "Mic", "Mic Master", "CD", "AOUT", - "Mic1", "Mix", "Line", "Master" - }; - - 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_es1688_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = snd_es1688_mixer_read(chip, ES1688_REC_DEV) & 7; - return 0; -} - -static int snd_es1688_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval, nval; - int change; - - if (ucontrol->value.enumerated.item[0] > 8) - return -EINVAL; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = snd_es1688_mixer_read(chip, ES1688_REC_DEV); - nval = (ucontrol->value.enumerated.item[0] & 7) | (oval & ~15); - change = nval != oval; - if (change) - snd_es1688_mixer_write(chip, ES1688_REC_DEV, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define ES1688_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es1688_info_single, \ - .get = snd_es1688_get_single, .put = snd_es1688_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_es1688_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (snd_es1688_mixer_read(chip, reg) >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned char oval, nval; - - nval = (ucontrol->value.integer.value[0] & mask); - if (invert) - nval = mask - nval; - nval <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = snd_es1688_mixer_read(chip, reg); - nval = (oval & ~(mask << shift)) | nval; - change = nval != oval; - if (change) - snd_es1688_mixer_write(chip, reg, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define ES1688_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es1688_info_double, \ - .get = snd_es1688_get_double, .put = snd_es1688_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -static int snd_es1688_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - unsigned char left, right; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg < 0xa0) - left = snd_es1688_mixer_read(chip, left_reg); - else - left = snd_es1688_read(chip, left_reg); - if (left_reg != right_reg) { - if (right_reg < 0xa0) - right = snd_es1688_mixer_read(chip, right_reg); - else - right = snd_es1688_read(chip, right_reg); - } else - right = left; - spin_unlock_irqrestore(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (left >> shift_left) & mask; - ucontrol->value.integer.value[1] = (right >> shift_right) & mask; - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned char val1, val2, oval1, oval2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - if (left_reg < 0xa0) - oval1 = snd_es1688_mixer_read(chip, left_reg); - else - oval1 = snd_es1688_read(chip, left_reg); - if (right_reg < 0xa0) - oval2 = snd_es1688_mixer_read(chip, right_reg); - else - oval2 = snd_es1688_read(chip, right_reg); - val1 = (oval1 & ~(mask << shift_left)) | val1; - val2 = (oval2 & ~(mask << shift_right)) | val2; - change = val1 != oval1 || val2 != oval2; - if (change) { - if (left_reg < 0xa0) - snd_es1688_mixer_write(chip, left_reg, val1); - else - snd_es1688_write(chip, left_reg, val1); - if (right_reg < 0xa0) - snd_es1688_mixer_write(chip, right_reg, val1); - else - snd_es1688_write(chip, right_reg, val1); - } - } else { - if (left_reg < 0xa0) - oval1 = snd_es1688_mixer_read(chip, left_reg); - else - oval1 = snd_es1688_read(chip, left_reg); - val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != oval1; - if (change) { - if (left_reg < 0xa0) - snd_es1688_mixer_write(chip, left_reg, val1); - else - snd_es1688_write(chip, left_reg, val1); - } - - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_es1688_controls[] = { -ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0), -ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0), -ES1688_SINGLE("Beep Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0), -ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0), -ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_es1688_info_mux, - .get = snd_es1688_get_mux, - .put = snd_es1688_put_mux, -}, -}; - -#define ES1688_INIT_TABLE_SIZE (sizeof(snd_es1688_init_table)/2) - -static unsigned char snd_es1688_init_table[][2] = { - { ES1688_MASTER_DEV, 0 }, - { ES1688_PCM_DEV, 0 }, - { ES1688_LINE_DEV, 0 }, - { ES1688_CD_DEV, 0 }, - { ES1688_FM_DEV, 0 }, - { ES1688_MIC_DEV, 0 }, - { ES1688_AUX_DEV, 0 }, - { ES1688_SPEAKER_DEV, 0 }, - { ES1688_RECLEV_DEV, 0 }, - { ES1688_REC_DEV, 0x17 } -}; - -int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip) -{ - unsigned int idx; - int err; - unsigned char reg, val; - - if (snd_BUG_ON(!chip || !card)) - return -EINVAL; - - strcpy(card->mixername, snd_es1688_chip_id(chip)); - - for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0) - return err; - } - for (idx = 0; idx < ES1688_INIT_TABLE_SIZE; idx++) { - reg = snd_es1688_init_table[idx][0]; - val = snd_es1688_init_table[idx][1]; - if (reg < 0xa0) - snd_es1688_mixer_write(chip, reg, val); - else - snd_es1688_write(chip, reg, val); - } - return 0; -} - -EXPORT_SYMBOL(snd_es1688_mixer_write); -EXPORT_SYMBOL(snd_es1688_create); -EXPORT_SYMBOL(snd_es1688_pcm); -EXPORT_SYMBOL(snd_es1688_mixer); - -/* - * INIT part - */ - -static int __init alsa_es1688_init(void) -{ - return 0; -} - -static void __exit alsa_es1688_exit(void) -{ -} - -module_init(alsa_es1688_init) -module_exit(alsa_es1688_exit) diff --git a/ANDROID_3.4.5/sound/isa/es18xx.c b/ANDROID_3.4.5/sound/isa/es18xx.c deleted file mode 100644 index c20baafd..00000000 --- a/ANDROID_3.4.5/sound/isa/es18xx.c +++ /dev/null @@ -1,2434 +0,0 @@ -/* - * Driver for generic ESS AudioDrive ES18xx soundcards - * Copyright (c) by Christian Fischbach <fishbach@pool.informatik.rwth-aachen.de> - * Copyright (c) by Abramo Bagnara <abramo@alsa-project.org> - * - * - * 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 - * - */ -/* GENERAL NOTES: - * - * BUGS: - * - There are pops (we can't delay in trigger function, cause midlevel - * often need to trigger down and then up very quickly). - * Any ideas? - * - Support for 16 bit DMA seems to be broken. I've no hardware to tune it. - */ - -/* - * ES1868 NOTES: - * - The chip has one half duplex pcm (with very limited full duplex support). - * - * - Duplex stereophonic sound is impossible. - * - Record and playback must share the same frequency rate. - * - * - The driver use dma2 for playback and dma1 for capture. - */ - -/* - * ES1869 NOTES: - * - * - there are a first full duplex pcm and a second playback only pcm - * (incompatible with first pcm capture) - * - * - there is support for the capture volume and ESS Spatializer 3D effect. - * - * - contrarily to some pages in DS_1869.PDF the rates can be set - * independently. - * - * - Zoom Video is implemented by sharing the FM DAC, thus the user can - * have either FM playback or Video playback but not both simultaneously. - * The Video Playback Switch mixer control toggles this choice. - * - * BUGS: - * - * - There is a major trouble I noted: - * - * using both channel for playback stereo 16 bit samples at 44100 Hz - * the second pcm (Audio1) DMA slows down irregularly and sound is garbled. - * - * The same happens using Audio1 for captureing. - * - * The Windows driver does not suffer of this (although it use Audio1 - * only for captureing). I'm unable to discover why. - * - */ - -/* - * ES1879 NOTES: - * - When Zoom Video is enabled (reg 0x71 bit 6 toggled on) the PCM playback - * seems to be effected (speaker_test plays a lower frequency). Can't find - * anything in the datasheet to account for this, so a Video Playback Switch - * control has been included to allow ZV to be enabled only when necessary. - * Then again on at least one test system the 0x71 bit 6 enable bit is not - * needed for ZV, so maybe the datasheet is entirely wrong here. - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/isa.h> -#include <linux/pnp.h> -#include <linux/isapnp.h> -#include <linux/module.h> -#include <linux/delay.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -#define PFX "es18xx: " - -struct snd_es18xx { - unsigned long port; /* port of ESS chip */ - unsigned long ctrl_port; /* Control port of ESS chip */ - struct resource *res_port; - struct resource *res_mpu_port; - struct resource *res_ctrl_port; - int irq; /* IRQ number of ESS chip */ - int dma1; /* DMA1 */ - int dma2; /* DMA2 */ - unsigned short version; /* version of ESS chip */ - int caps; /* Chip capabilities */ - unsigned short audio2_vol; /* volume level of audio2 */ - - unsigned short active; /* active channel mask */ - unsigned int dma1_shift; - unsigned int dma2_shift; - - struct snd_pcm *pcm; - struct snd_pcm_substream *playback_a_substream; - struct snd_pcm_substream *capture_a_substream; - struct snd_pcm_substream *playback_b_substream; - - struct snd_rawmidi *rmidi; - - struct snd_kcontrol *hw_volume; - struct snd_kcontrol *hw_switch; - struct snd_kcontrol *master_volume; - struct snd_kcontrol *master_switch; - - spinlock_t reg_lock; - spinlock_t mixer_lock; -#ifdef CONFIG_PM - unsigned char pm_reg; -#endif -#ifdef CONFIG_PNP - struct pnp_dev *dev; - struct pnp_dev *devc; -#endif -}; - -#define AUDIO1_IRQ 0x01 -#define AUDIO2_IRQ 0x02 -#define HWV_IRQ 0x04 -#define MPU_IRQ 0x08 - -#define ES18XX_PCM2 0x0001 /* Has two useable PCM */ -#define ES18XX_SPATIALIZER 0x0002 /* Has 3D Spatializer */ -#define ES18XX_RECMIX 0x0004 /* Has record mixer */ -#define ES18XX_DUPLEX_MONO 0x0008 /* Has mono duplex only */ -#define ES18XX_DUPLEX_SAME 0x0010 /* Playback and record must share the same rate */ -#define ES18XX_NEW_RATE 0x0020 /* More precise rate setting */ -#define ES18XX_AUXB 0x0040 /* AuxB mixer control */ -#define ES18XX_HWV 0x0080 /* Has separate hardware volume mixer controls*/ -#define ES18XX_MONO 0x0100 /* Mono_in mixer control */ -#define ES18XX_I2S 0x0200 /* I2S mixer control */ -#define ES18XX_MUTEREC 0x0400 /* Record source can be muted */ -#define ES18XX_CONTROL 0x0800 /* Has control ports */ - -/* Power Management */ -#define ES18XX_PM 0x07 -#define ES18XX_PM_GPO0 0x01 -#define ES18XX_PM_GPO1 0x02 -#define ES18XX_PM_PDR 0x04 -#define ES18XX_PM_ANA 0x08 -#define ES18XX_PM_FM 0x020 -#define ES18XX_PM_SUS 0x080 - -/* Lowlevel */ - -#define DAC1 0x01 -#define ADC1 0x02 -#define DAC2 0x04 -#define MILLISECOND 10000 - -static int snd_es18xx_dsp_command(struct snd_es18xx *chip, unsigned char val) -{ - int i; - - for(i = MILLISECOND; i; i--) - if ((inb(chip->port + 0x0C) & 0x80) == 0) { - outb(val, chip->port + 0x0C); - return 0; - } - snd_printk(KERN_ERR "dsp_command: timeout (0x%x)\n", val); - return -EINVAL; -} - -static int snd_es18xx_dsp_get_byte(struct snd_es18xx *chip) -{ - int i; - - for(i = MILLISECOND/10; i; i--) - if (inb(chip->port + 0x0C) & 0x40) - return inb(chip->port + 0x0A); - snd_printk(KERN_ERR "dsp_get_byte failed: 0x%lx = 0x%x!!!\n", - chip->port + 0x0A, inb(chip->port + 0x0A)); - return -ENODEV; -} - -#undef REG_DEBUG - -static int snd_es18xx_write(struct snd_es18xx *chip, - unsigned char reg, unsigned char data) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&chip->reg_lock, flags); - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_command(chip, data); - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x set to %02x\n", reg, data); -#endif - return ret; -} - -static int snd_es18xx_read(struct snd_es18xx *chip, unsigned char reg) -{ - unsigned long flags; - int ret, data; - spin_lock_irqsave(&chip->reg_lock, flags); - ret = snd_es18xx_dsp_command(chip, 0xC0); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - data = snd_es18xx_dsp_get_byte(chip); - ret = data; -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x now is %02x (%d)\n", reg, data, ret); -#endif - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return ret; -} - -/* Return old value */ -static int snd_es18xx_bits(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - int ret; - unsigned char old, new, oval; - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - ret = snd_es18xx_dsp_command(chip, 0xC0); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - ret = snd_es18xx_dsp_get_byte(chip); - if (ret < 0) { - goto end; - } - old = ret; - oval = old & mask; - if (val != oval) { - ret = snd_es18xx_dsp_command(chip, reg); - if (ret < 0) - goto end; - new = (old & ~mask) | (val & mask); - ret = snd_es18xx_dsp_command(chip, new); - if (ret < 0) - goto end; -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Reg %02x was %02x, set to %02x (%d)\n", - reg, old, new, ret); -#endif - } - ret = oval; - end: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return ret; -} - -static inline void snd_es18xx_mixer_write(struct snd_es18xx *chip, - unsigned char reg, unsigned char data) -{ - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - outb(data, chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x set to %02x\n", reg, data); -#endif -} - -static inline int snd_es18xx_mixer_read(struct snd_es18xx *chip, unsigned char reg) -{ - unsigned long flags; - int data; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - data = inb(chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x now is %02x\n", reg, data); -#endif - return data; -} - -/* Return old value */ -static inline int snd_es18xx_mixer_bits(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - unsigned char old, new, oval; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - old = inb(chip->port + 0x05); - oval = old & mask; - if (val != oval) { - new = (old & ~mask) | (val & mask); - outb(new, chip->port + 0x05); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x\n", - reg, old, new); -#endif - } - spin_unlock_irqrestore(&chip->mixer_lock, flags); - return oval; -} - -static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask) -{ - int old, expected, new; - unsigned long flags; - spin_lock_irqsave(&chip->mixer_lock, flags); - outb(reg, chip->port + 0x04); - old = inb(chip->port + 0x05); - expected = old ^ mask; - outb(expected, chip->port + 0x05); - new = inb(chip->port + 0x05); - spin_unlock_irqrestore(&chip->mixer_lock, flags); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Mixer reg %02x was %02x, set to %02x, now is %02x\n", - reg, old, expected, new); -#endif - return expected == new; -} - - -static int __devinit snd_es18xx_reset(struct snd_es18xx *chip) -{ - int i; - outb(0x03, chip->port + 0x06); - inb(chip->port + 0x06); - outb(0x00, chip->port + 0x06); - for(i = 0; i < MILLISECOND && !(inb(chip->port + 0x0E) & 0x80); i++); - if (inb(chip->port + 0x0A) != 0xAA) - return -1; - return 0; -} - -static int snd_es18xx_reset_fifo(struct snd_es18xx *chip) -{ - outb(0x02, chip->port + 0x06); - inb(chip->port + 0x06); - outb(0x00, chip->port + 0x06); - return 0; -} - -static struct snd_ratnum new_clocks[2] = { - { - .num = 793800, - .den_min = 1, - .den_max = 128, - .den_step = 1, - }, - { - .num = 768000, - .den_min = 1, - .den_max = 128, - .den_step = 1, - } -}; - -static struct snd_pcm_hw_constraint_ratnums new_hw_constraints_clocks = { - .nrats = 2, - .rats = new_clocks, -}; - -static struct snd_ratnum old_clocks[2] = { - { - .num = 795444, - .den_min = 1, - .den_max = 128, - .den_step = 1, - }, - { - .num = 397722, - .den_min = 1, - .den_max = 128, - .den_step = 1, - } -}; - -static struct snd_pcm_hw_constraint_ratnums old_hw_constraints_clocks = { - .nrats = 2, - .rats = old_clocks, -}; - - -static void snd_es18xx_rate_set(struct snd_es18xx *chip, - struct snd_pcm_substream *substream, - int mode) -{ - unsigned int bits, div0; - struct snd_pcm_runtime *runtime = substream->runtime; - if (chip->caps & ES18XX_NEW_RATE) { - if (runtime->rate_num == new_clocks[0].num) - bits = 128 - runtime->rate_den; - else - bits = 256 - runtime->rate_den; - } else { - if (runtime->rate_num == old_clocks[0].num) - bits = 256 - runtime->rate_den; - else - bits = 128 - runtime->rate_den; - } - - /* set filter register */ - div0 = 256 - 7160000*20/(8*82*runtime->rate); - - if ((chip->caps & ES18XX_PCM2) && mode == DAC2) { - snd_es18xx_mixer_write(chip, 0x70, bits); - /* - * Comment from kernel oss driver: - * FKS: fascinating: 0x72 doesn't seem to work. - */ - snd_es18xx_write(chip, 0xA2, div0); - snd_es18xx_mixer_write(chip, 0x72, div0); - } else { - snd_es18xx_write(chip, 0xA1, bits); - snd_es18xx_write(chip, 0xA2, div0); - } -} - -static int snd_es18xx_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - int shift, err; - - shift = 0; - if (params_channels(hw_params) == 2) - shift++; - if (snd_pcm_format_width(params_format(hw_params)) == 16) - shift++; - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) { - if ((chip->caps & ES18XX_DUPLEX_MONO) && - (chip->capture_a_substream) && - params_channels(hw_params) != 1) { - _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS); - return -EBUSY; - } - chip->dma2_shift = shift; - } else { - chip->dma1_shift = shift; - } - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - return 0; -} - -static int snd_es18xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_es18xx_playback1_prepare(struct snd_es18xx *chip, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - snd_es18xx_rate_set(chip, substream, DAC2); - - /* Transfer Count Reload */ - count = 0x10000 - count; - snd_es18xx_mixer_write(chip, 0x74, count & 0xff); - snd_es18xx_mixer_write(chip, 0x76, count >> 8); - - /* Set format */ - snd_es18xx_mixer_bits(chip, 0x7A, 0x07, - ((runtime->channels == 1) ? 0x00 : 0x02) | - (snd_pcm_format_width(runtime->format) == 16 ? 0x01 : 0x00) | - (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x04)); - - /* Set DMA controller */ - snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - - return 0; -} - -static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip, - struct snd_pcm_substream *substream, - int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (chip->active & DAC2) - return 0; - chip->active |= DAC2; - /* Start DMA */ - if (chip->dma2 >= 4) - snd_es18xx_mixer_write(chip, 0x78, 0xb3); - else - snd_es18xx_mixer_write(chip, 0x78, 0x93); -#ifdef AVOID_POPS - /* Avoid pops */ - udelay(100000); - if (chip->caps & ES18XX_PCM2) - /* Restore Audio 2 volume */ - snd_es18xx_mixer_write(chip, 0x7C, chip->audio2_vol); - else - /* Enable PCM output */ - snd_es18xx_dsp_command(chip, 0xD1); -#endif - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (!(chip->active & DAC2)) - return 0; - chip->active &= ~DAC2; - /* Stop DMA */ - snd_es18xx_mixer_write(chip, 0x78, 0x00); -#ifdef AVOID_POPS - udelay(25000); - if (chip->caps & ES18XX_PCM2) - /* Set Audio 2 volume to 0 */ - snd_es18xx_mixer_write(chip, 0x7C, 0); - else - /* Disable PCM output */ - snd_es18xx_dsp_command(chip, 0xD3); -#endif - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_es18xx_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - int shift, err; - - shift = 0; - if ((chip->caps & ES18XX_DUPLEX_MONO) && - chip->playback_a_substream && - params_channels(hw_params) != 1) { - _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS); - return -EBUSY; - } - if (params_channels(hw_params) == 2) - shift++; - if (snd_pcm_format_width(params_format(hw_params)) == 16) - shift++; - chip->dma1_shift = shift; - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - return 0; -} - -static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - snd_es18xx_reset_fifo(chip); - - /* Set stereo/mono */ - snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01); - - snd_es18xx_rate_set(chip, substream, ADC1); - - /* Transfer Count Reload */ - count = 0x10000 - count; - snd_es18xx_write(chip, 0xA4, count & 0xff); - snd_es18xx_write(chip, 0xA5, count >> 8); - -#ifdef AVOID_POPS - udelay(100000); -#endif - - /* Set format */ - snd_es18xx_write(chip, 0xB7, - snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71); - snd_es18xx_write(chip, 0xB7, 0x90 | - ((runtime->channels == 1) ? 0x40 : 0x08) | - (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) | - (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20)); - - /* Set DMA controller */ - snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - - return 0; -} - -static int snd_es18xx_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (chip->active & ADC1) - return 0; - chip->active |= ADC1; - /* Start DMA */ - snd_es18xx_write(chip, 0xB8, 0x0f); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (!(chip->active & ADC1)) - return 0; - chip->active &= ~ADC1; - /* Stop DMA */ - snd_es18xx_write(chip, 0xB8, 0x00); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - snd_es18xx_reset_fifo(chip); - - /* Set stereo/mono */ - snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01); - - snd_es18xx_rate_set(chip, substream, DAC1); - - /* Transfer Count Reload */ - count = 0x10000 - count; - snd_es18xx_write(chip, 0xA4, count & 0xff); - snd_es18xx_write(chip, 0xA5, count >> 8); - - /* Set format */ - snd_es18xx_write(chip, 0xB6, - snd_pcm_format_unsigned(runtime->format) ? 0x80 : 0x00); - snd_es18xx_write(chip, 0xB7, - snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71); - snd_es18xx_write(chip, 0xB7, 0x90 | - (runtime->channels == 1 ? 0x40 : 0x08) | - (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) | - (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20)); - - /* Set DMA controller */ - snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - - return 0; -} - -static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip, - struct snd_pcm_substream *substream, - int cmd) -{ - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - if (chip->active & DAC1) - return 0; - chip->active |= DAC1; - /* Start DMA */ - snd_es18xx_write(chip, 0xB8, 0x05); -#ifdef AVOID_POPS - /* Avoid pops */ - udelay(100000); - /* Enable Audio 1 */ - snd_es18xx_dsp_command(chip, 0xD1); -#endif - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - if (!(chip->active & DAC1)) - return 0; - chip->active &= ~DAC1; - /* Stop DMA */ - snd_es18xx_write(chip, 0xB8, 0x00); -#ifdef AVOID_POPS - /* Avoid pops */ - udelay(25000); - /* Disable Audio 1 */ - snd_es18xx_dsp_command(chip, 0xD3); -#endif - break; - default: - return -EINVAL; - } - - return 0; -} - -static int snd_es18xx_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) - return snd_es18xx_playback1_prepare(chip, substream); - else - return snd_es18xx_playback2_prepare(chip, substream); -} - -static int snd_es18xx_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) - return snd_es18xx_playback1_trigger(chip, substream, cmd); - else - return snd_es18xx_playback2_trigger(chip, substream, cmd); -} - -static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id) -{ - struct snd_card *card = dev_id; - struct snd_es18xx *chip = card->private_data; - unsigned char status; - - if (chip->caps & ES18XX_CONTROL) { - /* Read Interrupt status */ - status = inb(chip->ctrl_port + 6); - } else { - /* Read Interrupt status */ - status = snd_es18xx_mixer_read(chip, 0x7f) >> 4; - } -#if 0 - else { - status = 0; - if (inb(chip->port + 0x0C) & 0x01) - status |= AUDIO1_IRQ; - if (snd_es18xx_mixer_read(chip, 0x7A) & 0x80) - status |= AUDIO2_IRQ; - if ((chip->caps & ES18XX_HWV) && - snd_es18xx_mixer_read(chip, 0x64) & 0x10) - status |= HWV_IRQ; - } -#endif - - /* Audio 1 & Audio 2 */ - if (status & AUDIO2_IRQ) { - if (chip->active & DAC2) - snd_pcm_period_elapsed(chip->playback_a_substream); - /* ack interrupt */ - snd_es18xx_mixer_bits(chip, 0x7A, 0x80, 0x00); - } - if (status & AUDIO1_IRQ) { - /* ok.. capture is active */ - if (chip->active & ADC1) - snd_pcm_period_elapsed(chip->capture_a_substream); - /* ok.. playback2 is active */ - else if (chip->active & DAC1) - snd_pcm_period_elapsed(chip->playback_b_substream); - /* ack interrupt */ - inb(chip->port + 0x0E); - } - - /* MPU */ - if ((status & MPU_IRQ) && chip->rmidi) - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - - /* Hardware volume */ - if (status & HWV_IRQ) { - int split = 0; - if (chip->caps & ES18XX_HWV) { - split = snd_es18xx_mixer_read(chip, 0x64) & 0x80; - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hw_switch->id); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->hw_volume->id); - } - if (!split) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_switch->id); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - } - /* ack interrupt */ - snd_es18xx_mixer_write(chip, 0x66, 0x00); - } - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - int pos; - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) { - if (!(chip->active & DAC2)) - return 0; - pos = snd_dma_pointer(chip->dma2, size); - return pos >> chip->dma2_shift; - } else { - if (!(chip->active & DAC1)) - return 0; - pos = snd_dma_pointer(chip->dma1, size); - return pos >> chip->dma1_shift; - } -} - -static snd_pcm_uframes_t snd_es18xx_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - int pos; - - if (!(chip->active & ADC1)) - return 0; - pos = snd_dma_pointer(chip->dma1, size); - return pos >> chip->dma1_shift; -} - -static struct snd_pcm_hardware snd_es18xx_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_es18xx_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static int snd_es18xx_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) { - if ((chip->caps & ES18XX_DUPLEX_MONO) && - chip->capture_a_substream && - chip->capture_a_substream->runtime->channels != 1) - return -EAGAIN; - chip->playback_a_substream = substream; - } else if (substream->number <= 1) { - if (chip->capture_a_substream) - return -EAGAIN; - chip->playback_b_substream = substream; - } else { - snd_BUG(); - return -EINVAL; - } - substream->runtime->hw = snd_es18xx_playback; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks); - return 0; -} - -static int snd_es18xx_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - if (chip->playback_b_substream) - return -EAGAIN; - if ((chip->caps & ES18XX_DUPLEX_MONO) && - chip->playback_a_substream && - chip->playback_a_substream->runtime->channels != 1) - return -EAGAIN; - chip->capture_a_substream = substream; - substream->runtime->hw = snd_es18xx_capture; - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks); - return 0; -} - -static int snd_es18xx_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) - chip->playback_a_substream = NULL; - else - chip->playback_b_substream = NULL; - - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_es18xx_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_es18xx *chip = snd_pcm_substream_chip(substream); - - chip->capture_a_substream = NULL; - snd_pcm_lib_free_pages(substream); - return 0; -} - -/* - * MIXER part - */ - -/* Record source mux routines: - * Depending on the chipset this mux switches between 4, 5, or 8 possible inputs. - * bit table for the 4/5 source mux: - * reg 1C: - * b2 b1 b0 muxSource - * x 0 x microphone - * 0 1 x CD - * 1 1 0 line - * 1 1 1 mixer - * if it's "mixer" and it's a 5 source mux chipset then reg 7A bit 3 determines - * either the play mixer or the capture mixer. - * - * "map4Source" translates from source number to reg bit pattern - * "invMap4Source" translates from reg bit pattern to source number - */ - -static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts5Source[5] = { - "Mic", "CD", "Line", "Master", "Mix" - }; - static char *texts8Source[8] = { - "Mic", "Mic Master", "CD", "AOUT", - "Mic1", "Mix", "Line", "Master" - }; - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - switch (chip->version) { - case 0x1868: - case 0x1878: - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, - texts5Source[uinfo->value.enumerated.item]); - break; - case 0x1887: - case 0x1888: - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, texts5Source[uinfo->value.enumerated.item]); - break; - case 0x1869: /* DS somewhat contradictory for 1869: could be be 5 or 8 */ - case 0x1879: - uinfo->value.enumerated.items = 8; - if (uinfo->value.enumerated.item > 7) - uinfo->value.enumerated.item = 7; - strcpy(uinfo->value.enumerated.name, texts8Source[uinfo->value.enumerated.item]); - break; - default: - return -EINVAL; - } - return 0; -} - -static int snd_es18xx_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - static unsigned char invMap4Source[8] = {0, 0, 1, 1, 0, 0, 2, 3}; - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int muxSource = snd_es18xx_mixer_read(chip, 0x1c) & 0x07; - if (!(chip->version == 0x1869 || chip->version == 0x1879)) { - muxSource = invMap4Source[muxSource]; - if (muxSource==3 && - (chip->version == 0x1887 || chip->version == 0x1888) && - (snd_es18xx_mixer_read(chip, 0x7a) & 0x08) - ) - muxSource = 4; - } - ucontrol->value.enumerated.item[0] = muxSource; - return 0; -} - -static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - static unsigned char map4Source[4] = {0, 2, 6, 7}; - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - unsigned char val = ucontrol->value.enumerated.item[0]; - unsigned char retVal = 0; - - switch (chip->version) { - /* 5 source chips */ - case 0x1887: - case 0x1888: - if (val > 4) - return -EINVAL; - if (val == 4) { - retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x08) != 0x08; - val = 3; - } else - retVal = snd_es18xx_mixer_bits(chip, 0x7a, 0x08, 0x00) != 0x00; - /* 4 source chips */ - case 0x1868: - case 0x1878: - if (val > 3) - return -EINVAL; - val = map4Source[val]; - break; - /* 8 source chips */ - case 0x1869: - case 0x1879: - if (val > 7) - return -EINVAL; - break; - default: - return -EINVAL; - } - return (snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val) || retVal; -} - -#define snd_es18xx_info_spatializer_enable snd_ctl_boolean_mono_info - -static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - unsigned char val = snd_es18xx_mixer_read(chip, 0x50); - ucontrol->value.integer.value[0] = !!(val & 8); - return 0; -} - -static int snd_es18xx_put_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - unsigned char oval, nval; - int change; - nval = ucontrol->value.integer.value[0] ? 0x0c : 0x04; - oval = snd_es18xx_mixer_read(chip, 0x50) & 0x0c; - change = nval != oval; - if (change) { - snd_es18xx_mixer_write(chip, 0x50, nval & ~0x04); - snd_es18xx_mixer_write(chip, 0x50, nval); - } - return change; -} - -static int snd_es18xx_info_hw_volume(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 = 63; - return 0; -} - -static int snd_es18xx_get_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = snd_es18xx_mixer_read(chip, 0x61) & 0x3f; - ucontrol->value.integer.value[1] = snd_es18xx_mixer_read(chip, 0x63) & 0x3f; - return 0; -} - -#define snd_es18xx_info_hw_switch snd_ctl_boolean_stereo_info - -static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = !(snd_es18xx_mixer_read(chip, 0x61) & 0x40); - ucontrol->value.integer.value[1] = !(snd_es18xx_mixer_read(chip, 0x63) & 0x40); - return 0; -} - -static void snd_es18xx_hwv_free(struct snd_kcontrol *kcontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - chip->master_volume = NULL; - chip->master_switch = NULL; - chip->hw_volume = NULL; - chip->hw_switch = NULL; -} - -static int snd_es18xx_reg_bits(struct snd_es18xx *chip, unsigned char reg, - unsigned char mask, unsigned char val) -{ - if (reg < 0xa0) - return snd_es18xx_mixer_bits(chip, reg, mask, val); - else - return snd_es18xx_bits(chip, reg, mask, val); -} - -static int snd_es18xx_reg_read(struct snd_es18xx *chip, unsigned char reg) -{ - if (reg < 0xa0) - return snd_es18xx_mixer_read(chip, reg); - else - return snd_es18xx_read(chip, reg); -} - -#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es18xx_info_single, \ - .get = snd_es18xx_get_single, .put = snd_es18xx_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -static int snd_es18xx_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es18xx_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int val; - - val = snd_es18xx_reg_read(chip, reg); - ucontrol->value.integer.value[0] = (val >> shift) & mask; - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_es18xx_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - unsigned char val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - mask <<= shift; - val <<= shift; - return snd_es18xx_reg_bits(chip, reg, mask, val) != val; -} - -#define ES18XX_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_es18xx_info_double, \ - .get = snd_es18xx_get_double, .put = snd_es18xx_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } - -static int snd_es18xx_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_es18xx_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - unsigned char left, right; - - left = snd_es18xx_reg_read(chip, left_reg); - if (left_reg != right_reg) - right = snd_es18xx_reg_read(chip, right_reg); - else - right = left; - ucontrol->value.integer.value[0] = (left >> shift_left) & mask; - ucontrol->value.integer.value[1] = (right >> shift_right) & mask; - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_es18xx_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol); - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned char val1, val2, mask1, mask2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - mask1 = mask << shift_left; - mask2 = mask << shift_right; - if (left_reg != right_reg) { - change = 0; - if (snd_es18xx_reg_bits(chip, left_reg, mask1, val1) != val1) - change = 1; - if (snd_es18xx_reg_bits(chip, right_reg, mask2, val2) != val2) - change = 1; - } else { - change = (snd_es18xx_reg_bits(chip, left_reg, mask1 | mask2, - val1 | val2) != (val1 | val2)); - } - return change; -} - -/* Mixer controls - * These arrays contain setup data for mixer controls. - * - * The controls that are universal to all chipsets are fully initialized - * here. - */ -static struct snd_kcontrol_new snd_es18xx_base_controls[] = { -ES18XX_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0), -ES18XX_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), -ES18XX_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0), -ES18XX_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0), -ES18XX_DOUBLE("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0), -ES18XX_DOUBLE("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0), -ES18XX_DOUBLE("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0), -ES18XX_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0), -ES18XX_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_es18xx_info_mux, - .get = snd_es18xx_get_mux, - .put = snd_es18xx_put_mux, -} -}; - -static struct snd_kcontrol_new snd_es18xx_recmix_controls[] = { -ES18XX_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0), -ES18XX_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0), -ES18XX_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0), -ES18XX_DOUBLE("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0), -ES18XX_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0), -ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0) -}; - -/* - * The chipset specific mixer controls - */ -static struct snd_kcontrol_new snd_es18xx_opt_speaker = - ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0); - -static struct snd_kcontrol_new snd_es18xx_opt_1869[] = { -ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), -ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0), -ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), -ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0) -}; - -static struct snd_kcontrol_new snd_es18xx_opt_1878 = - ES18XX_DOUBLE("Video Playback Volume", 0, 0x68, 0x68, 4, 0, 15, 0); - -static struct snd_kcontrol_new snd_es18xx_opt_1879[] = { -ES18XX_SINGLE("Video Playback Switch", 0, 0x71, 6, 1, 0), -ES18XX_DOUBLE("Video Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), -ES18XX_DOUBLE("Video Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0) -}; - -static struct snd_kcontrol_new snd_es18xx_pcm1_controls[] = { -ES18XX_DOUBLE("PCM Playback Volume", 0, 0x14, 0x14, 4, 0, 15, 0), -}; - -static struct snd_kcontrol_new snd_es18xx_pcm2_controls[] = { -ES18XX_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0), -ES18XX_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0) -}; - -static struct snd_kcontrol_new snd_es18xx_spatializer_controls[] = { -ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Switch", - .info = snd_es18xx_info_spatializer_enable, - .get = snd_es18xx_get_spatializer_enable, - .put = snd_es18xx_put_spatializer_enable, -} -}; - -static struct snd_kcontrol_new snd_es18xx_micpre1_control = -ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0xa9, 2, 1, 0); - -static struct snd_kcontrol_new snd_es18xx_micpre2_control = -ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0); - -static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Hardware Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_es18xx_info_hw_volume, - .get = snd_es18xx_get_hw_volume, -}, -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Hardware Master Playback Switch", - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = snd_es18xx_info_hw_switch, - .get = snd_es18xx_get_hw_switch, -}, -ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0), -}; - -static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg) -{ - int data; - - outb(reg, chip->ctrl_port); - data = inb(chip->ctrl_port + 1); - return data; -} - -static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip, - unsigned char reg, unsigned char data) -{ - /* No need for spinlocks, this function is used only in - otherwise protected init code */ - outb(reg, chip->ctrl_port); - outb(data, chip->ctrl_port + 1); -#ifdef REG_DEBUG - snd_printk(KERN_DEBUG "Config reg %02x set to %02x\n", reg, data); -#endif -} - -static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip, - unsigned long mpu_port, - unsigned long fm_port) -{ - int mask = 0; - - /* enable extended mode */ - snd_es18xx_dsp_command(chip, 0xC6); - /* Reset mixer registers */ - snd_es18xx_mixer_write(chip, 0x00, 0x00); - - /* Audio 1 DMA demand mode (4 bytes/request) */ - snd_es18xx_write(chip, 0xB9, 2); - if (chip->caps & ES18XX_CONTROL) { - /* Hardware volume IRQ */ - snd_es18xx_config_write(chip, 0x27, chip->irq); - if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { - /* FM I/O */ - snd_es18xx_config_write(chip, 0x62, fm_port >> 8); - snd_es18xx_config_write(chip, 0x63, fm_port & 0xff); - } - if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) { - /* MPU-401 I/O */ - snd_es18xx_config_write(chip, 0x64, mpu_port >> 8); - snd_es18xx_config_write(chip, 0x65, mpu_port & 0xff); - /* MPU-401 IRQ */ - snd_es18xx_config_write(chip, 0x28, chip->irq); - } - /* Audio1 IRQ */ - snd_es18xx_config_write(chip, 0x70, chip->irq); - /* Audio2 IRQ */ - snd_es18xx_config_write(chip, 0x72, chip->irq); - /* Audio1 DMA */ - snd_es18xx_config_write(chip, 0x74, chip->dma1); - /* Audio2 DMA */ - snd_es18xx_config_write(chip, 0x75, chip->dma2); - - /* Enable Audio 1 IRQ */ - snd_es18xx_write(chip, 0xB1, 0x50); - /* Enable Audio 2 IRQ */ - snd_es18xx_mixer_write(chip, 0x7A, 0x40); - /* Enable Audio 1 DMA */ - snd_es18xx_write(chip, 0xB2, 0x50); - /* Enable MPU and hardware volume interrupt */ - snd_es18xx_mixer_write(chip, 0x64, 0x42); - /* Enable ESS wavetable input */ - snd_es18xx_mixer_bits(chip, 0x48, 0x10, 0x10); - } - else { - int irqmask, dma1mask, dma2mask; - switch (chip->irq) { - case 2: - case 9: - irqmask = 0; - break; - case 5: - irqmask = 1; - break; - case 7: - irqmask = 2; - break; - case 10: - irqmask = 3; - break; - default: - snd_printk(KERN_ERR "invalid irq %d\n", chip->irq); - return -ENODEV; - } - switch (chip->dma1) { - case 0: - dma1mask = 1; - break; - case 1: - dma1mask = 2; - break; - case 3: - dma1mask = 3; - break; - default: - snd_printk(KERN_ERR "invalid dma1 %d\n", chip->dma1); - return -ENODEV; - } - switch (chip->dma2) { - case 0: - dma2mask = 0; - break; - case 1: - dma2mask = 1; - break; - case 3: - dma2mask = 2; - break; - case 5: - dma2mask = 3; - break; - default: - snd_printk(KERN_ERR "invalid dma2 %d\n", chip->dma2); - return -ENODEV; - } - - /* Enable and set Audio 1 IRQ */ - snd_es18xx_write(chip, 0xB1, 0x50 | (irqmask << 2)); - /* Enable and set Audio 1 DMA */ - snd_es18xx_write(chip, 0xB2, 0x50 | (dma1mask << 2)); - /* Set Audio 2 DMA */ - snd_es18xx_mixer_bits(chip, 0x7d, 0x07, 0x04 | dma2mask); - /* Enable Audio 2 IRQ and DMA - Set capture mixer input */ - snd_es18xx_mixer_write(chip, 0x7A, 0x68); - /* Enable and set hardware volume interrupt */ - snd_es18xx_mixer_write(chip, 0x64, 0x06); - if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) { - /* MPU401 share irq with audio - Joystick enabled - FM enabled */ - snd_es18xx_mixer_write(chip, 0x40, - 0x43 | (mpu_port & 0xf0) >> 1); - } - snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01); - } - if (chip->caps & ES18XX_NEW_RATE) { - /* Change behaviour of register A1 - 4x oversampling - 2nd channel DAC asynchronous */ - snd_es18xx_mixer_write(chip, 0x71, 0x32); - } - if (!(chip->caps & ES18XX_PCM2)) { - /* Enable DMA FIFO */ - snd_es18xx_write(chip, 0xB7, 0x80); - } - if (chip->caps & ES18XX_SPATIALIZER) { - /* Set spatializer parameters to recommended values */ - snd_es18xx_mixer_write(chip, 0x54, 0x8f); - snd_es18xx_mixer_write(chip, 0x56, 0x95); - snd_es18xx_mixer_write(chip, 0x58, 0x94); - snd_es18xx_mixer_write(chip, 0x5a, 0x80); - } - /* Flip the "enable I2S" bits for those chipsets that need it */ - switch (chip->version) { - case 0x1879: - //Leaving I2S enabled on the 1879 screws up the PCM playback (rate effected somehow) - //so a Switch control has been added to toggle this 0x71 bit on/off: - //snd_es18xx_mixer_bits(chip, 0x71, 0x40, 0x40); - /* Note: we fall through on purpose here. */ - case 0x1878: - snd_es18xx_config_write(chip, 0x29, snd_es18xx_config_read(chip, 0x29) | 0x40); - break; - } - /* Mute input source */ - if (chip->caps & ES18XX_MUTEREC) - mask = 0x10; - if (chip->caps & ES18XX_RECMIX) - snd_es18xx_mixer_write(chip, 0x1c, 0x05 | mask); - else { - snd_es18xx_mixer_write(chip, 0x1c, 0x00 | mask); - snd_es18xx_write(chip, 0xb4, 0x00); - } -#ifndef AVOID_POPS - /* Enable PCM output */ - snd_es18xx_dsp_command(chip, 0xD1); -#endif - - return 0; -} - -static int __devinit snd_es18xx_identify(struct snd_es18xx *chip) -{ - int hi,lo; - - /* reset */ - if (snd_es18xx_reset(chip) < 0) { - snd_printk(KERN_ERR "reset at 0x%lx failed!!!\n", chip->port); - return -ENODEV; - } - - snd_es18xx_dsp_command(chip, 0xe7); - hi = snd_es18xx_dsp_get_byte(chip); - if (hi < 0) { - return hi; - } - lo = snd_es18xx_dsp_get_byte(chip); - if ((lo & 0xf0) != 0x80) { - return -ENODEV; - } - if (hi == 0x48) { - chip->version = 0x488; - return 0; - } - if (hi != 0x68) { - return -ENODEV; - } - if ((lo & 0x0f) < 8) { - chip->version = 0x688; - return 0; - } - - outb(0x40, chip->port + 0x04); - udelay(10); - hi = inb(chip->port + 0x05); - udelay(10); - lo = inb(chip->port + 0x05); - if (hi != lo) { - chip->version = hi << 8 | lo; - chip->ctrl_port = inb(chip->port + 0x05) << 8; - udelay(10); - chip->ctrl_port += inb(chip->port + 0x05); - - if ((chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL")) == NULL) { - snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port); - return -EBUSY; - } - - return 0; - } - - /* If has Hardware volume */ - if (snd_es18xx_mixer_writable(chip, 0x64, 0x04)) { - /* If has Audio2 */ - if (snd_es18xx_mixer_writable(chip, 0x70, 0x7f)) { - /* If has volume count */ - if (snd_es18xx_mixer_writable(chip, 0x64, 0x20)) { - chip->version = 0x1887; - } else { - chip->version = 0x1888; - } - } else { - chip->version = 0x1788; - } - } - else - chip->version = 0x1688; - return 0; -} - -static int __devinit snd_es18xx_probe(struct snd_es18xx *chip, - unsigned long mpu_port, - unsigned long fm_port) -{ - if (snd_es18xx_identify(chip) < 0) { - snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port); - return -ENODEV; - } - - switch (chip->version) { - case 0x1868: - chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_CONTROL; - break; - case 0x1869: - chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL | ES18XX_HWV; - break; - case 0x1878: - chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_I2S | ES18XX_CONTROL; - break; - case 0x1879: - chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV; - break; - case 0x1887: - case 0x1888: - chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME; - break; - default: - snd_printk(KERN_ERR "[0x%lx] unsupported chip ES%x\n", - chip->port, chip->version); - return -ENODEV; - } - - snd_printd("[0x%lx] ESS%x chip found\n", chip->port, chip->version); - - if (chip->dma1 == chip->dma2) - chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME); - - return snd_es18xx_initialize(chip, mpu_port, fm_port); -} - -static struct snd_pcm_ops snd_es18xx_playback_ops = { - .open = snd_es18xx_playback_open, - .close = snd_es18xx_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es18xx_playback_hw_params, - .hw_free = snd_es18xx_pcm_hw_free, - .prepare = snd_es18xx_playback_prepare, - .trigger = snd_es18xx_playback_trigger, - .pointer = snd_es18xx_playback_pointer, -}; - -static struct snd_pcm_ops snd_es18xx_capture_ops = { - .open = snd_es18xx_capture_open, - .close = snd_es18xx_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_es18xx_capture_hw_params, - .hw_free = snd_es18xx_pcm_hw_free, - .prepare = snd_es18xx_capture_prepare, - .trigger = snd_es18xx_capture_trigger, - .pointer = snd_es18xx_capture_pointer, -}; - -static int __devinit snd_es18xx_pcm(struct snd_card *card, int device, - struct snd_pcm **rpcm) -{ - struct snd_es18xx *chip = card->private_data; - struct snd_pcm *pcm; - char str[16]; - int err; - - if (rpcm) - *rpcm = NULL; - sprintf(str, "ES%x", chip->version); - if (chip->caps & ES18XX_PCM2) - err = snd_pcm_new(card, str, device, 2, 1, &pcm); - else - err = snd_pcm_new(card, str, device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es18xx_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es18xx_capture_ops); - - /* global setup */ - pcm->private_data = chip; - pcm->info_flags = 0; - if (chip->caps & ES18XX_DUPLEX_SAME) - pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX; - if (! (chip->caps & ES18XX_PCM2)) - pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX; - sprintf(pcm->name, "ESS AudioDrive ES%x", chip->version); - chip->pcm = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, - chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -/* Power Management support functions */ -#ifdef CONFIG_PM -static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state) -{ - struct snd_es18xx *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - snd_pcm_suspend_all(chip->pcm); - - /* power down */ - chip->pm_reg = (unsigned char)snd_es18xx_read(chip, ES18XX_PM); - chip->pm_reg |= (ES18XX_PM_FM | ES18XX_PM_SUS); - snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg); - snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_SUS); - - return 0; -} - -static int snd_es18xx_resume(struct snd_card *card) -{ - struct snd_es18xx *chip = card->private_data; - - /* restore PM register, we won't wake till (not 0x07) i/o activity though */ - snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -static int snd_es18xx_free(struct snd_card *card) -{ - struct snd_es18xx *chip = card->private_data; - - release_and_free_resource(chip->res_port); - release_and_free_resource(chip->res_ctrl_port); - release_and_free_resource(chip->res_mpu_port); - if (chip->irq >= 0) - free_irq(chip->irq, (void *) card); - if (chip->dma1 >= 0) { - disable_dma(chip->dma1); - free_dma(chip->dma1); - } - if (chip->dma2 >= 0 && chip->dma1 != chip->dma2) { - disable_dma(chip->dma2); - free_dma(chip->dma2); - } - return 0; -} - -static int snd_es18xx_dev_free(struct snd_device *device) -{ - return snd_es18xx_free(device->card); -} - -static int __devinit snd_es18xx_new_device(struct snd_card *card, - unsigned long port, - unsigned long mpu_port, - unsigned long fm_port, - int irq, int dma1, int dma2) -{ - struct snd_es18xx *chip = card->private_data; - static struct snd_device_ops ops = { - .dev_free = snd_es18xx_dev_free, - }; - int err; - - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->mixer_lock); - chip->port = port; - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - chip->audio2_vol = 0x00; - chip->active = 0; - - chip->res_port = request_region(port, 16, "ES18xx"); - if (chip->res_port == NULL) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1); - return -EBUSY; - } - - if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx", - (void *) card)) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq); - return -EBUSY; - } - chip->irq = irq; - - if (request_dma(dma1, "ES18xx DMA 1")) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1); - return -EBUSY; - } - chip->dma1 = dma1; - - if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) { - snd_es18xx_free(card); - snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2); - return -EBUSY; - } - chip->dma2 = dma2; - - if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) { - snd_es18xx_free(card); - return -ENODEV; - } - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_es18xx_free(card); - return err; - } - return 0; -} - -static int __devinit snd_es18xx_mixer(struct snd_card *card) -{ - struct snd_es18xx *chip = card->private_data; - int err; - unsigned int idx; - - strcpy(card->mixername, chip->pcm->name); - - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(&snd_es18xx_base_controls[idx], chip); - if (chip->caps & ES18XX_HWV) { - switch (idx) { - case 0: - chip->master_volume = kctl; - kctl->private_free = snd_es18xx_hwv_free; - break; - case 1: - chip->master_switch = kctl; - kctl->private_free = snd_es18xx_hwv_free; - break; - } - } - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - } - if (chip->caps & ES18XX_PCM2) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm2_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm2_controls[idx], chip))) < 0) - return err; - } - } else { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm1_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm1_controls[idx], chip))) < 0) - return err; - } - } - - if (chip->caps & ES18XX_RECMIX) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_recmix_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_recmix_controls[idx], chip))) < 0) - return err; - } - } - switch (chip->version) { - default: - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre1_control, chip))) < 0) - return err; - break; - case 0x1869: - case 0x1879: - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre2_control, chip))) < 0) - return err; - break; - } - if (chip->caps & ES18XX_SPATIALIZER) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_spatializer_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_spatializer_controls[idx], chip))) < 0) - return err; - } - } - if (chip->caps & ES18XX_HWV) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_hw_volume_controls); idx++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(&snd_es18xx_hw_volume_controls[idx], chip); - if (idx == 0) - chip->hw_volume = kctl; - else - chip->hw_switch = kctl; - kctl->private_free = snd_es18xx_hwv_free; - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - - } - } - /* finish initializing other chipset specific controls - */ - if (chip->version != 0x1868) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_opt_speaker, - chip)); - if (err < 0) - return err; - } - if (chip->version == 0x1869) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_opt_1869); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_es18xx_opt_1869[idx], - chip)); - if (err < 0) - return err; - } - } else if (chip->version == 0x1878) { - err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_opt_1878, - chip)); - if (err < 0) - return err; - } else if (chip->version == 0x1879) { - for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_opt_1879); idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_es18xx_opt_1879[idx], - chip)); - if (err < 0) - return err; - } - } - return 0; -} - - -/* Card level */ - -MODULE_AUTHOR("Christian Fischbach <fishbach@pool.informatik.rwth-aachen.de>, Abramo Bagnara <abramo@alsa-project.org>"); -MODULE_DESCRIPTION("ESS ES18xx AudioDrive"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESS,ES1868 PnP AudioDrive}," - "{ESS,ES1869 PnP AudioDrive}," - "{ESS,ES1878 PnP AudioDrive}," - "{ESS,ES1879 PnP AudioDrive}," - "{ESS,ES1887 PnP AudioDrive}," - "{ESS,ES1888 PnP AudioDrive}," - "{ESS,ES1887 AudioDrive}," - "{ESS,ES1888 AudioDrive}}"); - -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_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */ -#ifndef CONFIG_PNP -static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1}; -#else -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -#endif -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for ES18xx soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for ES18xx soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable ES18xx soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for ES18xx driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ES18xx driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for ES18xx driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for ES18xx driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -static int pnpc_registered; - -static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { - { .id = "ESS1869" }, - { .id = "ESS1879" }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids); - -/* PnP main device initialization */ -static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n"); - return -EBUSY; - } - /* ok. hack using Vendor-Defined Card-Level registers */ - /* skip csn and logdev initialization - already done in isapnp_configure */ - if (pnp_device_is_isapnp(pdev)) { - isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev)); - isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */ - if (mpu_port[dev] != SNDRV_AUTO_PORT) - isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */ - isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */ - isapnp_cfg_end(); - } - port[dev] = pnp_port_start(pdev, 0); - fm_port[dev] = pnp_port_start(pdev, 1); - mpu_port[dev] = pnp_port_start(pdev, 2); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]); - snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); - return 0; -} - -static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip, - struct pnp_dev *pdev) -{ - chip->dev = pdev; - if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0) - return -EBUSY; - return 0; -} - -static struct pnp_card_device_id snd_audiodrive_pnpids[] = { - /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */ - { .id = "ESS1868", .devs = { { "ESS1868" }, { "ESS0000" } } }, - /* ESS 1868 (integrated on Maxisound Cards) */ - { .id = "ESS1868", .devs = { { "ESS8601" }, { "ESS8600" } } }, - /* ESS 1868 (integrated on Maxisound Cards) */ - { .id = "ESS1868", .devs = { { "ESS8611" }, { "ESS8610" } } }, - /* ESS ES1869 Plug and Play AudioDrive */ - { .id = "ESS0003", .devs = { { "ESS1869" }, { "ESS0006" } } }, - /* ESS 1869 */ - { .id = "ESS1869", .devs = { { "ESS1869" }, { "ESS0006" } } }, - /* ESS 1878 */ - { .id = "ESS1878", .devs = { { "ESS1878" }, { "ESS0004" } } }, - /* ESS 1879 */ - { .id = "ESS1879", .devs = { { "ESS1879" }, { "ESS0009" } } }, - /* --- */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids); - -static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (chip->dev == NULL) - return -EBUSY; - - chip->devc = pnp_request_card_device(card, id->devs[1].id, NULL); - if (chip->devc == NULL) - return -EBUSY; - - /* Control port initialization */ - if (pnp_activate_dev(chip->devc) < 0) { - snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); - return -EAGAIN; - } - snd_printdd("pnp: port=0x%llx\n", - (unsigned long long)pnp_port_start(chip->devc, 0)); - if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0) - return -EBUSY; - - return 0; -} -#endif /* CONFIG_PNP */ - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static int snd_es18xx_card_new(int dev, struct snd_card **cardp) -{ - return snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_es18xx), cardp); -} - -static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) -{ - struct snd_es18xx *chip = card->private_data; - struct snd_opl3 *opl3; - int err; - - err = snd_es18xx_new_device(card, - port[dev], mpu_port[dev], fm_port[dev], - irq[dev], dma1[dev], dma2[dev]); - if (err < 0) - return err; - - sprintf(card->driver, "ES%x", chip->version); - - sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version); - if (dma1[dev] != dma2[dev]) - sprintf(card->longname, "%s at 0x%lx, irq %d, dma1 %d, dma2 %d", - card->shortname, - chip->port, - irq[dev], dma1[dev], dma2[dev]); - else - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - card->shortname, - chip->port, - irq[dev], dma1[dev]); - - err = snd_es18xx_pcm(card, 0, NULL); - if (err < 0) - return err; - - err = snd_es18xx_mixer(card); - if (err < 0) - return err; - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) { - snd_printk(KERN_WARNING PFX - "opl3 not detected at 0x%lx\n", - fm_port[dev]); - } else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - return err; - } - } - - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX, - mpu_port[dev], MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi); - if (err < 0) - return err; - } - - return snd_card_register(card); -} - -static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev) -{ - return enable[dev] && !is_isapnp_selected(dev); -} - -static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr) -{ - struct snd_card *card; - int err; - - err = snd_es18xx_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, devptr); - if ((err = snd_audiodrive_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev) -{ - int err; - static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1}; - static int possible_dmas[] = {1, 0, 3, 5, -1}; - - if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2[dev] == SNDRV_AUTO_DMA) { - if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) { - return snd_es18xx_isa_probe1(dev, pdev); - } else { - static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280}; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - port[dev] = possible_ports[i]; - err = snd_es18xx_isa_probe1(dev, pdev); - if (! err) - return 0; - } - return err; - } -} - -static int __devexit snd_es18xx_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_es18xx_suspend(dev_get_drvdata(dev), state); -} - -static int snd_es18xx_isa_resume(struct device *dev, unsigned int n) -{ - return snd_es18xx_resume(dev_get_drvdata(dev)); -} -#endif - -#define DEV_NAME "es18xx" - -static struct isa_driver snd_es18xx_isa_driver = { - .match = snd_es18xx_isa_match, - .probe = snd_es18xx_isa_probe, - .remove = __devexit_p(snd_es18xx_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_es18xx_isa_suspend, - .resume = snd_es18xx_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, - const struct pnp_device_id *id) -{ - static int dev; - int err; - struct snd_card *card; - - if (pnp_device_is_isapnp(pdev)) - return -ENOENT; /* we have another procedure - card */ - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - err = snd_es18xx_card_new(dev, &card); - if (err < 0) - return err; - if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_audiodrive_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_drvdata(pdev, card); - dev++; - return 0; -} - -static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev) -{ - snd_card_free(pnp_get_drvdata(pdev)); - pnp_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM -static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - return snd_es18xx_suspend(pnp_get_drvdata(pdev), state); -} -static int snd_audiodrive_pnp_resume(struct pnp_dev *pdev) -{ - return snd_es18xx_resume(pnp_get_drvdata(pdev)); -} -#endif - -static struct pnp_driver es18xx_pnp_driver = { - .name = "es18xx-pnpbios", - .id_table = snd_audiodrive_pnpbiosids, - .probe = snd_audiodrive_pnp_detect, - .remove = __devexit_p(snd_audiodrive_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_audiodrive_pnp_suspend, - .resume = snd_audiodrive_pnp_resume, -#endif -}; - -static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_es18xx_card_new(dev, &card); - if (res < 0) - return res; - - if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_audiodrive_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state); -} - -static int snd_audiodrive_pnpc_resume(struct pnp_card_link *pcard) -{ - return snd_es18xx_resume(pnp_get_card_drvdata(pcard)); -} - -#endif - -static struct pnp_card_driver es18xx_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "es18xx", - .id_table = snd_audiodrive_pnpids, - .probe = snd_audiodrive_pnpc_detect, - .remove = __devexit_p(snd_audiodrive_pnpc_remove), -#ifdef CONFIG_PM - .suspend = snd_audiodrive_pnpc_suspend, - .resume = snd_audiodrive_pnpc_resume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __init alsa_card_es18xx_init(void) -{ - int err; - - err = isa_register_driver(&snd_es18xx_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_driver(&es18xx_pnp_driver); - if (!err) - pnp_registered = 1; - - err = pnp_register_card_driver(&es18xx_pnpc_driver); - if (!err) - pnpc_registered = 1; - - if (isa_registered || pnp_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_es18xx_exit(void) -{ -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&es18xx_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&es18xx_pnp_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_es18xx_isa_driver); -} - -module_init(alsa_card_es18xx_init) -module_exit(alsa_card_es18xx_exit) diff --git a/ANDROID_3.4.5/sound/isa/galaxy/Makefile b/ANDROID_3.4.5/sound/isa/galaxy/Makefile deleted file mode 100644 index e307066d..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> -# - -snd-azt1605-objs := azt1605.o -snd-azt2316-objs := azt2316.o - -obj-$(CONFIG_SND_AZT1605) += snd-azt1605.o -obj-$(CONFIG_SND_AZT2316) += snd-azt2316.o diff --git a/ANDROID_3.4.5/sound/isa/galaxy/azt1605.c b/ANDROID_3.4.5/sound/isa/galaxy/azt1605.c deleted file mode 100644 index 9a97643c..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/azt1605.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Aztech AZT1605 Driver - * Copyright (C) 2007,2010 Rene Herman - * - * 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, see <http://www.gnu.org/licenses/>. - * - */ - -#define AZT1605 - -#define CRD_NAME "Aztech AZT1605" -#define DRV_NAME "AZT1605" -#define DEV_NAME "azt1605" - -#define GALAXY_DSP_MAJOR 2 -#define GALAXY_DSP_MINOR 1 - -#define GALAXY_CONFIG_SIZE 3 - -/* - * 24-bit config register - */ - -#define GALAXY_CONFIG_SBA_220 (0 << 0) -#define GALAXY_CONFIG_SBA_240 (1 << 0) -#define GALAXY_CONFIG_SBA_260 (2 << 0) -#define GALAXY_CONFIG_SBA_280 (3 << 0) -#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280 - -#define GALAXY_CONFIG_MPUA_300 (0 << 2) -#define GALAXY_CONFIG_MPUA_330 (1 << 2) - -#define GALAXY_CONFIG_MPU_ENABLE (1 << 3) - -#define GALAXY_CONFIG_GAME_ENABLE (1 << 4) - -#define GALAXY_CONFIG_CD_PANASONIC (1 << 5) -#define GALAXY_CONFIG_CD_MITSUMI (1 << 6) -#define GALAXY_CONFIG_CD_MASK (\ - GALAXY_CONFIG_CD_PANASONIC | GALAXY_CONFIG_CD_MITSUMI) - -#define GALAXY_CONFIG_UNUSED (1 << 7) -#define GALAXY_CONFIG_UNUSED_MASK GALAXY_CONFIG_UNUSED - -#define GALAXY_CONFIG_SBIRQ_2 (1 << 8) -#define GALAXY_CONFIG_SBIRQ_3 (1 << 9) -#define GALAXY_CONFIG_SBIRQ_5 (1 << 10) -#define GALAXY_CONFIG_SBIRQ_7 (1 << 11) - -#define GALAXY_CONFIG_MPUIRQ_2 (1 << 12) -#define GALAXY_CONFIG_MPUIRQ_3 (1 << 13) -#define GALAXY_CONFIG_MPUIRQ_5 (1 << 14) -#define GALAXY_CONFIG_MPUIRQ_7 (1 << 15) - -#define GALAXY_CONFIG_WSSA_530 (0 << 16) -#define GALAXY_CONFIG_WSSA_604 (1 << 16) -#define GALAXY_CONFIG_WSSA_E80 (2 << 16) -#define GALAXY_CONFIG_WSSA_F40 (3 << 16) - -#define GALAXY_CONFIG_WSS_ENABLE (1 << 18) - -#define GALAXY_CONFIG_CDIRQ_11 (1 << 19) -#define GALAXY_CONFIG_CDIRQ_12 (1 << 20) -#define GALAXY_CONFIG_CDIRQ_15 (1 << 21) -#define GALAXY_CONFIG_CDIRQ_MASK (\ - GALAXY_CONFIG_CDIRQ_11 | GALAXY_CONFIG_CDIRQ_12 |\ - GALAXY_CONFIG_CDIRQ_15) - -#define GALAXY_CONFIG_CDDMA_DISABLE (0 << 22) -#define GALAXY_CONFIG_CDDMA_0 (1 << 22) -#define GALAXY_CONFIG_CDDMA_1 (2 << 22) -#define GALAXY_CONFIG_CDDMA_3 (3 << 22) -#define GALAXY_CONFIG_CDDMA_MASK GALAXY_CONFIG_CDDMA_3 - -#define GALAXY_CONFIG_MASK (\ - GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CD_MASK |\ - GALAXY_CONFIG_UNUSED_MASK | GALAXY_CONFIG_CDIRQ_MASK |\ - GALAXY_CONFIG_CDDMA_MASK) - -#include "galaxy.c" diff --git a/ANDROID_3.4.5/sound/isa/galaxy/azt2316.c b/ANDROID_3.4.5/sound/isa/galaxy/azt2316.c deleted file mode 100644 index 18944114..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/azt2316.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Aztech AZT2316 Driver - * Copyright (C) 2007,2010 Rene Herman - * - * 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, see <http://www.gnu.org/licenses/>. - * - */ - -#define AZT2316 - -#define CRD_NAME "Aztech AZT2316" -#define DRV_NAME "AZT2316" -#define DEV_NAME "azt2316" - -#define GALAXY_DSP_MAJOR 3 -#define GALAXY_DSP_MINOR 1 - -#define GALAXY_CONFIG_SIZE 4 - -/* - * 32-bit config register - */ - -#define GALAXY_CONFIG_SBA_220 (0 << 0) -#define GALAXY_CONFIG_SBA_240 (1 << 0) -#define GALAXY_CONFIG_SBA_260 (2 << 0) -#define GALAXY_CONFIG_SBA_280 (3 << 0) -#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280 - -#define GALAXY_CONFIG_SBIRQ_2 (1 << 2) -#define GALAXY_CONFIG_SBIRQ_5 (1 << 3) -#define GALAXY_CONFIG_SBIRQ_7 (1 << 4) -#define GALAXY_CONFIG_SBIRQ_10 (1 << 5) - -#define GALAXY_CONFIG_SBDMA_DISABLE (0 << 6) -#define GALAXY_CONFIG_SBDMA_0 (1 << 6) -#define GALAXY_CONFIG_SBDMA_1 (2 << 6) -#define GALAXY_CONFIG_SBDMA_3 (3 << 6) - -#define GALAXY_CONFIG_WSSA_530 (0 << 8) -#define GALAXY_CONFIG_WSSA_604 (1 << 8) -#define GALAXY_CONFIG_WSSA_E80 (2 << 8) -#define GALAXY_CONFIG_WSSA_F40 (3 << 8) - -#define GALAXY_CONFIG_WSS_ENABLE (1 << 10) - -#define GALAXY_CONFIG_GAME_ENABLE (1 << 11) - -#define GALAXY_CONFIG_MPUA_300 (0 << 12) -#define GALAXY_CONFIG_MPUA_330 (1 << 12) - -#define GALAXY_CONFIG_MPU_ENABLE (1 << 13) - -#define GALAXY_CONFIG_CDA_310 (0 << 14) -#define GALAXY_CONFIG_CDA_320 (1 << 14) -#define GALAXY_CONFIG_CDA_340 (2 << 14) -#define GALAXY_CONFIG_CDA_350 (3 << 14) -#define GALAXY_CONFIG_CDA_MASK GALAXY_CONFIG_CDA_350 - -#define GALAXY_CONFIG_CD_DISABLE (0 << 16) -#define GALAXY_CONFIG_CD_PANASONIC (1 << 16) -#define GALAXY_CONFIG_CD_SONY (2 << 16) -#define GALAXY_CONFIG_CD_MITSUMI (3 << 16) -#define GALAXY_CONFIG_CD_AZTECH (4 << 16) -#define GALAXY_CONFIG_CD_UNUSED_5 (5 << 16) -#define GALAXY_CONFIG_CD_UNUSED_6 (6 << 16) -#define GALAXY_CONFIG_CD_UNUSED_7 (7 << 16) -#define GALAXY_CONFIG_CD_MASK GALAXY_CONFIG_CD_UNUSED_7 - -#define GALAXY_CONFIG_CDDMA8_DISABLE (0 << 20) -#define GALAXY_CONFIG_CDDMA8_0 (1 << 20) -#define GALAXY_CONFIG_CDDMA8_1 (2 << 20) -#define GALAXY_CONFIG_CDDMA8_3 (3 << 20) -#define GALAXY_CONFIG_CDDMA8_MASK GALAXY_CONFIG_CDDMA8_3 - -#define GALAXY_CONFIG_CDDMA16_DISABLE (0 << 22) -#define GALAXY_CONFIG_CDDMA16_5 (1 << 22) -#define GALAXY_CONFIG_CDDMA16_6 (2 << 22) -#define GALAXY_CONFIG_CDDMA16_7 (3 << 22) -#define GALAXY_CONFIG_CDDMA16_MASK GALAXY_CONFIG_CDDMA16_7 - -#define GALAXY_CONFIG_MPUIRQ_2 (1 << 24) -#define GALAXY_CONFIG_MPUIRQ_5 (1 << 25) -#define GALAXY_CONFIG_MPUIRQ_7 (1 << 26) -#define GALAXY_CONFIG_MPUIRQ_10 (1 << 27) - -#define GALAXY_CONFIG_CDIRQ_5 (1 << 28) -#define GALAXY_CONFIG_CDIRQ_11 (1 << 29) -#define GALAXY_CONFIG_CDIRQ_12 (1 << 30) -#define GALAXY_CONFIG_CDIRQ_15 (1 << 31) -#define GALAXY_CONFIG_CDIRQ_MASK (\ - GALAXY_CONFIG_CDIRQ_5 | GALAXY_CONFIG_CDIRQ_11 |\ - GALAXY_CONFIG_CDIRQ_12 | GALAXY_CONFIG_CDIRQ_15) - -#define GALAXY_CONFIG_MASK (\ - GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CDA_MASK |\ - GALAXY_CONFIG_CD_MASK | GALAXY_CONFIG_CDDMA16_MASK |\ - GALAXY_CONFIG_CDDMA8_MASK | GALAXY_CONFIG_CDIRQ_MASK) - -#include "galaxy.c" diff --git a/ANDROID_3.4.5/sound/isa/galaxy/galaxy.c b/ANDROID_3.4.5/sound/isa/galaxy/galaxy.c deleted file mode 100644 index 55e20782..00000000 --- a/ANDROID_3.4.5/sound/isa/galaxy/galaxy.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Aztech AZT1605/AZT2316 Driver - * Copyright (C) 2007,2010 Rene Herman - * - * 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, see <http://www.gnu.org/licenses/>. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/isa.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <asm/processor.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Rene Herman"); -MODULE_LICENSE("GPL"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); - -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; - -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(wss_port, long, NULL, 0444); -MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver."); - -/* - * Generic SB DSP support routines - */ - -#define DSP_PORT_RESET 0x6 -#define DSP_PORT_READ 0xa -#define DSP_PORT_COMMAND 0xc -#define DSP_PORT_STATUS 0xc -#define DSP_PORT_DATA_AVAIL 0xe - -#define DSP_SIGNATURE 0xaa - -#define DSP_COMMAND_GET_VERSION 0xe1 - -static int __devinit dsp_get_byte(void __iomem *port, u8 *val) -{ - int loops = 1000; - - while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) { - if (!loops--) - return -EIO; - cpu_relax(); - } - *val = ioread8(port + DSP_PORT_READ); - return 0; -} - -static int __devinit dsp_reset(void __iomem *port) -{ - u8 val; - - iowrite8(1, port + DSP_PORT_RESET); - udelay(10); - iowrite8(0, port + DSP_PORT_RESET); - - if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE) - return -ENODEV; - - return 0; -} - -static int __devinit dsp_command(void __iomem *port, u8 cmd) -{ - int loops = 1000; - - while (ioread8(port + DSP_PORT_STATUS) & 0x80) { - if (!loops--) - return -EIO; - cpu_relax(); - } - iowrite8(cmd, port + DSP_PORT_COMMAND); - return 0; -} - -static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor) -{ - int err; - - err = dsp_command(port, DSP_COMMAND_GET_VERSION); - if (err < 0) - return err; - - err = dsp_get_byte(port, major); - if (err < 0) - return err; - - err = dsp_get_byte(port, minor); - if (err < 0) - return err; - - return 0; -} - -/* - * Generic WSS support routines - */ - -#define WSS_CONFIG_DMA_0 (1 << 0) -#define WSS_CONFIG_DMA_1 (2 << 0) -#define WSS_CONFIG_DMA_3 (3 << 0) -#define WSS_CONFIG_DUPLEX (1 << 2) -#define WSS_CONFIG_IRQ_7 (1 << 3) -#define WSS_CONFIG_IRQ_9 (2 << 3) -#define WSS_CONFIG_IRQ_10 (3 << 3) -#define WSS_CONFIG_IRQ_11 (4 << 3) - -#define WSS_PORT_CONFIG 0 -#define WSS_PORT_SIGNATURE 3 - -#define WSS_SIGNATURE 4 - -static int __devinit wss_detect(void __iomem *wss_port) -{ - if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE) - return -ENODEV; - - return 0; -} - -static void wss_set_config(void __iomem *wss_port, u8 wss_config) -{ - iowrite8(wss_config, wss_port + WSS_PORT_CONFIG); -} - -/* - * Aztech Sound Galaxy specifics - */ - -#define GALAXY_PORT_CONFIG 1024 -#define CONFIG_PORT_SET 4 - -#define DSP_COMMAND_GALAXY_8 8 -#define GALAXY_COMMAND_GET_TYPE 5 - -#define DSP_COMMAND_GALAXY_9 9 -#define GALAXY_COMMAND_WSSMODE 0 -#define GALAXY_COMMAND_SB8MODE 1 - -#define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE -#define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE - -struct snd_galaxy { - void __iomem *port; - void __iomem *config_port; - void __iomem *wss_port; - u32 config; - struct resource *res_port; - struct resource *res_config_port; - struct resource *res_wss_port; -}; - -static u32 config[SNDRV_CARDS]; -static u8 wss_config[SNDRV_CARDS]; - -static int __devinit snd_galaxy_match(struct device *dev, unsigned int n) -{ - if (!enable[n]) - return 0; - - switch (port[n]) { - case SNDRV_AUTO_PORT: - dev_err(dev, "please specify port\n"); - return 0; - case 0x220: - config[n] |= GALAXY_CONFIG_SBA_220; - break; - case 0x240: - config[n] |= GALAXY_CONFIG_SBA_240; - break; - case 0x260: - config[n] |= GALAXY_CONFIG_SBA_260; - break; - case 0x280: - config[n] |= GALAXY_CONFIG_SBA_280; - break; - default: - dev_err(dev, "invalid port %#lx\n", port[n]); - return 0; - } - - switch (wss_port[n]) { - case SNDRV_AUTO_PORT: - dev_err(dev, "please specify wss_port\n"); - return 0; - case 0x530: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530; - break; - case 0x604: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604; - break; - case 0xe80: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80; - break; - case 0xf40: - config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40; - break; - default: - dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]); - return 0; - } - - switch (irq[n]) { - case SNDRV_AUTO_IRQ: - dev_err(dev, "please specify irq\n"); - return 0; - case 7: - wss_config[n] |= WSS_CONFIG_IRQ_7; - break; - case 2: - irq[n] = 9; - case 9: - wss_config[n] |= WSS_CONFIG_IRQ_9; - break; - case 10: - wss_config[n] |= WSS_CONFIG_IRQ_10; - break; - case 11: - wss_config[n] |= WSS_CONFIG_IRQ_11; - break; - default: - dev_err(dev, "invalid IRQ %d\n", irq[n]); - return 0; - } - - switch (dma1[n]) { - case SNDRV_AUTO_DMA: - dev_err(dev, "please specify dma1\n"); - return 0; - case 0: - wss_config[n] |= WSS_CONFIG_DMA_0; - break; - case 1: - wss_config[n] |= WSS_CONFIG_DMA_1; - break; - case 3: - wss_config[n] |= WSS_CONFIG_DMA_3; - break; - default: - dev_err(dev, "invalid playback DMA %d\n", dma1[n]); - return 0; - } - - if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) { - dma2[n] = -1; - goto mpu; - } - - wss_config[n] |= WSS_CONFIG_DUPLEX; - switch (dma2[n]) { - case 0: - break; - case 1: - if (dma1[n] == 0) - break; - default: - dev_err(dev, "invalid capture DMA %d\n", dma2[n]); - return 0; - } - -mpu: - switch (mpu_port[n]) { - case SNDRV_AUTO_PORT: - dev_warn(dev, "mpu_port not specified; not using MPU-401\n"); - mpu_port[n] = -1; - goto fm; - case 0x300: - config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300; - break; - case 0x330: - config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330; - break; - default: - dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]); - return 0; - } - - switch (mpu_irq[n]) { - case SNDRV_AUTO_IRQ: - dev_warn(dev, "mpu_irq not specified: using polling mode\n"); - mpu_irq[n] = -1; - break; - case 2: - mpu_irq[n] = 9; - case 9: - config[n] |= GALAXY_CONFIG_MPUIRQ_2; - break; -#ifdef AZT1605 - case 3: - config[n] |= GALAXY_CONFIG_MPUIRQ_3; - break; -#endif - case 5: - config[n] |= GALAXY_CONFIG_MPUIRQ_5; - break; - case 7: - config[n] |= GALAXY_CONFIG_MPUIRQ_7; - break; -#ifdef AZT2316 - case 10: - config[n] |= GALAXY_CONFIG_MPUIRQ_10; - break; -#endif - default: - dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]); - return 0; - } - - if (mpu_irq[n] == irq[n]) { - dev_err(dev, "cannot share IRQ between WSS and MPU-401\n"); - return 0; - } - -fm: - switch (fm_port[n]) { - case SNDRV_AUTO_PORT: - dev_warn(dev, "fm_port not specified: not using OPL3\n"); - fm_port[n] = -1; - break; - case 0x388: - break; - default: - dev_err(dev, "illegal FM port %#lx\n", fm_port[n]); - return 0; - } - - config[n] |= GALAXY_CONFIG_GAME_ENABLE; - return 1; -} - -static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type) -{ - u8 major; - u8 minor; - int err; - - err = dsp_reset(galaxy->port); - if (err < 0) - return err; - - err = dsp_get_version(galaxy->port, &major, &minor); - if (err < 0) - return err; - - if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR) - return -ENODEV; - - err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8); - if (err < 0) - return err; - - err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE); - if (err < 0) - return err; - - err = dsp_get_byte(galaxy->port, type); - if (err < 0) - return err; - - return 0; -} - -static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode) -{ - int err; - - err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9); - if (err < 0) - return err; - - err = dsp_command(galaxy->port, mode); - if (err < 0) - return err; - -#ifdef AZT1605 - /* - * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again - */ - err = dsp_reset(galaxy->port); - if (err < 0) - return err; -#endif - - return 0; -} - -static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config) -{ - u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET); - int i; - - iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET); - for (i = 0; i < GALAXY_CONFIG_SIZE; i++) { - iowrite8(config, galaxy->config_port + i); - config >>= 8; - } - iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET); - msleep(10); -} - -static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config) -{ - int i; - - for (i = GALAXY_CONFIG_SIZE; i; i--) { - u8 tmp = ioread8(galaxy->config_port + i - 1); - galaxy->config = (galaxy->config << 8) | tmp; - } - config |= galaxy->config & GALAXY_CONFIG_MASK; - galaxy_set_config(galaxy, config); -} - -static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config) -{ - int err; - - err = wss_detect(galaxy->wss_port); - if (err < 0) - return err; - - wss_set_config(galaxy->wss_port, wss_config); - - err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS); - if (err < 0) - return err; - - return 0; -} - -static void snd_galaxy_free(struct snd_card *card) -{ - struct snd_galaxy *galaxy = card->private_data; - - if (galaxy->wss_port) { - wss_set_config(galaxy->wss_port, 0); - ioport_unmap(galaxy->wss_port); - release_and_free_resource(galaxy->res_wss_port); - } - if (galaxy->config_port) { - galaxy_set_config(galaxy, galaxy->config); - ioport_unmap(galaxy->config_port); - release_and_free_resource(galaxy->res_config_port); - } - if (galaxy->port) { - ioport_unmap(galaxy->port); - release_and_free_resource(galaxy->res_port); - } -} - -static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n) -{ - struct snd_galaxy *galaxy; - struct snd_wss *chip; - struct snd_card *card; - u8 type; - int err; - - err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy, - &card); - if (err < 0) - return err; - - snd_card_set_dev(card, dev); - - card->private_free = snd_galaxy_free; - galaxy = card->private_data; - - galaxy->res_port = request_region(port[n], 16, DRV_NAME); - if (!galaxy->res_port) { - dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n], - port[n] + 15); - err = -EBUSY; - goto error; - } - galaxy->port = ioport_map(port[n], 16); - - err = galaxy_init(galaxy, &type); - if (err < 0) { - dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]); - goto error; - } - dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]); - - galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG, - 16, DRV_NAME); - if (!galaxy->res_config_port) { - dev_err(dev, "could not grab ports %#lx-%#lx\n", - port[n] + GALAXY_PORT_CONFIG, - port[n] + GALAXY_PORT_CONFIG + 15); - err = -EBUSY; - goto error; - } - galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16); - - galaxy_config(galaxy, config[n]); - - galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME); - if (!galaxy->res_wss_port) { - dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n], - wss_port[n] + 3); - err = -EBUSY; - goto error; - } - galaxy->wss_port = ioport_map(wss_port[n], 4); - - err = galaxy_wss_config(galaxy, wss_config[n]); - if (err < 0) { - dev_err(dev, "could not configure WSS\n"); - goto error; - } - - strcpy(card->driver, DRV_NAME); - strcpy(card->shortname, DRV_NAME); - sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d", - card->shortname, port[n], wss_port[n], irq[n], dma1[n], - dma2[n]); - - err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n], - dma2[n], WSS_HW_DETECT, 0, &chip); - if (err < 0) - goto error; - - err = snd_wss_pcm(chip, 0, NULL); - if (err < 0) - goto error; - - err = snd_wss_mixer(chip); - if (err < 0) - goto error; - - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) - goto error; - - if (mpu_port[n] >= 0) { - err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port[n], 0, mpu_irq[n], NULL); - if (err < 0) - goto error; - } - - if (fm_port[n] >= 0) { - struct snd_opl3 *opl3; - - err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2, - OPL3_HW_AUTO, 0, &opl3); - if (err < 0) { - dev_err(dev, "no OPL device at %#lx\n", fm_port[n]); - goto error; - } - err = snd_opl3_timer_new(opl3, 1, 2); - if (err < 0) - goto error; - - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - goto error; - } - - err = snd_card_register(card); - if (err < 0) - goto error; - - dev_set_drvdata(dev, card); - return 0; - -error: - snd_card_free(card); - return err; -} - -static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_galaxy_driver = { - .match = snd_galaxy_match, - .probe = snd_galaxy_probe, - .remove = __devexit_p(snd_galaxy_remove), - - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_galaxy_init(void) -{ - return isa_register_driver(&snd_galaxy_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_galaxy_exit(void) -{ - isa_unregister_driver(&snd_galaxy_driver); -} - -module_init(alsa_card_galaxy_init); -module_exit(alsa_card_galaxy_exit); diff --git a/ANDROID_3.4.5/sound/isa/gus/Makefile b/ANDROID_3.4.5/sound/isa/gus/Makefile deleted file mode 100644 index 6cd4ee03..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-gus-lib-objs := gus_main.o \ - gus_io.o gus_irq.o gus_timer.o \ - gus_mem.o gus_mem_proc.o gus_dram.o gus_dma.o gus_volume.o \ - gus_pcm.o gus_mixer.o \ - gus_uart.o \ - gus_reset.o - -snd-gusclassic-objs := gusclassic.o -snd-gusextreme-objs := gusextreme.o -snd-gusmax-objs := gusmax.o -snd-interwave-objs := interwave.o -snd-interwave-stb-objs := interwave-stb.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o -obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o -obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o -obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o -obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_dma.c b/ANDROID_3.4.5/sound/isa/gus/gus_dma.c deleted file mode 100644 index 36c27c83..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_dma.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Routines for GF1 DMA control - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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 <asm/dma.h> -#include <linux/slab.h> -#include <sound/core.h> -#include <sound/gus.h> - -static void snd_gf1_dma_ack(struct snd_gus_card * gus) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, 0x00); - snd_gf1_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static void snd_gf1_dma_program(struct snd_gus_card * gus, - unsigned int addr, - unsigned long buf_addr, - unsigned int count, - unsigned int cmd) -{ - unsigned long flags; - unsigned int address; - unsigned char dma_cmd; - unsigned int address_high; - - snd_printdd("dma_transfer: addr=0x%x, buf=0x%lx, count=0x%x\n", - addr, buf_addr, count); - - if (gus->gf1.dma1 > 3) { - if (gus->gf1.enh_mode) { - address = addr >> 1; - } else { - if (addr & 0x1f) { - snd_printd("snd_gf1_dma_transfer: unaligned address (0x%x)?\n", addr); - return; - } - address = (addr & 0x000c0000) | ((addr & 0x0003ffff) >> 1); - } - } else { - address = addr; - } - - dma_cmd = SNDRV_GF1_DMA_ENABLE | (unsigned short) cmd; -#if 0 - dma_cmd |= 0x08; -#endif - if (dma_cmd & SNDRV_GF1_DMA_16BIT) { - count++; - count &= ~1; /* align */ - } - if (gus->gf1.dma1 > 3) { - dma_cmd |= SNDRV_GF1_DMA_WIDTH16; - count++; - count &= ~1; /* align */ - } - snd_gf1_dma_ack(gus); - snd_dma_program(gus->gf1.dma1, buf_addr, count, dma_cmd & SNDRV_GF1_DMA_READ ? DMA_MODE_READ : DMA_MODE_WRITE); -#if 0 - snd_printk(KERN_DEBUG "address = 0x%x, count = 0x%x, dma_cmd = 0x%x\n", - address << 1, count, dma_cmd); -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - if (gus->gf1.enh_mode) { - address_high = ((address >> 16) & 0x000000f0) | (address & 0x0000000f); - snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); - snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH, (unsigned char) address_high); - } else - snd_gf1_write16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW, (unsigned short) (address >> 4)); - snd_gf1_write8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL, dma_cmd); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static struct snd_gf1_dma_block *snd_gf1_dma_next_block(struct snd_gus_card * gus) -{ - struct snd_gf1_dma_block *block; - - /* PCM block have bigger priority than synthesizer one */ - if (gus->gf1.dma_data_pcm) { - block = gus->gf1.dma_data_pcm; - if (gus->gf1.dma_data_pcm_last == block) { - gus->gf1.dma_data_pcm = - gus->gf1.dma_data_pcm_last = NULL; - } else { - gus->gf1.dma_data_pcm = block->next; - } - } else if (gus->gf1.dma_data_synth) { - block = gus->gf1.dma_data_synth; - if (gus->gf1.dma_data_synth_last == block) { - gus->gf1.dma_data_synth = - gus->gf1.dma_data_synth_last = NULL; - } else { - gus->gf1.dma_data_synth = block->next; - } - } else { - block = NULL; - } - if (block) { - gus->gf1.dma_ack = block->ack; - gus->gf1.dma_private_data = block->private_data; - } - return block; -} - - -static void snd_gf1_dma_interrupt(struct snd_gus_card * gus) -{ - struct snd_gf1_dma_block *block; - - snd_gf1_dma_ack(gus); - if (gus->gf1.dma_ack) - gus->gf1.dma_ack(gus, gus->gf1.dma_private_data); - spin_lock(&gus->dma_lock); - if (gus->gf1.dma_data_pcm == NULL && - gus->gf1.dma_data_synth == NULL) { - gus->gf1.dma_ack = NULL; - gus->gf1.dma_flags &= ~SNDRV_GF1_DMA_TRIGGER; - spin_unlock(&gus->dma_lock); - return; - } - block = snd_gf1_dma_next_block(gus); - spin_unlock(&gus->dma_lock); - snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); - kfree(block); -#if 0 - snd_printd(KERN_DEBUG "program dma (IRQ) - " - "addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", - block->addr, block->buf_addr, block->count, block->cmd); -#endif -} - -int snd_gf1_dma_init(struct snd_gus_card * gus) -{ - mutex_lock(&gus->dma_mutex); - gus->gf1.dma_shared++; - if (gus->gf1.dma_shared > 1) { - mutex_unlock(&gus->dma_mutex); - return 0; - } - gus->gf1.interrupt_handler_dma_write = snd_gf1_dma_interrupt; - gus->gf1.dma_data_pcm = - gus->gf1.dma_data_pcm_last = - gus->gf1.dma_data_synth = - gus->gf1.dma_data_synth_last = NULL; - mutex_unlock(&gus->dma_mutex); - return 0; -} - -int snd_gf1_dma_done(struct snd_gus_card * gus) -{ - struct snd_gf1_dma_block *block; - - mutex_lock(&gus->dma_mutex); - gus->gf1.dma_shared--; - if (!gus->gf1.dma_shared) { - snd_dma_disable(gus->gf1.dma1); - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_WRITE); - snd_gf1_dma_ack(gus); - while ((block = gus->gf1.dma_data_pcm)) { - gus->gf1.dma_data_pcm = block->next; - kfree(block); - } - while ((block = gus->gf1.dma_data_synth)) { - gus->gf1.dma_data_synth = block->next; - kfree(block); - } - gus->gf1.dma_data_pcm_last = - gus->gf1.dma_data_synth_last = NULL; - } - mutex_unlock(&gus->dma_mutex); - return 0; -} - -int snd_gf1_dma_transfer_block(struct snd_gus_card * gus, - struct snd_gf1_dma_block * __block, - int atomic, - int synth) -{ - unsigned long flags; - struct snd_gf1_dma_block *block; - - block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL); - if (block == NULL) { - snd_printk(KERN_ERR "gf1: DMA transfer failure; not enough memory\n"); - return -ENOMEM; - } - *block = *__block; - block->next = NULL; - - snd_printdd("addr = 0x%x, buffer = 0x%lx, count = 0x%x, cmd = 0x%x\n", - block->addr, (long) block->buffer, block->count, - block->cmd); - - snd_printdd("gus->gf1.dma_data_pcm_last = 0x%lx\n", - (long)gus->gf1.dma_data_pcm_last); - snd_printdd("gus->gf1.dma_data_pcm = 0x%lx\n", - (long)gus->gf1.dma_data_pcm); - - spin_lock_irqsave(&gus->dma_lock, flags); - if (synth) { - if (gus->gf1.dma_data_synth_last) { - gus->gf1.dma_data_synth_last->next = block; - gus->gf1.dma_data_synth_last = block; - } else { - gus->gf1.dma_data_synth = - gus->gf1.dma_data_synth_last = block; - } - } else { - if (gus->gf1.dma_data_pcm_last) { - gus->gf1.dma_data_pcm_last->next = block; - gus->gf1.dma_data_pcm_last = block; - } else { - gus->gf1.dma_data_pcm = - gus->gf1.dma_data_pcm_last = block; - } - } - if (!(gus->gf1.dma_flags & SNDRV_GF1_DMA_TRIGGER)) { - gus->gf1.dma_flags |= SNDRV_GF1_DMA_TRIGGER; - block = snd_gf1_dma_next_block(gus); - spin_unlock_irqrestore(&gus->dma_lock, flags); - if (block == NULL) - return 0; - snd_gf1_dma_program(gus, block->addr, block->buf_addr, block->count, (unsigned short) block->cmd); - kfree(block); - return 0; - } - spin_unlock_irqrestore(&gus->dma_lock, flags); - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_dram.c b/ANDROID_3.4.5/sound/isa/gus/gus_dram.c deleted file mode 100644 index fd2e2e2e..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_dram.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * DRAM access routines - * - * - * 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/gus.h> -#include <sound/info.h> - - -static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer, - unsigned int address, unsigned int size) -{ - unsigned long flags; - unsigned int size1, size2; - char buffer[256], *pbuffer; - - while (size > 0) { - size1 = size > sizeof(buffer) ? sizeof(buffer) : size; - if (copy_from_user(buffer, _buffer, size1)) - return -EFAULT; - if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - snd_gf1_dram_addr(gus, address); - outsb(GUSP(gus, DRAM), buffer, size1); - spin_unlock_irqrestore(&gus->reg_lock, flags); - address += size1; - } else { - pbuffer = buffer; - size2 = size1; - while (size2--) - snd_gf1_poke(gus, address++, *pbuffer++); - } - size -= size1; - _buffer += size1; - } - return 0; -} - - -int snd_gus_dram_write(struct snd_gus_card *gus, char __user *buffer, - unsigned int address, unsigned int size) -{ - return snd_gus_dram_poke(gus, buffer, address, size); -} - -static int snd_gus_dram_peek(struct snd_gus_card *gus, char __user *_buffer, - unsigned int address, unsigned int size, - int rom) -{ - unsigned long flags; - unsigned int size1, size2; - char buffer[256], *pbuffer; - - while (size > 0) { - size1 = size > sizeof(buffer) ? sizeof(buffer) : size; - if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01); - snd_gf1_dram_addr(gus, address); - insb(GUSP(gus, DRAM), buffer, size1); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - spin_unlock_irqrestore(&gus->reg_lock, flags); - address += size1; - } else { - pbuffer = buffer; - size2 = size1; - while (size2--) - *pbuffer++ = snd_gf1_peek(gus, address++); - } - if (copy_to_user(_buffer, buffer, size1)) - return -EFAULT; - size -= size1; - _buffer += size1; - } - return 0; -} - -int snd_gus_dram_read(struct snd_gus_card *gus, char __user *buffer, - unsigned int address, unsigned int size, - int rom) -{ - return snd_gus_dram_peek(gus, buffer, address, size, rom); -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_instr.c b/ANDROID_3.4.5/sound/isa/gus/gus_instr.c deleted file mode 100644 index 4dc9caf8..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_instr.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Routines for Gravis UltraSound soundcards - Synthesizer - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/gus.h> - -/* - * - */ - -int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - struct snd_gf1_mem_block *block; - int err; - - if (wave->format & IWFFFF_WAVE_ROM) - return 0; /* it's probably ok - verify the address? */ - if (wave->format & IWFFFF_WAVE_STEREO) - return -EINVAL; /* not supported */ - block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF, - NULL, wave->size, - wave->format & IWFFFF_WAVE_16BIT, 1, - wave->share_id); - if (block == NULL) - return -ENOMEM; - err = snd_gus_dram_write(gus, data, - block->ptr, wave->size); - if (err < 0) { - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); - snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); - return err; - } - wave->address.memory = block->ptr; - return 0; -} - -int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, - wave->format & IWFFFF_WAVE_ROM ? 1 : 0); -} - -int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave, - int atomic) -{ - struct snd_gus_card *gus = private_data; - - if (wave->format & IWFFFF_WAVE_ROM) - return 0; /* it's probably ok - verify the address? */ - return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory); -} - -/* - * - */ - -int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - struct snd_gf1_mem_block *block; - int err; - - if (wave->format & GF1_WAVE_STEREO) - return -EINVAL; /* not supported */ - block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_WAVE_GF1, - NULL, wave->size, - wave->format & GF1_WAVE_16BIT, 1, - wave->share_id); - if (block == NULL) - return -ENOMEM; - err = snd_gus_dram_write(gus, data, - block->ptr, wave->size); - if (err < 0) { - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); - snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); - return err; - } - wave->address.memory = block->ptr; - return 0; -} - -int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0); -} - -int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave, - int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory); -} - -/* - * - */ - -int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - struct snd_gf1_mem_block *block; - int err; - - if (instr->format & SIMPLE_WAVE_STEREO) - return -EINVAL; /* not supported */ - block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE, - NULL, instr->size, - instr->format & SIMPLE_WAVE_16BIT, 1, - instr->share_id); - if (block == NULL) - return -ENOMEM; - err = snd_gus_dram_write(gus, data, block->ptr, instr->size); - if (err < 0) { - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0); - snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block); - snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1); - return err; - } - instr->address.memory = block->ptr; - return 0; -} - -int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr, - char __user *data, long len, int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0); -} - -int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr, - int atomic) -{ - struct snd_gus_card *gus = private_data; - - return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory); -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_io.c b/ANDROID_3.4.5/sound/isa/gus/gus_io.c deleted file mode 100644 index ca79878d..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_io.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * I/O routines for GF1/InterWave synthesizer chips - * - * - * 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/time.h> -#include <sound/core.h> -#include <sound/gus.h> - -void snd_gf1_delay(struct snd_gus_card * gus) -{ - int i; - - for (i = 0; i < 6; i++) { - mb(); - inb(GUSP(gus, DRAM)); - } -} - -/* - * ======================================================================= - */ - -/* - * ok.. stop of control registers (wave & ramp) need some special things.. - * big UltraClick (tm) elimination... - */ - -static inline void __snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned char value; - - outb(reg | 0x80, gus->gf1.reg_regsel); - mb(); - value = inb(gus->gf1.reg_data8); - mb(); - outb(reg, gus->gf1.reg_regsel); - mb(); - outb((value | 0x03) & ~(0x80 | 0x20), gus->gf1.reg_data8); - mb(); -} - -static inline void __snd_gf1_write8(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - outb(data, gus->gf1.reg_data8); - mb(); -} - -static inline unsigned char __snd_gf1_look8(struct snd_gus_card * gus, - unsigned char reg) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - return inb(gus->gf1.reg_data8); -} - -static inline void __snd_gf1_write16(struct snd_gus_card * gus, - unsigned char reg, unsigned int data) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) data, gus->gf1.reg_data16); - mb(); -} - -static inline unsigned short __snd_gf1_look16(struct snd_gus_card * gus, - unsigned char reg) -{ - outb(reg, gus->gf1.reg_regsel); - mb(); - return inw(gus->gf1.reg_data16); -} - -static inline void __snd_gf1_adlib_write(struct snd_gus_card * gus, - unsigned char reg, unsigned char data) -{ - outb(reg, gus->gf1.reg_timerctrl); - inb(gus->gf1.reg_timerctrl); - inb(gus->gf1.reg_timerctrl); - outb(data, gus->gf1.reg_timerdata); - inb(gus->gf1.reg_timerctrl); - inb(gus->gf1.reg_timerctrl); -} - -static inline void __snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg, - unsigned int addr, int w_16bit) -{ - if (gus->gf1.enh_mode) { - if (w_16bit) - addr = ((addr >> 1) & ~0x0000000f) | (addr & 0x0000000f); - __snd_gf1_write8(gus, SNDRV_GF1_VB_UPPER_ADDRESS, (unsigned char) ((addr >> 26) & 0x03)); - } else if (w_16bit) - addr = (addr & 0x00c0000f) | ((addr & 0x003ffff0) >> 1); - __snd_gf1_write16(gus, reg, (unsigned short) (addr >> 11)); - __snd_gf1_write16(gus, reg + 1, (unsigned short) (addr << 5)); -} - -static inline unsigned int __snd_gf1_read_addr(struct snd_gus_card * gus, - unsigned char reg, short w_16bit) -{ - unsigned int res; - - res = ((unsigned int) __snd_gf1_look16(gus, reg | 0x80) << 11) & 0xfff800; - res |= ((unsigned int) __snd_gf1_look16(gus, (reg + 1) | 0x80) >> 5) & 0x0007ff; - if (gus->gf1.enh_mode) { - res |= (unsigned int) __snd_gf1_look8(gus, SNDRV_GF1_VB_UPPER_ADDRESS | 0x80) << 26; - if (w_16bit) - res = ((res << 1) & 0xffffffe0) | (res & 0x0000000f); - } else if (w_16bit) - res = ((res & 0x001ffff0) << 1) | (res & 0x00c0000f); - return res; -} - - -/* - * ======================================================================= - */ - -void snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) -{ - __snd_gf1_ctrl_stop(gus, reg); -} - -void snd_gf1_write8(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - __snd_gf1_write8(gus, reg, data); -} - -unsigned char snd_gf1_look8(struct snd_gus_card * gus, unsigned char reg) -{ - return __snd_gf1_look8(gus, reg); -} - -void snd_gf1_write16(struct snd_gus_card * gus, - unsigned char reg, - unsigned int data) -{ - __snd_gf1_write16(gus, reg, data); -} - -unsigned short snd_gf1_look16(struct snd_gus_card * gus, unsigned char reg) -{ - return __snd_gf1_look16(gus, reg); -} - -void snd_gf1_adlib_write(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - __snd_gf1_adlib_write(gus, reg, data); -} - -void snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg, - unsigned int addr, short w_16bit) -{ - __snd_gf1_write_addr(gus, reg, addr, w_16bit); -} - -unsigned int snd_gf1_read_addr(struct snd_gus_card * gus, - unsigned char reg, - short w_16bit) -{ - return __snd_gf1_read_addr(gus, reg, w_16bit); -} - -/* - - */ - -void snd_gf1_i_ctrl_stop(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_ctrl_stop(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -void snd_gf1_i_write8(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_write8(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned char snd_gf1_i_look8(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_look8(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -void snd_gf1_i_write16(struct snd_gus_card * gus, - unsigned char reg, - unsigned int data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_write16(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned short snd_gf1_i_look16(struct snd_gus_card * gus, unsigned char reg) -{ - unsigned long flags; - unsigned short res; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_look16(gus, reg); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -#if 0 - -void snd_gf1_i_adlib_write(struct snd_gus_card * gus, - unsigned char reg, - unsigned char data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_adlib_write(gus, reg, data); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -void snd_gf1_i_write_addr(struct snd_gus_card * gus, unsigned char reg, - unsigned int addr, short w_16bit) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - __snd_gf1_write_addr(gus, reg, addr, w_16bit); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -#endif /* 0 */ - -#ifdef CONFIG_SND_DEBUG -static unsigned int snd_gf1_i_read_addr(struct snd_gus_card * gus, - unsigned char reg, short w_16bit) -{ - unsigned int res; - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - res = __snd_gf1_read_addr(gus, reg, w_16bit); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} -#endif - -/* - - */ - -void snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr) -{ - outb(0x43, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(0x44, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); -} - -void snd_gf1_poke(struct snd_gus_card * gus, unsigned int addr, unsigned char data) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(data, gus->gf1.reg_dram); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned char snd_gf1_peek(struct snd_gus_card * gus, unsigned int addr) -{ - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - res = inb(gus->gf1.reg_dram); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -#if 0 - -void snd_gf1_pokew(struct snd_gus_card * gus, unsigned int addr, unsigned short data) -{ - unsigned long flags; - -#ifdef CONFIG_SND_DEBUG - if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_pokew - GF1!!!\n"); -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); - mb(); - outw(data, gus->gf1.reg_data16); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -unsigned short snd_gf1_peekw(struct snd_gus_card * gus, unsigned int addr) -{ - unsigned long flags; - unsigned short res; - -#ifdef CONFIG_SND_DEBUG - if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_peekw - GF1!!!\n"); -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); - mb(); - res = inw(gus->gf1.reg_data16); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return res; -} - -void snd_gf1_dram_setmem(struct snd_gus_card * gus, unsigned int addr, - unsigned short value, unsigned int count) -{ - unsigned long port; - unsigned long flags; - -#ifdef CONFIG_SND_DEBUG - if (!gus->interwave) - snd_printk(KERN_DEBUG "snd_gf1_dram_setmem - GF1!!!\n"); -#endif - addr &= ~1; - count >>= 1; - port = GUSP(gus, GF1DATALOW); - spin_lock_irqsave(&gus->reg_lock, flags); - outb(SNDRV_GF1_GW_DRAM_IO_LOW, gus->gf1.reg_regsel); - mb(); - outw((unsigned short) addr, gus->gf1.reg_data16); - mb(); - outb(SNDRV_GF1_GB_DRAM_IO_HIGH, gus->gf1.reg_regsel); - mb(); - outb((unsigned char) (addr >> 16), gus->gf1.reg_data8); - mb(); - outb(SNDRV_GF1_GW_DRAM_IO16, gus->gf1.reg_regsel); - while (count--) - outw(value, port); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -#endif /* 0 */ - -void snd_gf1_select_active_voices(struct snd_gus_card * gus) -{ - unsigned short voices; - - static unsigned short voices_tbl[32 - 14 + 1] = - { - 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843, - 25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293 - }; - - voices = gus->gf1.active_voices; - if (voices > 32) - voices = 32; - if (voices < 14) - voices = 14; - if (gus->gf1.enh_mode) - voices = 32; - gus->gf1.active_voices = voices; - gus->gf1.playback_freq = - gus->gf1.enh_mode ? 44100 : voices_tbl[voices - 14]; - if (!gus->gf1.enh_mode) { - snd_gf1_i_write8(gus, SNDRV_GF1_GB_ACTIVE_VOICES, 0xc0 | (voices - 1)); - udelay(100); - } -} - -#ifdef CONFIG_SND_DEBUG - -void snd_gf1_print_voice_registers(struct snd_gus_card * gus) -{ - unsigned char mode; - int voice, ctrl; - - voice = gus->gf1.active_voice; - printk(KERN_INFO " -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n", voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d)); - printk(KERN_INFO " -%i- GF1 frequency = 0x%x\n", voice, snd_gf1_i_read16(gus, 1)); - printk(KERN_INFO " -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4), snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4), snd_gf1_i_read_addr(gus, 4, ctrl & 4), snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4)); - printk(KERN_INFO " -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n", voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8), snd_gf1_i_read8(gus, 6)); - printk(KERN_INFO" -%i- GF1 volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 9)); - printk(KERN_INFO " -%i- GF1 position = 0x%x (0x%x)\n", voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4), snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4)); - if (gus->interwave && snd_gf1_i_read8(gus, 0x19) & 0x01) { /* enhanced mode */ - mode = snd_gf1_i_read8(gus, 0x15); - printk(KERN_INFO " -%i- GFA1 mode = 0x%x\n", voice, mode); - if (mode & 0x01) { /* Effect processor */ - printk(KERN_INFO " -%i- GFA1 effect address = 0x%x\n", voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4)); - printk(KERN_INFO " -%i- GFA1 effect volume = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x16)); - printk(KERN_INFO " -%i- GFA1 effect volume final = 0x%x\n", voice, snd_gf1_i_read16(gus, 0x1d)); - printk(KERN_INFO " -%i- GFA1 effect acumulator = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x14)); - } - if (mode & 0x20) { - printk(KERN_INFO " -%i- GFA1 left offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x13), snd_gf1_i_read16(gus, 0x13) >> 4); - printk(KERN_INFO " -%i- GFA1 left offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1c), snd_gf1_i_read16(gus, 0x1c) >> 4); - printk(KERN_INFO " -%i- GFA1 right offset = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x0c), snd_gf1_i_read16(gus, 0x0c) >> 4); - printk(KERN_INFO " -%i- GFA1 right offset final = 0x%x (%i)\n", voice, snd_gf1_i_read16(gus, 0x1b), snd_gf1_i_read16(gus, 0x1b) >> 4); - } else - printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); - } else - printk(KERN_INFO " -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); -} - -#if 0 - -void snd_gf1_print_global_registers(struct snd_gus_card * gus) -{ - unsigned char global_mode = 0x00; - - printk(KERN_INFO " -G- GF1 active voices = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES)); - if (gus->interwave) { - global_mode = snd_gf1_i_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE); - printk(KERN_INFO " -G- GF1 global mode = 0x%x\n", global_mode); - } - if (global_mode & 0x02) /* LFO enabled? */ - printk(KERN_INFO " -G- GF1 LFO base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE)); - printk(KERN_INFO " -G- GF1 voices IRQ read = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ)); - printk(KERN_INFO " -G- GF1 DRAM DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL)); - printk(KERN_INFO " -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW)); - printk(KERN_INFO " -G- GF1 DRAM IO high/low = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH), snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW)); - if (!gus->interwave) - printk(KERN_INFO " -G- GF1 record DMA control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL)); - printk(KERN_INFO " -G- GF1 DRAM IO 16 = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16)); - if (gus->gf1.enh_mode) { - printk(KERN_INFO " -G- GFA1 memory config = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG)); - printk(KERN_INFO " -G- GFA1 memory control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL)); - printk(KERN_INFO " -G- GFA1 FIFO record base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR)); - printk(KERN_INFO " -G- GFA1 FIFO playback base = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR)); - printk(KERN_INFO " -G- GFA1 interleave control = 0x%x\n", snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE)); - } -} - -void snd_gf1_print_setup_registers(struct snd_gus_card * gus) -{ - printk(KERN_INFO " -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG))); - printk(KERN_INFO " -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT))); - printk(KERN_INFO " -S- timer control = 0x%x\n", inb(GUSP(gus, TIMERCNTRL))); - printk(KERN_INFO " -S- timer data = 0x%x\n", inb(GUSP(gus, TIMERDATA))); - printk(KERN_INFO " -S- status read = 0x%x\n", inb(GUSP(gus, REGCNTRLS))); - printk(KERN_INFO " -S- Sound Blaster control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL)); - printk(KERN_INFO " -S- AdLib timer 1/2 = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1), snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2)); - printk(KERN_INFO " -S- reset = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)); - if (gus->interwave) { - printk(KERN_INFO " -S- compatibility = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY)); - printk(KERN_INFO " -S- decode control = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL)); - printk(KERN_INFO " -S- version number = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER)); - printk(KERN_INFO " -S- MPU-401 emul. control A/B = 0x%x/0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A), snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B)); - printk(KERN_INFO " -S- emulation IRQ = 0x%x\n", snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ)); - } -} - -void snd_gf1_peek_print_block(struct snd_gus_card * gus, unsigned int addr, int count, int w_16bit) -{ - if (!w_16bit) { - while (count-- > 0) - printk(count > 0 ? "%02x:" : "%02x", snd_gf1_peek(gus, addr++)); - } else { - while (count-- > 0) { - printk(count > 0 ? "%04x:" : "%04x", snd_gf1_peek(gus, addr) | (snd_gf1_peek(gus, addr + 1) << 8)); - addr += 2; - } - } -} - -#endif /* 0 */ - -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_irq.c b/ANDROID_3.4.5/sound/isa/gus/gus_irq.c deleted file mode 100644 index 2055aff7..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_irq.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Routine for IRQ handling from GF1/InterWave chip - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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 <sound/core.h> -#include <sound/info.h> -#include <sound/gus.h> - -#ifdef CONFIG_SND_DEBUG -#define STAT_ADD(x) ((x)++) -#else -#define STAT_ADD(x) while (0) { ; } -#endif - -irqreturn_t snd_gus_interrupt(int irq, void *dev_id) -{ - struct snd_gus_card * gus = dev_id; - unsigned char status; - int loop = 100; - int handled = 0; - -__again: - status = inb(gus->gf1.reg_irqstat); - if (status == 0) - return IRQ_RETVAL(handled); - handled = 1; - /* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */ - if (status & 0x02) { - STAT_ADD(gus->gf1.interrupt_stat_midi_in); - if (gus->gf1.interrupt_handler_midi_in) - gus->gf1.interrupt_handler_midi_in(gus); - } - if (status & 0x01) { - STAT_ADD(gus->gf1.interrupt_stat_midi_out); - if (gus->gf1.interrupt_handler_midi_out) - gus->gf1.interrupt_handler_midi_out(gus); - } - if (status & (0x20 | 0x40)) { - unsigned int already, _current_; - unsigned char voice_status, voice; - struct snd_gus_voice *pvoice; - - already = 0; - while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) { - voice = voice_status & 0x1f; - _current_ = 1 << voice; - if (already & _current_) - continue; /* multi request */ - already |= _current_; /* mark request */ -#if 0 - printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, " - "voice_verify = %i\n", - voice, voice_status, inb(GUSP(gus, GF1PAGE))); -#endif - pvoice = &gus->gf1.voices[voice]; - if (pvoice->use) { - if (!(voice_status & 0x80)) { /* voice position IRQ */ - STAT_ADD(pvoice->interrupt_stat_wave); - pvoice->handler_wave(gus, pvoice); - } - if (!(voice_status & 0x40)) { /* volume ramp IRQ */ - STAT_ADD(pvoice->interrupt_stat_volume); - pvoice->handler_volume(gus, pvoice); - } - } else { - STAT_ADD(gus->gf1.interrupt_stat_voice_lost); - snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - } - } - } - if (status & 0x04) { - STAT_ADD(gus->gf1.interrupt_stat_timer1); - if (gus->gf1.interrupt_handler_timer1) - gus->gf1.interrupt_handler_timer1(gus); - } - if (status & 0x08) { - STAT_ADD(gus->gf1.interrupt_stat_timer2); - if (gus->gf1.interrupt_handler_timer2) - gus->gf1.interrupt_handler_timer2(gus); - } - if (status & 0x80) { - if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { - STAT_ADD(gus->gf1.interrupt_stat_dma_write); - if (gus->gf1.interrupt_handler_dma_write) - gus->gf1.interrupt_handler_dma_write(gus); - } - if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { - STAT_ADD(gus->gf1.interrupt_stat_dma_read); - if (gus->gf1.interrupt_handler_dma_read) - gus->gf1.interrupt_handler_dma_read(gus); - } - } - if (--loop > 0) - goto __again; - return IRQ_NONE; -} - -#ifdef CONFIG_SND_DEBUG -static void snd_gus_irq_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_gus_card *gus; - struct snd_gus_voice *pvoice; - int idx; - - gus = entry->private_data; - snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out); - snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in); - snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1); - snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2); - snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write); - snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read); - snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost); - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n", - idx, - pvoice->interrupt_stat_wave, - pvoice->interrupt_stat_volume); - } -} - -void snd_gus_irq_profile_init(struct snd_gus_card *gus) -{ - struct snd_info_entry *entry; - - if (! snd_card_proc_new(gus->card, "gusirq", &entry)) - snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read); -} - -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_main.c b/ANDROID_3.4.5/sound/isa/gus/gus_main.c deleted file mode 100644 index 4490ee44..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_main.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Routines for Gravis UltraSound soundcards - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/delay.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/gus.h> -#include <sound/control.h> - -#include <asm/dma.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards"); -MODULE_LICENSE("GPL"); - -static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches); - -int snd_gus_use_inc(struct snd_gus_card * gus) -{ - if (!try_module_get(gus->card->module)) - return 0; - return 1; -} - -void snd_gus_use_dec(struct snd_gus_card * gus) -{ - module_put(gus->card->module); -} - -static int snd_gus_joystick_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 = 31; - return 0; -} - -static int snd_gus_joystick_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = gus->joystick_dac & 31; - return 0; -} - -static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval; - - nval = ucontrol->value.integer.value[0] & 31; - spin_lock_irqsave(&gus->reg_lock, flags); - change = gus->joystick_dac != nval; - gus->joystick_dac = nval; - snd_gf1_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_gus_joystick_control = { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "Joystick Speed", - .info = snd_gus_joystick_info, - .get = snd_gus_joystick_get, - .put = snd_gus_joystick_put -}; - -static void snd_gus_init_control(struct snd_gus_card *gus) -{ - if (!gus->ace_flag) - snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus)); -} - -/* - * - */ - -static int snd_gus_free(struct snd_gus_card *gus) -{ - if (gus->gf1.res_port2 == NULL) - goto __hw_end; - snd_gf1_stop(gus); - snd_gus_init_dma_irq(gus, 0); - __hw_end: - release_and_free_resource(gus->gf1.res_port1); - release_and_free_resource(gus->gf1.res_port2); - if (gus->gf1.irq >= 0) - free_irq(gus->gf1.irq, (void *) gus); - if (gus->gf1.dma1 >= 0) { - disable_dma(gus->gf1.dma1); - free_dma(gus->gf1.dma1); - } - if (!gus->equal_dma && gus->gf1.dma2 >= 0) { - disable_dma(gus->gf1.dma2); - free_dma(gus->gf1.dma2); - } - kfree(gus); - return 0; -} - -static int snd_gus_dev_free(struct snd_device *device) -{ - struct snd_gus_card *gus = device->device_data; - return snd_gus_free(gus); -} - -int snd_gus_create(struct snd_card *card, - unsigned long port, - int irq, int dma1, int dma2, - int timer_dev, - int voices, - int pcm_channels, - int effect, - struct snd_gus_card **rgus) -{ - struct snd_gus_card *gus; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_gus_dev_free, - }; - - *rgus = NULL; - gus = kzalloc(sizeof(*gus), GFP_KERNEL); - if (gus == NULL) - return -ENOMEM; - spin_lock_init(&gus->reg_lock); - spin_lock_init(&gus->voice_alloc); - spin_lock_init(&gus->active_voice_lock); - spin_lock_init(&gus->event_lock); - spin_lock_init(&gus->dma_lock); - spin_lock_init(&gus->pcm_volume_level_lock); - spin_lock_init(&gus->uart_cmd_lock); - mutex_init(&gus->dma_mutex); - gus->gf1.irq = -1; - gus->gf1.dma1 = -1; - gus->gf1.dma2 = -1; - gus->card = card; - gus->gf1.port = port; - /* fill register variables for speedup */ - gus->gf1.reg_page = GUSP(gus, GF1PAGE); - gus->gf1.reg_regsel = GUSP(gus, GF1REGSEL); - gus->gf1.reg_data8 = GUSP(gus, GF1DATAHIGH); - gus->gf1.reg_data16 = GUSP(gus, GF1DATALOW); - gus->gf1.reg_irqstat = GUSP(gus, IRQSTAT); - gus->gf1.reg_dram = GUSP(gus, DRAM); - gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL); - gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA); - /* allocate resources */ - if ((gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)")) == NULL) { - snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port); - snd_gus_free(gus); - return -EBUSY; - } - if ((gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)")) == NULL) { - snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100); - snd_gus_free(gus); - return -EBUSY; - } - if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) { - snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); - snd_gus_free(gus); - return -EBUSY; - } - gus->gf1.irq = irq; - if (request_dma(dma1, "GUS - 1")) { - snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1); - snd_gus_free(gus); - return -EBUSY; - } - gus->gf1.dma1 = dma1; - if (dma2 >= 0 && dma1 != dma2) { - if (request_dma(dma2, "GUS - 2")) { - snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2); - snd_gus_free(gus); - return -EBUSY; - } - gus->gf1.dma2 = dma2; - } else { - gus->gf1.dma2 = gus->gf1.dma1; - gus->equal_dma = 1; - } - gus->timer_dev = timer_dev; - if (voices < 14) - voices = 14; - if (voices > 32) - voices = 32; - if (pcm_channels < 0) - pcm_channels = 0; - if (pcm_channels > 8) - pcm_channels = 8; - pcm_channels++; - pcm_channels &= ~1; - gus->gf1.effect = effect ? 1 : 0; - gus->gf1.active_voices = voices; - gus->gf1.pcm_channels = pcm_channels; - gus->gf1.volume_ramp = 25; - gus->gf1.smooth_pan = 1; - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { - snd_gus_free(gus); - return err; - } - *rgus = gus; - return 0; -} - -/* - * Memory detection routine for plain GF1 soundcards - */ - -static int snd_gus_detect_memory(struct snd_gus_card * gus) -{ - int l, idx, local; - unsigned char d; - - snd_gf1_poke(gus, 0L, 0xaa); - snd_gf1_poke(gus, 1L, 0x55); - if (snd_gf1_peek(gus, 0L) != 0xaa || snd_gf1_peek(gus, 1L) != 0x55) { - snd_printk(KERN_ERR "plain GF1 card at 0x%lx without onboard DRAM?\n", gus->gf1.port); - return -ENOMEM; - } - for (idx = 1, d = 0xab; idx < 4; idx++, d++) { - local = idx << 18; - snd_gf1_poke(gus, local, d); - snd_gf1_poke(gus, local + 1, d + 1); - if (snd_gf1_peek(gus, local) != d || - snd_gf1_peek(gus, local + 1) != d + 1 || - snd_gf1_peek(gus, 0L) != 0xaa) - break; - } -#if 1 - gus->gf1.memory = idx << 18; -#else - gus->gf1.memory = 256 * 1024; -#endif - for (l = 0, local = gus->gf1.memory; l < 4; l++, local -= 256 * 1024) { - gus->gf1.mem_alloc.banks_8[l].address = - gus->gf1.mem_alloc.banks_8[l].size = 0; - gus->gf1.mem_alloc.banks_16[l].address = l << 18; - gus->gf1.mem_alloc.banks_16[l].size = local > 0 ? 256 * 1024 : 0; - } - gus->gf1.mem_alloc.banks_8[0].size = gus->gf1.memory; - return 0; /* some memory were detected */ -} - -static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches) -{ - struct snd_card *card; - unsigned long flags; - int irq, dma1, dma2; - static unsigned char irqs[16] = - {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7}; - static unsigned char dmas[8] = - {6, 1, 0, 2, 0, 3, 4, 5}; - - if (snd_BUG_ON(!gus)) - return -EINVAL; - card = gus->card; - if (snd_BUG_ON(!card)) - return -EINVAL; - - gus->mix_cntrl_reg &= 0xf8; - gus->mix_cntrl_reg |= 0x01; /* disable MIC, LINE IN, enable LINE OUT */ - if (gus->codec_flag || gus->ess_flag) { - gus->mix_cntrl_reg &= ~1; /* enable LINE IN */ - gus->mix_cntrl_reg |= 4; /* enable MIC */ - } - dma1 = gus->gf1.dma1; - dma1 = abs(dma1); - dma1 = dmas[dma1 & 7]; - dma2 = gus->gf1.dma2; - dma2 = abs(dma2); - dma2 = dmas[dma2 & 7]; - dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3); - - if ((dma1 & 7) == 0 || (dma2 & 7) == 0) { - snd_printk(KERN_ERR "Error! DMA isn't defined.\n"); - return -EINVAL; - } - irq = gus->gf1.irq; - irq = abs(irq); - irq = irqs[irq & 0x0f]; - if (irq == 0) { - snd_printk(KERN_ERR "Error! IRQ isn't defined.\n"); - return -EINVAL; - } - irq |= 0x40; -#if 0 - card->mixer.mix_ctrl_reg |= 0x10; -#endif - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(5, GUSP(gus, REGCNTRLS)); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(0x00, GUSP(gus, IRQDMACNTRLREG)); - outb(0, GUSP(gus, REGCNTRLS)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - - udelay(100); - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(dma1, GUSP(gus, IRQDMACNTRLREG)); - if (latches) { - outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(irq, GUSP(gus, IRQDMACNTRLREG)); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - - udelay(100); - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x00 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(dma1, GUSP(gus, IRQDMACNTRLREG)); - if (latches) { - outb(0x40 | gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(irq, GUSP(gus, IRQDMACNTRLREG)); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - - snd_gf1_delay(gus); - - if (latches) - gus->mix_cntrl_reg |= 0x08; /* enable latches */ - else - gus->mix_cntrl_reg &= ~0x08; /* disable latches */ - spin_lock_irqsave(&gus->reg_lock, flags); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - outb(0, GUSP(gus, GF1PAGE)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - - return 0; -} - -static int snd_gus_check_version(struct snd_gus_card * gus) -{ - unsigned long flags; - unsigned char val, rev; - struct snd_card *card; - - card = gus->card; - spin_lock_irqsave(&gus->reg_lock, flags); - outb(0x20, GUSP(gus, REGCNTRLS)); - val = inb(GUSP(gus, REGCNTRLS)); - rev = inb(GUSP(gus, BOARDVERSION)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - snd_printdd("GF1 [0x%lx] init - val = 0x%x, rev = 0x%x\n", gus->gf1.port, val, rev); - strcpy(card->driver, "GUS"); - strcpy(card->longname, "Gravis UltraSound Classic (2.4)"); - if ((val != 255 && (val & 0x06)) || (rev >= 5 && rev != 255)) { - if (rev >= 5 && rev <= 9) { - gus->ics_flag = 1; - if (rev == 5) - gus->ics_flipped = 1; - card->longname[27] = '3'; - card->longname[29] = rev == 5 ? '5' : '7'; - } - if (rev >= 10 && rev != 255) { - if (rev >= 10 && rev <= 11) { - strcpy(card->driver, "GUS MAX"); - strcpy(card->longname, "Gravis UltraSound MAX"); - gus->max_flag = 1; - } else if (rev == 0x30) { - strcpy(card->driver, "GUS ACE"); - strcpy(card->longname, "Gravis UltraSound Ace"); - gus->ace_flag = 1; - } else if (rev == 0x50) { - strcpy(card->driver, "GUS Extreme"); - strcpy(card->longname, "Gravis UltraSound Extreme"); - gus->ess_flag = 1; - } else { - snd_printk(KERN_ERR "unknown GF1 revision number at 0x%lx - 0x%x (0x%x)\n", gus->gf1.port, rev, val); - snd_printk(KERN_ERR " please - report to <perex@perex.cz>\n"); - } - } - } - strcpy(card->shortname, card->longname); - gus->uart_enable = 1; /* standard GUSes doesn't have midi uart trouble */ - snd_gus_init_control(gus); - return 0; -} - -int snd_gus_initialize(struct snd_gus_card *gus) -{ - int err; - - if (!gus->interwave) { - if ((err = snd_gus_check_version(gus)) < 0) { - snd_printk(KERN_ERR "version check failed\n"); - return err; - } - if ((err = snd_gus_detect_memory(gus)) < 0) - return err; - } - if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) - return err; - snd_gf1_start(gus); - gus->initialized = 1; - return 0; -} - - /* gus_io.c */ -EXPORT_SYMBOL(snd_gf1_delay); -EXPORT_SYMBOL(snd_gf1_write8); -EXPORT_SYMBOL(snd_gf1_look8); -EXPORT_SYMBOL(snd_gf1_write16); -EXPORT_SYMBOL(snd_gf1_look16); -EXPORT_SYMBOL(snd_gf1_i_write8); -EXPORT_SYMBOL(snd_gf1_i_look8); -EXPORT_SYMBOL(snd_gf1_i_look16); -EXPORT_SYMBOL(snd_gf1_dram_addr); -EXPORT_SYMBOL(snd_gf1_write_addr); -EXPORT_SYMBOL(snd_gf1_poke); -EXPORT_SYMBOL(snd_gf1_peek); - /* gus_reset.c */ -EXPORT_SYMBOL(snd_gf1_alloc_voice); -EXPORT_SYMBOL(snd_gf1_free_voice); -EXPORT_SYMBOL(snd_gf1_ctrl_stop); -EXPORT_SYMBOL(snd_gf1_stop_voice); - /* gus_mixer.c */ -EXPORT_SYMBOL(snd_gf1_new_mixer); - /* gus_pcm.c */ -EXPORT_SYMBOL(snd_gf1_pcm_new); - /* gus.c */ -EXPORT_SYMBOL(snd_gus_use_inc); -EXPORT_SYMBOL(snd_gus_use_dec); -EXPORT_SYMBOL(snd_gus_create); -EXPORT_SYMBOL(snd_gus_initialize); - /* gus_irq.c */ -EXPORT_SYMBOL(snd_gus_interrupt); - /* gus_uart.c */ -EXPORT_SYMBOL(snd_gf1_rawmidi_new); - /* gus_dram.c */ -EXPORT_SYMBOL(snd_gus_dram_write); -EXPORT_SYMBOL(snd_gus_dram_read); - /* gus_volume.c */ -EXPORT_SYMBOL(snd_gf1_lvol_to_gvol_raw); -EXPORT_SYMBOL(snd_gf1_translate_freq); - /* gus_mem.c */ -EXPORT_SYMBOL(snd_gf1_mem_alloc); -EXPORT_SYMBOL(snd_gf1_mem_xfree); -EXPORT_SYMBOL(snd_gf1_mem_free); -EXPORT_SYMBOL(snd_gf1_mem_lock); - -/* - * INIT part - */ - -static int __init alsa_gus_init(void) -{ - return 0; -} - -static void __exit alsa_gus_exit(void) -{ -} - -module_init(alsa_gus_init) -module_exit(alsa_gus_exit) diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_mem.c b/ANDROID_3.4.5/sound/isa/gus/gus_mem.c deleted file mode 100644 index af888a02..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_mem.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * GUS's memory allocation routines / bottom layer - * - * - * 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/string.h> -#include <sound/core.h> -#include <sound/gus.h> -#include <sound/info.h> - -#ifdef CONFIG_SND_DEBUG -static void snd_gf1_mem_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer); -#endif - -void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup) -{ - if (!xup) { - mutex_lock(&alloc->memory_mutex); - } else { - mutex_unlock(&alloc->memory_mutex); - } -} - -static struct snd_gf1_mem_block *snd_gf1_mem_xalloc(struct snd_gf1_mem * alloc, - struct snd_gf1_mem_block * block) -{ - struct snd_gf1_mem_block *pblock, *nblock; - - nblock = kmalloc(sizeof(struct snd_gf1_mem_block), GFP_KERNEL); - if (nblock == NULL) - return NULL; - *nblock = *block; - pblock = alloc->first; - while (pblock) { - if (pblock->ptr > nblock->ptr) { - nblock->prev = pblock->prev; - nblock->next = pblock; - pblock->prev = nblock; - if (pblock == alloc->first) - alloc->first = nblock; - else - nblock->prev->next = nblock; - mutex_unlock(&alloc->memory_mutex); - return NULL; - } - pblock = pblock->next; - } - nblock->next = NULL; - if (alloc->last == NULL) { - nblock->prev = NULL; - alloc->first = alloc->last = nblock; - } else { - nblock->prev = alloc->last; - alloc->last->next = nblock; - alloc->last = nblock; - } - return nblock; -} - -int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block) -{ - if (block->share) { /* ok.. shared block */ - block->share--; - mutex_unlock(&alloc->memory_mutex); - return 0; - } - if (alloc->first == block) { - alloc->first = block->next; - if (block->next) - block->next->prev = NULL; - } else { - block->prev->next = block->next; - if (block->next) - block->next->prev = block->prev; - } - if (alloc->last == block) { - alloc->last = block->prev; - if (block->prev) - block->prev->next = NULL; - } else { - block->next->prev = block->prev; - if (block->prev) - block->prev->next = block->next; - } - kfree(block->name); - kfree(block); - return 0; -} - -static struct snd_gf1_mem_block *snd_gf1_mem_look(struct snd_gf1_mem * alloc, - unsigned int address) -{ - struct snd_gf1_mem_block *block; - - for (block = alloc->first; block; block = block->next) { - if (block->ptr == address) { - return block; - } - } - return NULL; -} - -static struct snd_gf1_mem_block *snd_gf1_mem_share(struct snd_gf1_mem * alloc, - unsigned int *share_id) -{ - struct snd_gf1_mem_block *block; - - if (!share_id[0] && !share_id[1] && - !share_id[2] && !share_id[3]) - return NULL; - for (block = alloc->first; block; block = block->next) - if (!memcmp(share_id, block->share_id, - sizeof(block->share_id))) - return block; - return NULL; -} - -static int snd_gf1_mem_find(struct snd_gf1_mem * alloc, - struct snd_gf1_mem_block * block, - unsigned int size, int w_16, int align) -{ - struct snd_gf1_bank_info *info = w_16 ? alloc->banks_16 : alloc->banks_8; - unsigned int idx, boundary; - int size1; - struct snd_gf1_mem_block *pblock; - unsigned int ptr1, ptr2; - - if (w_16 && align < 2) - align = 2; - block->flags = w_16 ? SNDRV_GF1_MEM_BLOCK_16BIT : 0; - block->owner = SNDRV_GF1_MEM_OWNER_DRIVER; - block->share = 0; - block->share_id[0] = block->share_id[1] = - block->share_id[2] = block->share_id[3] = 0; - block->name = NULL; - block->prev = block->next = NULL; - for (pblock = alloc->first, idx = 0; pblock; pblock = pblock->next) { - while (pblock->ptr >= (boundary = info[idx].address + info[idx].size)) - idx++; - while (pblock->ptr + pblock->size >= (boundary = info[idx].address + info[idx].size)) - idx++; - ptr2 = boundary; - if (pblock->next) { - if (pblock->ptr + pblock->size == pblock->next->ptr) - continue; - if (pblock->next->ptr < boundary) - ptr2 = pblock->next->ptr; - } - ptr1 = ALIGN(pblock->ptr + pblock->size, align); - if (ptr1 >= ptr2) - continue; - size1 = ptr2 - ptr1; - if ((int)size <= size1) { - block->ptr = ptr1; - block->size = size; - return 0; - } - } - while (++idx < 4) { - if (size <= info[idx].size) { - /* I assume that bank address is already aligned.. */ - block->ptr = info[idx].address; - block->size = size; - return 0; - } - } - return -ENOMEM; -} - -struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner, - char *name, int size, int w_16, int align, - unsigned int *share_id) -{ - struct snd_gf1_mem_block block, *nblock; - - snd_gf1_mem_lock(alloc, 0); - if (share_id != NULL) { - nblock = snd_gf1_mem_share(alloc, share_id); - if (nblock != NULL) { - if (size != (int)nblock->size) { - /* TODO: remove in the future */ - snd_printk(KERN_ERR "snd_gf1_mem_alloc - share: sizes differ\n"); - goto __std; - } - nblock->share++; - snd_gf1_mem_lock(alloc, 1); - return NULL; - } - } - __std: - if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) { - snd_gf1_mem_lock(alloc, 1); - return NULL; - } - if (share_id != NULL) - memcpy(&block.share_id, share_id, sizeof(block.share_id)); - block.owner = owner; - block.name = kstrdup(name, GFP_KERNEL); - nblock = snd_gf1_mem_xalloc(alloc, &block); - snd_gf1_mem_lock(alloc, 1); - return nblock; -} - -int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address) -{ - int result; - struct snd_gf1_mem_block *block; - - snd_gf1_mem_lock(alloc, 0); - if ((block = snd_gf1_mem_look(alloc, address)) != NULL) { - result = snd_gf1_mem_xfree(alloc, block); - snd_gf1_mem_lock(alloc, 1); - return result; - } - snd_gf1_mem_lock(alloc, 1); - return -EINVAL; -} - -int snd_gf1_mem_init(struct snd_gus_card * gus) -{ - struct snd_gf1_mem *alloc; - struct snd_gf1_mem_block block; -#ifdef CONFIG_SND_DEBUG - struct snd_info_entry *entry; -#endif - - alloc = &gus->gf1.mem_alloc; - mutex_init(&alloc->memory_mutex); - alloc->first = alloc->last = NULL; - if (!gus->gf1.memory) - return 0; - - memset(&block, 0, sizeof(block)); - block.owner = SNDRV_GF1_MEM_OWNER_DRIVER; - if (gus->gf1.enh_mode) { - block.ptr = 0; - block.size = 1024; - block.name = kstrdup("InterWave LFOs", GFP_KERNEL); - if (snd_gf1_mem_xalloc(alloc, &block) == NULL) - return -ENOMEM; - } - block.ptr = gus->gf1.default_voice_address; - block.size = 4; - block.name = kstrdup("Voice default (NULL's)", GFP_KERNEL); - if (snd_gf1_mem_xalloc(alloc, &block) == NULL) - return -ENOMEM; -#ifdef CONFIG_SND_DEBUG - if (! snd_card_proc_new(gus->card, "gusmem", &entry)) - snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read); -#endif - return 0; -} - -int snd_gf1_mem_done(struct snd_gus_card * gus) -{ - struct snd_gf1_mem *alloc; - struct snd_gf1_mem_block *block, *nblock; - - alloc = &gus->gf1.mem_alloc; - block = alloc->first; - while (block) { - nblock = block->next; - snd_gf1_mem_xfree(alloc, block); - block = nblock; - } - return 0; -} - -#ifdef CONFIG_SND_DEBUG -static void snd_gf1_mem_info_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct snd_gus_card *gus; - struct snd_gf1_mem *alloc; - struct snd_gf1_mem_block *block; - unsigned int total, used; - int i; - - gus = entry->private_data; - alloc = &gus->gf1.mem_alloc; - mutex_lock(&alloc->memory_mutex); - snd_iprintf(buffer, "8-bit banks : \n "); - for (i = 0; i < 4; i++) - snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_8[i].address, alloc->banks_8[i].size >> 10, i + 1 < 4 ? "," : ""); - snd_iprintf(buffer, "\n" - "16-bit banks : \n "); - for (i = total = 0; i < 4; i++) { - snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_16[i].address, alloc->banks_16[i].size >> 10, i + 1 < 4 ? "," : ""); - total += alloc->banks_16[i].size; - } - snd_iprintf(buffer, "\n"); - used = 0; - for (block = alloc->first, i = 0; block; block = block->next, i++) { - used += block->size; - snd_iprintf(buffer, "Block %i at 0x%lx onboard 0x%x size %i (0x%x):\n", i, (long) block, block->ptr, block->size, block->size); - if (block->share || - block->share_id[0] || block->share_id[1] || - block->share_id[2] || block->share_id[3]) - snd_iprintf(buffer, " Share : %i [id0 0x%x] [id1 0x%x] [id2 0x%x] [id3 0x%x]\n", - block->share, - block->share_id[0], block->share_id[1], - block->share_id[2], block->share_id[3]); - snd_iprintf(buffer, " Flags :%s\n", - block->flags & SNDRV_GF1_MEM_BLOCK_16BIT ? " 16-bit" : ""); - snd_iprintf(buffer, " Owner : "); - switch (block->owner) { - case SNDRV_GF1_MEM_OWNER_DRIVER: - snd_iprintf(buffer, "driver - %s\n", block->name); - break; - case SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE: - snd_iprintf(buffer, "SIMPLE wave\n"); - break; - case SNDRV_GF1_MEM_OWNER_WAVE_GF1: - snd_iprintf(buffer, "GF1 wave\n"); - break; - case SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF: - snd_iprintf(buffer, "IWFFFF wave\n"); - break; - default: - snd_iprintf(buffer, "unknown\n"); - } - } - snd_iprintf(buffer, " Total: memory = %i, used = %i, free = %i\n", - total, used, total - used); - mutex_unlock(&alloc->memory_mutex); -#if 0 - ultra_iprintf(buffer, " Verify: free = %i, max 8-bit block = %i, max 16-bit block = %i\n", - ultra_memory_free_size(card, &card->gf1.mem_alloc), - ultra_memory_free_block(card, &card->gf1.mem_alloc, 0), - ultra_memory_free_block(card, &card->gf1.mem_alloc, 1)); -#endif -} -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c b/ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c deleted file mode 100644 index 2ccb3fad..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_mem_proc.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * GUS's memory access via proc filesystem - * - * - * 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 <sound/core.h> -#include <sound/gus.h> -#include <sound/info.h> - -struct gus_proc_private { - int rom; /* data are in ROM */ - unsigned int address; - unsigned int size; - struct snd_gus_card * gus; -}; - -static ssize_t snd_gf1_mem_proc_dump(struct snd_info_entry *entry, - void *file_private_data, - struct file *file, char __user *buf, - size_t count, loff_t pos) -{ - struct gus_proc_private *priv = entry->private_data; - struct snd_gus_card *gus = priv->gus; - int err; - - err = snd_gus_dram_read(gus, buf, pos, count, priv->rom); - if (err < 0) - return err; - return count; -} - -static void snd_gf1_mem_proc_free(struct snd_info_entry *entry) -{ - struct gus_proc_private *priv = entry->private_data; - kfree(priv); -} - -static struct snd_info_entry_ops snd_gf1_mem_proc_ops = { - .read = snd_gf1_mem_proc_dump, -}; - -int snd_gf1_mem_proc_init(struct snd_gus_card * gus) -{ - int idx; - char name[16]; - struct gus_proc_private *priv; - struct snd_info_entry *entry; - - for (idx = 0; idx < 4; idx++) { - if (gus->gf1.mem_alloc.banks_8[idx].size > 0) { - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - priv->gus = gus; - sprintf(name, "gus-ram-%i", idx); - if (! snd_card_proc_new(gus->card, name, &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = priv; - entry->private_free = snd_gf1_mem_proc_free; - entry->c.ops = &snd_gf1_mem_proc_ops; - priv->address = gus->gf1.mem_alloc.banks_8[idx].address; - priv->size = entry->size = gus->gf1.mem_alloc.banks_8[idx].size; - } - } - } - for (idx = 0; idx < 4; idx++) { - if (gus->gf1.rom_present & (1 << idx)) { - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - priv->rom = 1; - priv->gus = gus; - sprintf(name, "gus-rom-%i", idx); - if (! snd_card_proc_new(gus->card, name, &entry)) { - entry->content = SNDRV_INFO_CONTENT_DATA; - entry->private_data = priv; - entry->private_free = snd_gf1_mem_proc_free; - entry->c.ops = &snd_gf1_mem_proc_ops; - priv->address = idx * 4096 * 1024; - priv->size = entry->size = gus->gf1.rom_memory; - } - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_mixer.c b/ANDROID_3.4.5/sound/isa/gus/gus_mixer.c deleted file mode 100644 index 0dd43414..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_mixer.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of ICS 2101 chip and "mixer" in GF1 chip - * - * - * 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/wait.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/gus.h> - -/* - * - */ - -#define GF1_SINGLE(xname, xindex, shift, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_gf1_info_single, \ - .get = snd_gf1_get_single, .put = snd_gf1_put_single, \ - .private_value = shift | (invert << 8) } - -#define snd_gf1_info_single snd_ctl_boolean_mono_info - -static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - - ucontrol->value.integer.value[0] = (gus->mix_cntrl_reg >> shift) & 1; - if (invert) - ucontrol->value.integer.value[0] ^= 1; - return 0; -} - -static int snd_gf1_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int shift = kcontrol->private_value & 0xff; - int invert = (kcontrol->private_value >> 8) & 1; - int change; - unsigned char oval, nval; - - nval = ucontrol->value.integer.value[0] & 1; - if (invert) - nval ^= 1; - nval <<= shift; - spin_lock_irqsave(&gus->reg_lock, flags); - oval = gus->mix_cntrl_reg; - nval = (oval & ~(1 << shift)) | nval; - change = nval != oval; - outb(gus->mix_cntrl_reg = nval, GUSP(gus, MIXCNTRLREG)); - outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return change; -} - -#define ICS_DOUBLE(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_ics_info_double, \ - .get = snd_ics_get_double, .put = snd_ics_put_double, \ - .private_value = addr } - -static int snd_ics_info_double(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 = 127; - return 0; -} - -static int snd_ics_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int addr = kcontrol->private_value & 0xff; - unsigned char left, right; - - spin_lock_irqsave(&gus->reg_lock, flags); - left = gus->gf1.ics_regs[addr][0]; - right = gus->gf1.ics_regs[addr][1]; - spin_unlock_irqrestore(&gus->reg_lock, flags); - ucontrol->value.integer.value[0] = left & 127; - ucontrol->value.integer.value[1] = right & 127; - return 0; -} - -static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int addr = kcontrol->private_value & 0xff; - int change; - unsigned char val1, val2, oval1, oval2, tmp; - - val1 = ucontrol->value.integer.value[0] & 127; - val2 = ucontrol->value.integer.value[1] & 127; - spin_lock_irqsave(&gus->reg_lock, flags); - oval1 = gus->gf1.ics_regs[addr][0]; - oval2 = gus->gf1.ics_regs[addr][1]; - change = val1 != oval1 || val2 != oval2; - gus->gf1.ics_regs[addr][0] = val1; - gus->gf1.ics_regs[addr][1] = val2; - if (gus->ics_flag && gus->ics_flipped && - (addr == SNDRV_ICS_GF1_DEV || addr == SNDRV_ICS_MASTER_DEV)) { - tmp = val1; - val1 = val2; - val2 = tmp; - } - addr <<= 3; - outb(addr | 0, GUSP(gus, MIXCNTRLPORT)); - outb(1, GUSP(gus, MIXDATAPORT)); - outb(addr | 2, GUSP(gus, MIXCNTRLPORT)); - outb((unsigned char) val1, GUSP(gus, MIXDATAPORT)); - outb(addr | 1, GUSP(gus, MIXCNTRLPORT)); - outb(2, GUSP(gus, MIXDATAPORT)); - outb(addr | 3, GUSP(gus, MIXCNTRLPORT)); - outb((unsigned char) val2, GUSP(gus, MIXDATAPORT)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_gf1_controls[] = { -GF1_SINGLE("Master Playback Switch", 0, 1, 1), -GF1_SINGLE("Line Switch", 0, 0, 1), -GF1_SINGLE("Mic Switch", 0, 2, 0) -}; - -static struct snd_kcontrol_new snd_ics_controls[] = { -GF1_SINGLE("Master Playback Switch", 0, 1, 1), -ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV), -ICS_DOUBLE("Synth Playback Volume", 0, SNDRV_ICS_GF1_DEV), -GF1_SINGLE("Line Switch", 0, 0, 1), -ICS_DOUBLE("Line Playback Volume", 0, SNDRV_ICS_LINE_DEV), -GF1_SINGLE("Mic Switch", 0, 2, 0), -ICS_DOUBLE("Mic Playback Volume", 0, SNDRV_ICS_MIC_DEV), -ICS_DOUBLE("CD Playback Volume", 0, SNDRV_ICS_CD_DEV) -}; - -int snd_gf1_new_mixer(struct snd_gus_card * gus) -{ - struct snd_card *card; - unsigned int idx, max; - int err; - - if (snd_BUG_ON(!gus)) - return -EINVAL; - card = gus->card; - if (snd_BUG_ON(!card)) - return -EINVAL; - - if (gus->ics_flag) - snd_component_add(card, "ICS2101"); - if (card->mixername[0] == '\0') { - strcpy(card->mixername, gus->ics_flag ? "GF1,ICS2101" : "GF1"); - } else { - if (gus->ics_flag) - strcat(card->mixername, ",ICS2101"); - strcat(card->mixername, ",GF1"); - } - - if (!gus->ics_flag) { - max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls); - for (idx = 0; idx < max; idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0) - return err; - } - } else { - for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0) - return err; - } - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_pcm.c b/ANDROID_3.4.5/sound/isa/gus/gus_pcm.c deleted file mode 100644 index 2dcf45bf..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_pcm.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of GF1 chip (PCM things) - * - * InterWave chips supports interleaved DMA, but this feature isn't used in - * this code. - * - * This code emulates autoinit DMA transfer for playback, recording by GF1 - * chip doesn't support autoinit DMA. - * - * - * 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 <asm/dma.h> -#include <linux/slab.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/gus.h> -#include <sound/pcm_params.h> -#include "gus_tables.h" - -/* maximum rate */ - -#define SNDRV_GF1_PCM_RATE 48000 - -#define SNDRV_GF1_PCM_PFLG_NONE 0 -#define SNDRV_GF1_PCM_PFLG_ACTIVE (1<<0) -#define SNDRV_GF1_PCM_PFLG_NEUTRAL (2<<0) - -struct gus_pcm_private { - struct snd_gus_card * gus; - struct snd_pcm_substream *substream; - spinlock_t lock; - unsigned int voices; - struct snd_gus_voice *pvoices[2]; - unsigned int memory; - unsigned short flags; - unsigned char voice_ctrl, ramp_ctrl; - unsigned int bpos; - unsigned int blocks; - unsigned int block_size; - unsigned int dma_size; - wait_queue_head_t sleep; - atomic_t dma_count; - int final_volume; -}; - -static int snd_gf1_pcm_use_dma = 1; - -static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data) -{ - struct gus_pcm_private *pcmp = private_data; - - if (pcmp) { - atomic_dec(&pcmp->dma_count); - wake_up(&pcmp->sleep); - } -} - -static int snd_gf1_pcm_block_change(struct snd_pcm_substream *substream, - unsigned int offset, - unsigned int addr, - unsigned int count) -{ - struct snd_gf1_dma_block block; - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - count += offset & 31; - offset &= ~31; - /* - snd_printk(KERN_DEBUG "block change - offset = 0x%x, count = 0x%x\n", - offset, count); - */ - memset(&block, 0, sizeof(block)); - block.cmd = SNDRV_GF1_DMA_IRQ; - if (snd_pcm_format_unsigned(runtime->format)) - block.cmd |= SNDRV_GF1_DMA_UNSIGNED; - if (snd_pcm_format_width(runtime->format) == 16) - block.cmd |= SNDRV_GF1_DMA_16BIT; - block.addr = addr & ~31; - block.buffer = runtime->dma_area + offset; - block.buf_addr = runtime->dma_addr + offset; - block.count = count; - block.private_data = pcmp; - block.ack = snd_gf1_pcm_block_change_ack; - if (!snd_gf1_dma_transfer_block(pcmp->gus, &block, 0, 0)) - atomic_inc(&pcmp->dma_count); - return 0; -} - -static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - struct snd_gus_card * gus = pcmp->gus; - unsigned long flags; - unsigned char voice_ctrl, ramp_ctrl; - unsigned short rate; - unsigned int curr, begin, end; - unsigned short vol; - unsigned char pan; - unsigned int voice; - - spin_lock_irqsave(&pcmp->lock, flags); - if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) { - spin_unlock_irqrestore(&pcmp->lock, flags); - return; - } - pcmp->flags |= SNDRV_GF1_PCM_PFLG_ACTIVE; - pcmp->final_volume = 0; - spin_unlock_irqrestore(&pcmp->lock, flags); - rate = snd_gf1_translate_freq(gus, runtime->rate << 4); - /* enable WAVE IRQ */ - voice_ctrl = snd_pcm_format_width(runtime->format) == 16 ? 0x24 : 0x20; - /* enable RAMP IRQ + rollover */ - ramp_ctrl = 0x24; - if (pcmp->blocks == 1) { - voice_ctrl |= 0x08; /* loop enable */ - ramp_ctrl &= ~0x04; /* disable rollover */ - } - for (voice = 0; voice < pcmp->voices; voice++) { - begin = pcmp->memory + voice * (pcmp->dma_size / runtime->channels); - curr = begin + (pcmp->bpos * pcmp->block_size) / runtime->channels; - end = curr + (pcmp->block_size / runtime->channels); - end -= snd_pcm_format_width(runtime->format) == 16 ? 2 : 1; - /* - snd_printk(KERN_DEBUG "init: curr=0x%x, begin=0x%x, end=0x%x, " - "ctrl=0x%x, ramp=0x%x, rate=0x%x\n", - curr, begin, end, voice_ctrl, ramp_ctrl, rate); - */ - pan = runtime->channels == 2 ? (!voice ? 1 : 14) : 8; - vol = !voice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); - snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, pan); - snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, rate); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, begin << 4, voice_ctrl & 4); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, curr << 4, voice_ctrl & 4); - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME << 4); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0x2f); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, vol >> 8); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - if (!gus->gf1.enh_mode) { - snd_gf1_delay(gus); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - } - spin_lock_irqsave(&gus->reg_lock, flags); - for (voice = 0; voice < pcmp->voices; voice++) { - snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); - if (gus->gf1.enh_mode) - snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, 0x00); /* deactivate voice */ - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - voice_ctrl &= ~0x20; - } - voice_ctrl |= 0x20; - if (!gus->gf1.enh_mode) { - snd_gf1_delay(gus); - for (voice = 0; voice < pcmp->voices; voice++) { - snd_gf1_select_voice(gus, pcmp->pvoices[voice]->number); - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - voice_ctrl &= ~0x20; /* disable IRQ for next voice */ - } - } - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus, - struct snd_gus_voice *pvoice) -{ - struct gus_pcm_private * pcmp; - struct snd_pcm_runtime *runtime; - unsigned char voice_ctrl, ramp_ctrl; - unsigned int idx; - unsigned int end, step; - - if (!pvoice->private_data) { - snd_printd("snd_gf1_pcm: unknown wave irq?\n"); - snd_gf1_smart_stop_voice(gus, pvoice->number); - return; - } - pcmp = pvoice->private_data; - if (pcmp == NULL) { - snd_printd("snd_gf1_pcm: unknown wave irq?\n"); - snd_gf1_smart_stop_voice(gus, pvoice->number); - return; - } - gus = pcmp->gus; - runtime = pcmp->substream->runtime; - - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & ~0x8b; - ramp_ctrl = (snd_gf1_read8(gus, SNDRV_GF1_VB_VOLUME_CONTROL) & ~0xa4) | 0x03; -#if 0 - snd_gf1_select_voice(gus, pvoice->number); - printk(KERN_DEBUG "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); - snd_gf1_select_voice(gus, pcmp->pvoices[1]->number); - printk(KERN_DEBUG "position = 0x%x\n", - (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4)); - snd_gf1_select_voice(gus, pvoice->number); -#endif - pcmp->bpos++; - pcmp->bpos %= pcmp->blocks; - if (pcmp->bpos + 1 >= pcmp->blocks) { /* last block? */ - voice_ctrl |= 0x08; /* enable loop */ - } else { - ramp_ctrl |= 0x04; /* enable rollover */ - } - end = pcmp->memory + (((pcmp->bpos + 1) * pcmp->block_size) / runtime->channels); - end -= voice_ctrl & 4 ? 2 : 1; - step = pcmp->dma_size / runtime->channels; - voice_ctrl |= 0x20; - if (!pcmp->final_volume) { - ramp_ctrl |= 0x20; - ramp_ctrl &= ~0x03; - } - for (idx = 0; idx < pcmp->voices; idx++, end += step) { - snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, end << 4, voice_ctrl & 4); - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - voice_ctrl &= ~0x20; - } - if (!gus->gf1.enh_mode) { - snd_gf1_delay(gus); - voice_ctrl |= 0x20; - for (idx = 0; idx < pcmp->voices; idx++) { - snd_gf1_select_voice(gus, pcmp->pvoices[idx]->number); - snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice_ctrl); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, ramp_ctrl); - voice_ctrl &= ~0x20; - } - } - spin_unlock(&gus->reg_lock); - - snd_pcm_period_elapsed(pcmp->substream); -#if 0 - if ((runtime->flags & SNDRV_PCM_FLG_MMAP) && - *runtime->state == SNDRV_PCM_STATE_RUNNING) { - end = pcmp->bpos * pcmp->block_size; - if (runtime->channels > 1) { - snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + (end / 2), pcmp->block_size / 2); - snd_gf1_pcm_block_change(pcmp->substream, end + (pcmp->block_size / 2), pcmp->memory + (pcmp->dma_size / 2) + (end / 2), pcmp->block_size / 2); - } else { - snd_gf1_pcm_block_change(pcmp->substream, end, pcmp->memory + end, pcmp->block_size); - } - } -#endif -} - -static void snd_gf1_pcm_interrupt_volume(struct snd_gus_card * gus, - struct snd_gus_voice * pvoice) -{ - unsigned short vol; - int cvoice; - struct gus_pcm_private *pcmp = pvoice->private_data; - - /* stop ramp, but leave rollover bit untouched */ - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - spin_unlock(&gus->reg_lock); - if (pcmp == NULL) - return; - /* are we active? */ - if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) - return; - /* load real volume - better precision */ - cvoice = pcmp->pvoices[0] == pvoice ? 0 : 1; - if (pcmp->substream == NULL) - return; - vol = !cvoice ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); - pcmp->final_volume = 1; - spin_unlock(&gus->reg_lock); -} - -static void snd_gf1_pcm_volume_change(struct snd_gus_card * gus) -{ -} - -static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, - unsigned int pos, unsigned int count, - int w16, int invert) -{ - unsigned int len; - unsigned long flags; - - /* - printk(KERN_DEBUG - "poke block; buf = 0x%x, pos = %i, count = %i, port = 0x%x\n", - (int)buf, pos, count, gus->gf1.port); - */ - while (count > 0) { - len = count; - if (len > 512) /* limit, to allow IRQ */ - len = 512; - count -= len; - if (gus->interwave) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01 | (invert ? 0x08 : 0x00)); - snd_gf1_dram_addr(gus, pos); - if (w16) { - outb(SNDRV_GF1_GW_DRAM_IO16, GUSP(gus, GF1REGSEL)); - outsw(GUSP(gus, GF1DATALOW), buf, len >> 1); - } else { - outsb(GUSP(gus, DRAM), buf, len); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - buf += 512; - pos += 512; - } else { - invert = invert ? 0x80 : 0x00; - if (w16) { - len >>= 1; - while (len--) { - snd_gf1_poke(gus, pos++, *buf++); - snd_gf1_poke(gus, pos++, *buf++ ^ invert); - } - } else { - while (len--) - snd_gf1_poke(gus, pos++, *buf++ ^ invert); - } - } - if (count > 0 && !in_interrupt()) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - return -EAGAIN; - } - } - return 0; -} - -static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, - int voice, - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int bpos, len; - - bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); - len = samples_to_bytes(runtime, count); - if (snd_BUG_ON(bpos > pcmp->dma_size)) - return -EIO; - if (snd_BUG_ON(bpos + len > pcmp->dma_size)) - return -EIO; - if (copy_from_user(runtime->dma_area + bpos, src, len)) - return -EFAULT; - if (snd_gf1_pcm_use_dma && len > 32) { - return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); - } else { - struct snd_gus_card *gus = pcmp->gus; - int err, w16, invert; - - w16 = (snd_pcm_format_width(runtime->format) == 16); - invert = snd_pcm_format_unsigned(runtime->format); - if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) - return err; - } - return 0; -} - -static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int bpos, len; - - bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); - len = samples_to_bytes(runtime, count); - if (snd_BUG_ON(bpos > pcmp->dma_size)) - return -EIO; - if (snd_BUG_ON(bpos + len > pcmp->dma_size)) - return -EIO; - snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count); - if (snd_gf1_pcm_use_dma && len > 32) { - return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); - } else { - struct snd_gus_card *gus = pcmp->gus; - int err, w16, invert; - - w16 = (snd_pcm_format_width(runtime->format) == 16); - invert = snd_pcm_format_unsigned(runtime->format); - if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) - return err; - } - return 0; -} - -static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - if (err > 0) { /* change */ - struct snd_gf1_mem_block *block; - if (pcmp->memory > 0) { - snd_gf1_mem_free(&gus->gf1.mem_alloc, pcmp->memory); - pcmp->memory = 0; - } - if ((block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_DRIVER, - "GF1 PCM", - runtime->dma_bytes, 1, 32, - NULL)) == NULL) - return -ENOMEM; - pcmp->memory = block->ptr; - } - pcmp->voices = params_channels(hw_params); - if (pcmp->pvoices[0] == NULL) { - if ((pcmp->pvoices[0] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL) - return -ENOMEM; - pcmp->pvoices[0]->handler_wave = snd_gf1_pcm_interrupt_wave; - pcmp->pvoices[0]->handler_volume = snd_gf1_pcm_interrupt_volume; - pcmp->pvoices[0]->volume_change = snd_gf1_pcm_volume_change; - pcmp->pvoices[0]->private_data = pcmp; - } - if (pcmp->voices > 1 && pcmp->pvoices[1] == NULL) { - if ((pcmp->pvoices[1] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL) - return -ENOMEM; - pcmp->pvoices[1]->handler_wave = snd_gf1_pcm_interrupt_wave; - pcmp->pvoices[1]->handler_volume = snd_gf1_pcm_interrupt_volume; - pcmp->pvoices[1]->volume_change = snd_gf1_pcm_volume_change; - pcmp->pvoices[1]->private_data = pcmp; - } else if (pcmp->voices == 1) { - if (pcmp->pvoices[1]) { - snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]); - pcmp->pvoices[1] = NULL; - } - } - return 0; -} - -static int snd_gf1_pcm_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - snd_pcm_lib_free_pages(substream); - if (pcmp->pvoices[0]) { - snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[0]); - pcmp->pvoices[0] = NULL; - } - if (pcmp->pvoices[1]) { - snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[1]); - pcmp->pvoices[1] = NULL; - } - if (pcmp->memory > 0) { - snd_gf1_mem_free(&pcmp->gus->gf1.mem_alloc, pcmp->memory); - pcmp->memory = 0; - } - return 0; -} - -static int snd_gf1_pcm_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - pcmp->bpos = 0; - pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream); - pcmp->block_size = snd_pcm_lib_period_bytes(substream); - pcmp->blocks = pcmp->dma_size / pcmp->block_size; - return 0; -} - -static int snd_gf1_pcm_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - int voice; - - if (cmd == SNDRV_PCM_TRIGGER_START) { - snd_gf1_pcm_trigger_up(substream); - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - spin_lock(&pcmp->lock); - pcmp->flags &= ~SNDRV_GF1_PCM_PFLG_ACTIVE; - spin_unlock(&pcmp->lock); - voice = pcmp->pvoices[0]->number; - snd_gf1_stop_voices(gus, voice, voice); - if (pcmp->pvoices[1]) { - voice = pcmp->pvoices[1]->number; - snd_gf1_stop_voices(gus, voice, voice); - } - } else { - return -EINVAL; - } - return 0; -} - -static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int pos; - unsigned char voice_ctrl; - - pos = 0; - spin_lock(&gus->reg_lock); - if (pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE) { - snd_gf1_select_voice(gus, pcmp->pvoices[0]->number); - voice_ctrl = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - pos = (snd_gf1_read_addr(gus, SNDRV_GF1_VA_CURRENT, voice_ctrl & 4) >> 4) - pcmp->memory; - if (substream->runtime->channels > 1) - pos <<= 1; - pos = bytes_to_frames(runtime, pos); - } - spin_unlock(&gus->reg_lock); - return pos; -} - -static struct snd_ratnum clock = { - .num = 9878400/16, - .den_min = 2, - .den_max = 257, - .den_step = 1, -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { - .nrats = 1, - .rats = &clock, -}; - -static int snd_gf1_pcm_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - - gus->c_dma_size = params_buffer_bytes(hw_params); - gus->c_period_size = params_period_bytes(hw_params); - gus->c_pos = 0; - gus->gf1.pcm_rcntrl_reg = 0x21; /* IRQ at end, enable & start */ - if (params_channels(hw_params) > 1) - gus->gf1.pcm_rcntrl_reg |= 2; - if (gus->gf1.dma2 > 3) - gus->gf1.pcm_rcntrl_reg |= 4; - if (snd_pcm_format_unsigned(params_format(hw_params))) - gus->gf1.pcm_rcntrl_reg |= 0x80; - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -static int snd_gf1_pcm_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_gf1_pcm_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RECORD_RATE, runtime->rate_den - 2); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */ - snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); /* Sampling Control Register */ - snd_dma_program(gus->gf1.dma2, runtime->dma_addr, gus->c_period_size, DMA_MODE_READ); - return 0; -} - -static int snd_gf1_pcm_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - int val; - - if (cmd == SNDRV_PCM_TRIGGER_START) { - val = gus->gf1.pcm_rcntrl_reg; - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - val = 0; - } else { - return -EINVAL; - } - - spin_lock(&gus->reg_lock); - snd_gf1_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, val); - snd_gf1_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); - spin_unlock(&gus->reg_lock); - return 0; -} - -static snd_pcm_uframes_t snd_gf1_pcm_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - int pos = snd_dma_pointer(gus->gf1.dma2, gus->c_period_size); - pos = bytes_to_frames(substream->runtime, (gus->c_pos + pos) % gus->c_dma_size); - return pos; -} - -static void snd_gf1_pcm_interrupt_dma_read(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */ - snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); /* Sampling Control Register */ - if (gus->pcm_cap_substream != NULL) { - snd_gf1_pcm_capture_prepare(gus->pcm_cap_substream); - snd_gf1_pcm_capture_trigger(gus->pcm_cap_substream, SNDRV_PCM_TRIGGER_START); - gus->c_pos += gus->c_period_size; - snd_pcm_period_elapsed(gus->pcm_cap_substream); - } -} - -static struct snd_pcm_hardware snd_gf1_pcm_playback = -{ - .info = SNDRV_PCM_INFO_NONINTERLEAVED, - .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE), - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .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, -}; - -static struct snd_pcm_hardware snd_gf1_pcm_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100, - .rate_min = 5510, - .rate_max = 44100, - .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, -}; - -static void snd_gf1_pcm_playback_free(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream) -{ - struct gus_pcm_private *pcmp; - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - pcmp = kzalloc(sizeof(*pcmp), GFP_KERNEL); - if (pcmp == NULL) - return -ENOMEM; - pcmp->gus = gus; - spin_lock_init(&pcmp->lock); - init_waitqueue_head(&pcmp->sleep); - atomic_set(&pcmp->dma_count, 0); - - runtime->private_data = pcmp; - runtime->private_free = snd_gf1_pcm_playback_free; - -#if 0 - printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", - (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); -#endif - if ((err = snd_gf1_dma_init(gus)) < 0) - return err; - pcmp->flags = SNDRV_GF1_PCM_PFLG_NONE; - pcmp->substream = substream; - runtime->hw = snd_gf1_pcm_playback; - snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(gus->gf1.dma1, &runtime->hw.period_bytes_max); - snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); - return 0; -} - -static int snd_gf1_pcm_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - - if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ)) - snd_printk(KERN_ERR "gf1 pcm - serious DMA problem\n"); - - snd_gf1_dma_done(gus); - return 0; -} - -static int snd_gf1_pcm_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - - gus->gf1.interrupt_handler_dma_read = snd_gf1_pcm_interrupt_dma_read; - gus->pcm_cap_substream = substream; - substream->runtime->hw = snd_gf1_pcm_capture; - snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(gus->gf1.dma2, &runtime->hw.period_bytes_max); - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clocks); - return 0; -} - -static int snd_gf1_pcm_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_gus_card *gus = snd_pcm_substream_chip(substream); - - gus->pcm_cap_substream = NULL; - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_READ); - return 0; -} - -static int snd_gf1_pcm_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 = 127; - return 0; -} - -static int snd_gf1_pcm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&gus->pcm_volume_level_lock, flags); - ucontrol->value.integer.value[0] = gus->gf1.pcm_volume_level_left1; - ucontrol->value.integer.value[1] = gus->gf1.pcm_volume_level_right1; - spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags); - return 0; -} - -static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned int idx; - unsigned short val1, val2, vol; - struct gus_pcm_private *pcmp; - struct snd_gus_voice *pvoice; - - val1 = ucontrol->value.integer.value[0] & 127; - val2 = ucontrol->value.integer.value[1] & 127; - spin_lock_irqsave(&gus->pcm_volume_level_lock, flags); - change = val1 != gus->gf1.pcm_volume_level_left1 || - val2 != gus->gf1.pcm_volume_level_right1; - gus->gf1.pcm_volume_level_left1 = val1; - gus->gf1.pcm_volume_level_right1 = val2; - gus->gf1.pcm_volume_level_left = snd_gf1_lvol_to_gvol_raw(val1 << 9) << 4; - gus->gf1.pcm_volume_level_right = snd_gf1_lvol_to_gvol_raw(val2 << 9) << 4; - spin_unlock_irqrestore(&gus->pcm_volume_level_lock, flags); - /* are we active? */ - spin_lock_irqsave(&gus->voice_alloc, flags); - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - if (!pvoice->pcm) - continue; - pcmp = pvoice->private_data; - if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE)) - continue; - /* load real volume - better precision */ - spin_lock(&gus->reg_lock); - snd_gf1_select_voice(gus, pvoice->number); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right; - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol); - pcmp->final_volume = 1; - spin_unlock(&gus->reg_lock); - } - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return change; -} - -static struct snd_kcontrol_new snd_gf1_pcm_volume_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Playback Volume", - .info = snd_gf1_pcm_volume_info, - .get = snd_gf1_pcm_volume_get, - .put = snd_gf1_pcm_volume_put -}; - -static struct snd_kcontrol_new snd_gf1_pcm_volume_control1 = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "GPCM Playback Volume", - .info = snd_gf1_pcm_volume_info, - .get = snd_gf1_pcm_volume_get, - .put = snd_gf1_pcm_volume_put -}; - -static struct snd_pcm_ops snd_gf1_pcm_playback_ops = { - .open = snd_gf1_pcm_playback_open, - .close = snd_gf1_pcm_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_gf1_pcm_playback_hw_params, - .hw_free = snd_gf1_pcm_playback_hw_free, - .prepare = snd_gf1_pcm_playback_prepare, - .trigger = snd_gf1_pcm_playback_trigger, - .pointer = snd_gf1_pcm_playback_pointer, - .copy = snd_gf1_pcm_playback_copy, - .silence = snd_gf1_pcm_playback_silence, -}; - -static struct snd_pcm_ops snd_gf1_pcm_capture_ops = { - .open = snd_gf1_pcm_capture_open, - .close = snd_gf1_pcm_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_gf1_pcm_capture_hw_params, - .hw_free = snd_gf1_pcm_capture_hw_free, - .prepare = snd_gf1_pcm_capture_prepare, - .trigger = snd_gf1_pcm_capture_trigger, - .pointer = snd_gf1_pcm_capture_pointer, -}; - -int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, struct snd_pcm ** rpcm) -{ - struct snd_card *card; - struct snd_kcontrol *kctl; - struct snd_pcm *pcm; - struct snd_pcm_substream *substream; - int capture, err; - - if (rpcm) - *rpcm = NULL; - card = gus->card; - capture = !gus->interwave && !gus->ess_flag && !gus->ace_flag ? 1 : 0; - err = snd_pcm_new(card, - gus->interwave ? "AMD InterWave" : "GF1", - pcm_dev, - gus->gf1.pcm_channels / 2, - capture, - &pcm); - if (err < 0) - return err; - pcm->private_data = gus; - /* playback setup */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_gf1_pcm_playback_ops); - - for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) - snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, gus->gf1.dma1 > 3 ? 128*1024 : 64*1024); - - pcm->info_flags = 0; - pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; - if (capture) { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_gf1_pcm_capture_ops); - if (gus->gf1.dma2 == gus->gf1.dma1) - pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX; - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, - SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(), - 64*1024, gus->gf1.dma2 > 3 ? 128*1024 : 64*1024); - } - strcpy(pcm->name, pcm->id); - if (gus->interwave) { - sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); - } - strcat(pcm->name, " (synth)"); - gus->pcm = pcm; - - if (gus->codec_flag) - kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus); - else - kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus); - if ((err = snd_ctl_add(card, kctl)) < 0) - return err; - kctl->id.index = control_index; - - if (rpcm) - *rpcm = pcm; - return 0; -} - diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_reset.c b/ANDROID_3.4.5/sound/isa/gus/gus_reset.c deleted file mode 100644 index 3d1fed0c..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_reset.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/interrupt.h> -#include <linux/time.h> -#include <sound/core.h> -#include <sound/gus.h> - -extern void snd_gf1_timers_init(struct snd_gus_card * gus); -extern void snd_gf1_timers_done(struct snd_gus_card * gus); -extern int snd_gf1_synth_init(struct snd_gus_card * gus); -extern void snd_gf1_synth_done(struct snd_gus_card * gus); - -/* - * ok.. default interrupt handlers... - */ - -static void snd_gf1_default_interrupt_handler_midi_out(struct snd_gus_card * gus) -{ - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x20); -} - -static void snd_gf1_default_interrupt_handler_midi_in(struct snd_gus_card * gus) -{ - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x80); -} - -static void snd_gf1_default_interrupt_handler_timer1(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~4); -} - -static void snd_gf1_default_interrupt_handler_timer2(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~8); -} - -static void snd_gf1_default_interrupt_handler_wave_and_volume(struct snd_gus_card * gus, struct snd_gus_voice * voice) -{ - snd_gf1_i_ctrl_stop(gus, 0x00); - snd_gf1_i_ctrl_stop(gus, 0x0d); -} - -static void snd_gf1_default_interrupt_handler_dma_write(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, 0x41, 0x00); -} - -static void snd_gf1_default_interrupt_handler_dma_read(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, 0x49, 0x00); -} - -void snd_gf1_set_default_handlers(struct snd_gus_card * gus, unsigned int what) -{ - if (what & SNDRV_GF1_HANDLER_MIDI_OUT) - gus->gf1.interrupt_handler_midi_out = snd_gf1_default_interrupt_handler_midi_out; - if (what & SNDRV_GF1_HANDLER_MIDI_IN) - gus->gf1.interrupt_handler_midi_in = snd_gf1_default_interrupt_handler_midi_in; - if (what & SNDRV_GF1_HANDLER_TIMER1) - gus->gf1.interrupt_handler_timer1 = snd_gf1_default_interrupt_handler_timer1; - if (what & SNDRV_GF1_HANDLER_TIMER2) - gus->gf1.interrupt_handler_timer2 = snd_gf1_default_interrupt_handler_timer2; - if (what & SNDRV_GF1_HANDLER_VOICE) { - struct snd_gus_voice *voice; - - voice = &gus->gf1.voices[what & 0xffff]; - voice->handler_wave = - voice->handler_volume = snd_gf1_default_interrupt_handler_wave_and_volume; - voice->handler_effect = NULL; - voice->volume_change = NULL; - } - if (what & SNDRV_GF1_HANDLER_DMA_WRITE) - gus->gf1.interrupt_handler_dma_write = snd_gf1_default_interrupt_handler_dma_write; - if (what & SNDRV_GF1_HANDLER_DMA_READ) - gus->gf1.interrupt_handler_dma_read = snd_gf1_default_interrupt_handler_dma_read; -} - -/* - - */ - -static void snd_gf1_clear_regs(struct snd_gus_card * gus) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - inb(GUSP(gus, IRQSTAT)); - snd_gf1_write8(gus, 0x41, 0); /* DRAM DMA Control Register */ - snd_gf1_write8(gus, 0x45, 0); /* Timer Control */ - snd_gf1_write8(gus, 0x49, 0); /* Sampling Control Register */ - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -static void snd_gf1_look_regs(struct snd_gus_card * gus) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_look8(gus, 0x41); /* DRAM DMA Control Register */ - snd_gf1_look8(gus, 0x49); /* Sampling Control Register */ - inb(GUSP(gus, IRQSTAT)); - snd_gf1_read8(gus, 0x0f); /* IRQ Source Register */ - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -/* - * put selected GF1 voices to initial stage... - */ - -void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, voice); -#if 0 - printk(KERN_DEBUG " -%i- smart stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); -#endif - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - spin_unlock_irqrestore(&gus->reg_lock, flags); -} - -void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice) -{ - unsigned long flags; - - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, voice); -#if 0 - printk(KERN_DEBUG " -%i- stop voice - volume = 0x%x\n", voice, snd_gf1_i_read16(gus, SNDRV_GF1_VW_VOLUME)); -#endif - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); - if (gus->gf1.enh_mode) - snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0); - spin_unlock_irqrestore(&gus->reg_lock, flags); -#if 0 - snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_VIBRATO); - snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_TREMOLO); -#endif -} - -static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min, - unsigned short v_max) -{ - unsigned long flags; - unsigned int daddr; - unsigned short i, w_16; - - daddr = gus->gf1.default_voice_address << 4; - for (i = v_min; i <= v_max; i++) { -#if 0 - if (gus->gf1.syn_voices) - gus->gf1.syn_voices[i].flags = ~VFLG_DYNAMIC; -#endif - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, i); - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); /* Voice Control Register = voice stop */ - snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); /* Volume Ramp Control Register = ramp off */ - if (gus->gf1.enh_mode) - snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, gus->gf1.memory ? 0x02 : 0x82); /* Deactivate voice */ - w_16 = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL) & 0x04; - snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, 0x400); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, daddr, w_16); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, daddr, w_16); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, 0); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, 0); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 0); - snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0); - snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, daddr, w_16); - snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, 7); - if (gus->gf1.enh_mode) { - snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0); - snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, 0); - snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, 0); - } - spin_unlock_irqrestore(&gus->reg_lock, flags); -#if 0 - snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_VIBRATO); - snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_TREMOLO); -#endif - } -} - -void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max) -{ - unsigned long flags; - short i, ramp_ok; - unsigned short ramp_end; - - if (!in_interrupt()) { /* this can't be done in interrupt */ - for (i = v_min, ramp_ok = 0; i <= v_max; i++) { - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_select_voice(gus, i); - ramp_end = snd_gf1_read16(gus, 9) >> 8; - if (ramp_end > SNDRV_GF1_MIN_OFFSET) { - ramp_ok++; - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 20); /* ramp rate */ - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET); /* ramp start */ - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, ramp_end); /* ramp end */ - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40); /* ramp down */ - if (gus->gf1.enh_mode) { - snd_gf1_delay(gus); - snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40); - } - } - spin_unlock_irqrestore(&gus->reg_lock, flags); - } - msleep_interruptible(50); - } - snd_gf1_clear_voices(gus, v_min, v_max); -} - -static void snd_gf1_alloc_voice_use(struct snd_gus_card * gus, - struct snd_gus_voice * pvoice, - int type, int client, int port) -{ - pvoice->use = 1; - switch (type) { - case SNDRV_GF1_VOICE_TYPE_PCM: - gus->gf1.pcm_alloc_voices++; - pvoice->pcm = 1; - break; - case SNDRV_GF1_VOICE_TYPE_SYNTH: - pvoice->synth = 1; - pvoice->client = client; - pvoice->port = port; - break; - case SNDRV_GF1_VOICE_TYPE_MIDI: - pvoice->midi = 1; - pvoice->client = client; - pvoice->port = port; - break; - } -} - -struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, int client, int port) -{ - struct snd_gus_voice *pvoice; - unsigned long flags; - int idx; - - spin_lock_irqsave(&gus->voice_alloc, flags); - if (type == SNDRV_GF1_VOICE_TYPE_PCM) { - if (gus->gf1.pcm_alloc_voices >= gus->gf1.pcm_channels) { - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return NULL; - } - } - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - if (!pvoice->use) { - snd_gf1_alloc_voice_use(gus, pvoice, type, client, port); - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return pvoice; - } - } - for (idx = 0; idx < 32; idx++) { - pvoice = &gus->gf1.voices[idx]; - if (pvoice->midi && !pvoice->client) { - snd_gf1_clear_voices(gus, pvoice->number, pvoice->number); - snd_gf1_alloc_voice_use(gus, pvoice, type, client, port); - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return pvoice; - } - } - spin_unlock_irqrestore(&gus->voice_alloc, flags); - return NULL; -} - -void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice) -{ - unsigned long flags; - void (*private_free)(struct snd_gus_voice *voice); - void *private_data; - - if (voice == NULL || !voice->use) - return; - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | voice->number); - snd_gf1_clear_voices(gus, voice->number, voice->number); - spin_lock_irqsave(&gus->voice_alloc, flags); - private_free = voice->private_free; - private_data = voice->private_data; - voice->private_free = NULL; - voice->private_data = NULL; - if (voice->pcm) - gus->gf1.pcm_alloc_voices--; - voice->use = voice->pcm = 0; - voice->sample_ops = NULL; - spin_unlock_irqrestore(&gus->voice_alloc, flags); - if (private_free) - private_free(voice); -} - -/* - * call this function only by start of driver - */ - -int snd_gf1_start(struct snd_gus_card * gus) -{ - unsigned long flags; - unsigned int i; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */ - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL, gus->joystick_dac); - - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_ALL); - for (i = 0; i < 32; i++) { - gus->gf1.voices[i].number = i; - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_VOICE | i); - } - - snd_gf1_uart_cmd(gus, 0x03); /* huh.. this cleanup took me some time... */ - - if (gus->gf1.enh_mode) { /* enhanced mode !!!! */ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - } - snd_gf1_clear_regs(gus); - snd_gf1_select_active_voices(gus); - snd_gf1_delay(gus); - gus->gf1.default_voice_address = gus->gf1.memory > 0 ? 0 : 512 - 8; - /* initialize LFOs & clear LFOs memory */ - if (gus->gf1.enh_mode && gus->gf1.memory) { - gus->gf1.hw_lfo = 1; - gus->gf1.default_voice_address += 1024; - } else { - gus->gf1.sw_lfo = 1; - } -#if 0 - snd_gf1_lfo_init(gus); -#endif - if (gus->gf1.memory > 0) - for (i = 0; i < 4; i++) - snd_gf1_poke(gus, gus->gf1.default_voice_address + i, 0); - snd_gf1_clear_regs(gus); - snd_gf1_clear_voices(gus, 0, 31); - snd_gf1_look_regs(gus); - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */ - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 7); /* Reset Register = IRQ enable, DAC enable */ - if (gus->gf1.enh_mode) { /* enhanced mode !!!! */ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); - } - while ((snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ) & 0xc0) != 0xc0); - - spin_lock_irqsave(&gus->reg_lock, flags); - outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE)); - outb(gus->mix_cntrl_reg, GUSP(gus, MIXCNTRLREG)); - spin_unlock_irqrestore(&gus->reg_lock, flags); - - snd_gf1_timers_init(gus); - snd_gf1_look_regs(gus); - snd_gf1_mem_init(gus); - snd_gf1_mem_proc_init(gus); -#ifdef CONFIG_SND_DEBUG - snd_gus_irq_profile_init(gus); -#endif - -#if 0 - if (gus->pnp_flag) { - if (gus->chip.playback_fifo_size > 0) - snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR, gus->chip.playback_fifo_block->ptr >> 8); - if (gus->chip.record_fifo_size > 0) - snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR, gus->chip.record_fifo_block->ptr >> 8); - snd_gf1_i_write16(gus, SNDRV_GF1_GW_FIFO_SIZE, gus->chip.interwave_fifo_reg); - } -#endif - - return 0; -} - -/* - * call this function only by shutdown of driver - */ - -int snd_gf1_stop(struct snd_gus_card * gus) -{ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0); /* stop all timers */ - snd_gf1_stop_voices(gus, 0, 31); /* stop all voices */ - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */ - snd_gf1_timers_done(gus); - snd_gf1_mem_done(gus); -#if 0 - snd_gf1_lfo_done(gus); -#endif - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_tables.h b/ANDROID_3.4.5/sound/isa/gus/gus_tables.h deleted file mode 100644 index 42a4ca0d..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_tables.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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 - * - */ - -#define SNDRV_GF1_SCALE_TABLE_SIZE 128 -#define SNDRV_GF1_ATTEN_TABLE_SIZE 128 - -#ifdef __GUS_TABLES_ALLOC__ - -#if 0 - -unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] = -{ - 8372, 8870, 9397, 9956, 10548, 11175, - 11840, 12544, 13290, 14080, 14917, 15804, - 16744, 17740, 18795, 19912, 21096, 22351, - 23680, 25088, 26580, 28160, 29834, 31609, - 33488, 35479, 37589, 39824, 42192, 44701, - 47359, 50175, 53159, 56320, 59669, 63217, - 66976, 70959, 75178, 79649, 84385, 89402, - 94719, 100351, 106318, 112640, 119338, 126434, - 133952, 141918, 150356, 159297, 168769, 178805, - 189437, 200702, 212636, 225280, 238676, 252868, - 267905, 283835, 300713, 318594, 337539, 357610, - 378874, 401403, 425272, 450560, 477352, 505737, - 535809, 567670, 601425, 637188, 675077, 715219, - 757749, 802807, 850544, 901120, 954703, 1011473, - 1071618, 1135340, 1202851, 1274376, 1350154, 1430439, - 1515497, 1605613, 1701088, 1802240, 1909407, 2022946, - 2143237, 2270680, 2405702, 2548752, 2700309, 2860878, - 3030994, 3211227, 3402176, 3604480, 3818814, 4045892, - 4286473, 4541360, 4811404, 5097505, 5400618, 5721755, - 6061989, 6422453, 6804352, 7208960, 7637627, 8091784, - 8572947, 9082720, 9622807, 10195009, 10801236, 11443511, - 12123977, 12844906 -}; - -#endif /* 0 */ - -unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = { - 4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */, - 1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */, - 939 /* 10 */,903 /* 11 */,871 /* 12 */,842 /* 13 */,814 /* 14 */, - 789 /* 15 */,765 /* 16 */,743 /* 17 */,722 /* 18 */,702 /* 19 */, - 683 /* 20 */,665 /* 21 */,647 /* 22 */,631 /* 23 */,615 /* 24 */, - 600 /* 25 */,586 /* 26 */,572 /* 27 */,558 /* 28 */,545 /* 29 */, - 533 /* 30 */,521 /* 31 */,509 /* 32 */,498 /* 33 */,487 /* 34 */, - 476 /* 35 */,466 /* 36 */,455 /* 37 */,446 /* 38 */,436 /* 39 */, - 427 /* 40 */,418 /* 41 */,409 /* 42 */,400 /* 43 */,391 /* 44 */, - 383 /* 45 */,375 /* 46 */,367 /* 47 */,359 /* 48 */,352 /* 49 */, - 344 /* 50 */,337 /* 51 */,330 /* 52 */,323 /* 53 */,316 /* 54 */, - 309 /* 55 */,302 /* 56 */,296 /* 57 */,289 /* 58 */,283 /* 59 */, - 277 /* 60 */,271 /* 61 */,265 /* 62 */,259 /* 63 */,253 /* 64 */, - 247 /* 65 */,242 /* 66 */,236 /* 67 */,231 /* 68 */,225 /* 69 */, - 220 /* 70 */,215 /* 71 */,210 /* 72 */,205 /* 73 */,199 /* 74 */, - 195 /* 75 */,190 /* 76 */,185 /* 77 */,180 /* 78 */,175 /* 79 */, - 171 /* 80 */,166 /* 81 */,162 /* 82 */,157 /* 83 */,153 /* 84 */, - 148 /* 85 */,144 /* 86 */,140 /* 87 */,135 /* 88 */,131 /* 89 */, - 127 /* 90 */,123 /* 91 */,119 /* 92 */,115 /* 93 */,111 /* 94 */, - 107 /* 95 */,103 /* 96 */,100 /* 97 */,96 /* 98 */,92 /* 99 */, - 88 /* 100 */,85 /* 101 */,81 /* 102 */,77 /* 103 */,74 /* 104 */, - 70 /* 105 */,67 /* 106 */,63 /* 107 */,60 /* 108 */,56 /* 109 */, - 53 /* 110 */,50 /* 111 */,46 /* 112 */,43 /* 113 */,40 /* 114 */, - 37 /* 115 */,33 /* 116 */,30 /* 117 */,27 /* 118 */,24 /* 119 */, - 21 /* 120 */,18 /* 121 */,15 /* 122 */,12 /* 123 */,9 /* 124 */, - 6 /* 125 */,3 /* 126 */,0 /* 127 */, -}; - -#else - -extern unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE]; -extern unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE]; - -#endif diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_timer.c b/ANDROID_3.4.5/sound/isa/gus/gus_timer.c deleted file mode 100644 index c5372714..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_timer.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Routines for Gravis UltraSound soundcards - Timers - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * GUS have similar timers as AdLib (OPL2/OPL3 chips). - * - * - * 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/gus.h> - -/* - * Timer 1 - 80us - */ - -static int snd_gf1_timer1_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - ticks = timer->sticks; - tmp = (gus->gf1.timer_enabled |= 4); - snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1, 256 - ticks); /* timer 1 count */ - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 1 IRQ */ - snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -static int snd_gf1_timer1_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - tmp = (gus->gf1.timer_enabled &= ~4); - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -/* - * Timer 2 - 320us - */ - -static int snd_gf1_timer2_start(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - unsigned int ticks; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - ticks = timer->sticks; - tmp = (gus->gf1.timer_enabled |= 8); - snd_gf1_write8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2, 256 - ticks); /* timer 2 count */ - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* enable timer 2 IRQ */ - snd_gf1_adlib_write(gus, 0x04, tmp >> 2); /* timer 2 start */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -static int snd_gf1_timer2_stop(struct snd_timer * timer) -{ - unsigned long flags; - unsigned char tmp; - struct snd_gus_card *gus; - - gus = snd_timer_chip(timer); - spin_lock_irqsave(&gus->reg_lock, flags); - tmp = (gus->gf1.timer_enabled &= ~8); - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, tmp); /* disable timer #1 */ - spin_unlock_irqrestore(&gus->reg_lock, flags); - return 0; -} - -/* - - */ - -static void snd_gf1_interrupt_timer1(struct snd_gus_card * gus) -{ - struct snd_timer *timer = gus->gf1.timer1; - - if (timer == NULL) - return; - snd_timer_interrupt(timer, timer->sticks); -} - -static void snd_gf1_interrupt_timer2(struct snd_gus_card * gus) -{ - struct snd_timer *timer = gus->gf1.timer2; - - if (timer == NULL) - return; - snd_timer_interrupt(timer, timer->sticks); -} - -/* - - */ - -static struct snd_timer_hardware snd_gf1_timer1 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 80000, - .ticks = 256, - .start = snd_gf1_timer1_start, - .stop = snd_gf1_timer1_stop, -}; - -static struct snd_timer_hardware snd_gf1_timer2 = -{ - .flags = SNDRV_TIMER_HW_STOP, - .resolution = 320000, - .ticks = 256, - .start = snd_gf1_timer2_start, - .stop = snd_gf1_timer2_stop, -}; - -static void snd_gf1_timer1_free(struct snd_timer *timer) -{ - struct snd_gus_card *gus = timer->private_data; - gus->gf1.timer1 = NULL; -} - -static void snd_gf1_timer2_free(struct snd_timer *timer) -{ - struct snd_gus_card *gus = timer->private_data; - gus->gf1.timer2 = NULL; -} - -void snd_gf1_timers_init(struct snd_gus_card * gus) -{ - struct snd_timer *timer; - struct snd_timer_id tid; - - if (gus->gf1.timer1 != NULL || gus->gf1.timer2 != NULL) - return; - - gus->gf1.interrupt_handler_timer1 = snd_gf1_interrupt_timer1; - gus->gf1.interrupt_handler_timer2 = snd_gf1_interrupt_timer2; - - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = gus->card->number; - tid.device = gus->timer_dev; - tid.subdevice = 0; - - if (snd_timer_new(gus->card, "GF1 timer", &tid, &timer) >= 0) { - strcpy(timer->name, "GF1 timer #1"); - timer->private_data = gus; - timer->private_free = snd_gf1_timer1_free; - timer->hw = snd_gf1_timer1; - } - gus->gf1.timer1 = timer; - - tid.device++; - - if (snd_timer_new(gus->card, "GF1 timer", &tid, &timer) >= 0) { - strcpy(timer->name, "GF1 timer #2"); - timer->private_data = gus; - timer->private_free = snd_gf1_timer2_free; - timer->hw = snd_gf1_timer2; - } - gus->gf1.timer2 = timer; -} - -void snd_gf1_timers_done(struct snd_gus_card * gus) -{ - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_TIMER1 | SNDRV_GF1_HANDLER_TIMER2); - if (gus->gf1.timer1) { - snd_device_free(gus->card, gus->gf1.timer1); - gus->gf1.timer1 = NULL; - } - if (gus->gf1.timer2) { - snd_device_free(gus->card, gus->gf1.timer2); - gus->gf1.timer2 = NULL; - } -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_uart.c b/ANDROID_3.4.5/sound/isa/gus/gus_uart.c deleted file mode 100644 index 21cc42e4..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_uart.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for the GF1 MIDI interface - like UART 6850 - * - * - * 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/interrupt.h> -#include <linux/time.h> -#include <sound/core.h> -#include <sound/gus.h> - -static void snd_gf1_interrupt_midi_in(struct snd_gus_card * gus) -{ - int count; - unsigned char stat, data, byte; - unsigned long flags; - - count = 10; - while (count) { - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - stat = snd_gf1_uart_stat(gus); - if (!(stat & 0x01)) { /* data in Rx FIFO? */ - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - count--; - continue; - } - count = 100; /* arm counter to new value */ - data = snd_gf1_uart_get(gus); - if (!(gus->gf1.uart_cmd & 0x80)) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - continue; - } - if (stat & 0x10) { /* framing error */ - gus->gf1.uart_framing++; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - continue; - } - byte = snd_gf1_uart_get(gus); - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - snd_rawmidi_receive(gus->midi_substream_input, &byte, 1); - if (stat & 0x20) { - gus->gf1.uart_overrun++; - } - } -} - -static void snd_gf1_interrupt_midi_out(struct snd_gus_card * gus) -{ - char byte; - unsigned long flags; - - /* try unlock output */ - if (snd_gf1_uart_stat(gus) & 0x01) - snd_gf1_interrupt_midi_in(gus); - - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (snd_gf1_uart_stat(gus) & 0x02) { /* Tx FIFO free? */ - if (snd_rawmidi_transmit(gus->midi_substream_output, &byte, 1) != 1) { /* no other bytes or error */ - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); /* disable Tx interrupt */ - } else { - snd_gf1_uart_put(gus, byte); - } - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -} - -static void snd_gf1_uart_reset(struct snd_gus_card * gus, int close) -{ - snd_gf1_uart_cmd(gus, 0x03); /* reset */ - if (!close && gus->uart_enable) { - udelay(160); - snd_gf1_uart_cmd(gus, 0x00); /* normal operations */ - } -} - -static int snd_gf1_uart_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (!(gus->gf1.uart_cmd & 0x80)) { /* input active? */ - snd_gf1_uart_reset(gus, 0); - } - gus->gf1.interrupt_handler_midi_out = snd_gf1_interrupt_midi_out; - gus->midi_substream_output = substream; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -#if 0 - snd_printk(KERN_DEBUG "write init - cmd = 0x%x, stat = 0x%x\n", gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); -#endif - return 0; -} - -static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - int i; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) { - snd_gf1_uart_reset(gus, 0); - } - gus->gf1.interrupt_handler_midi_in = snd_gf1_interrupt_midi_in; - gus->midi_substream_input = substream; - if (gus->uart_enable) { - for (i = 0; i < 1000 && (snd_gf1_uart_stat(gus) & 0x01); i++) - snd_gf1_uart_get(gus); /* clean Rx */ - if (i >= 1000) - snd_printk(KERN_ERR "gus midi uart init read - cleanup error\n"); - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -#if 0 - snd_printk(KERN_DEBUG - "read init - enable = %i, cmd = 0x%x, stat = 0x%x\n", - gus->uart_enable, gus->gf1.uart_cmd, snd_gf1_uart_stat(gus)); - snd_printk(KERN_DEBUG - "[0x%x] reg (ctrl/status) = 0x%x, reg (data) = 0x%x " - "(page = 0x%x)\n", - gus->gf1.port + 0x100, inb(gus->gf1.port + 0x100), - inb(gus->gf1.port + 0x101), inb(gus->gf1.port + 0x102)); -#endif - return 0; -} - -static int snd_gf1_uart_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in) - snd_gf1_uart_reset(gus, 1); - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_OUT); - gus->midi_substream_output = NULL; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return 0; -} - -static int snd_gf1_uart_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_gus_card *gus; - - gus = substream->rmidi->private_data; - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) - snd_gf1_uart_reset(gus, 1); - snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_MIDI_IN); - gus->midi_substream_input = NULL; - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return 0; -} - -static void snd_gf1_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - struct snd_gus_card *gus; - unsigned long flags; - - gus = substream->rmidi->private_data; - - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (up) { - if ((gus->gf1.uart_cmd & 0x80) == 0) - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x80); /* enable Rx interrupts */ - } else { - if (gus->gf1.uart_cmd & 0x80) - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x80); /* disable Rx interrupts */ - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -} - -static void snd_gf1_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_gus_card *gus; - char byte; - int timeout; - - gus = substream->rmidi->private_data; - - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (up) { - if ((gus->gf1.uart_cmd & 0x20) == 0) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - /* wait for empty Rx - Tx is probably unlocked */ - timeout = 10000; - while (timeout-- > 0 && snd_gf1_uart_stat(gus) & 0x01); - /* Tx FIFO free? */ - spin_lock_irqsave(&gus->uart_cmd_lock, flags); - if (gus->gf1.uart_cmd & 0x20) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return; - } - if (snd_gf1_uart_stat(gus) & 0x02) { - if (snd_rawmidi_transmit(substream, &byte, 1) != 1) { - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); - return; - } - snd_gf1_uart_put(gus, byte); - } - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd | 0x20); /* enable Tx interrupt */ - } - } else { - if (gus->gf1.uart_cmd & 0x20) - snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd & ~0x20); - } - spin_unlock_irqrestore(&gus->uart_cmd_lock, flags); -} - -static struct snd_rawmidi_ops snd_gf1_uart_output = -{ - .open = snd_gf1_uart_output_open, - .close = snd_gf1_uart_output_close, - .trigger = snd_gf1_uart_output_trigger, -}; - -static struct snd_rawmidi_ops snd_gf1_uart_input = -{ - .open = snd_gf1_uart_input_open, - .close = snd_gf1_uart_input_close, - .trigger = snd_gf1_uart_input_trigger, -}; - -int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi ** rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi)) < 0) - return err; - strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_gf1_uart_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_gf1_uart_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = gus; - gus->midi_uart = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return err; -} diff --git a/ANDROID_3.4.5/sound/isa/gus/gus_volume.c b/ANDROID_3.4.5/sound/isa/gus/gus_volume.c deleted file mode 100644 index 3dd841ae..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gus_volume.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/gus.h> -#define __GUS_TABLES_ALLOC__ -#include "gus_tables.h" - -EXPORT_SYMBOL(snd_gf1_atten_table); /* for snd-gus-synth module */ - -unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol) -{ - unsigned short e, m, tmp; - - if (vol > 65535) - vol = 65535; - tmp = vol; - e = 7; - if (tmp < 128) { - while (e > 0 && tmp < (1 << e)) - e--; - } else { - while (tmp > 255) { - tmp >>= 1; - e++; - } - } - m = vol - (1 << e); - if (m > 0) { - if (e > 8) - m >>= e - 8; - else if (e < 8) - m <<= 8 - e; - m &= 255; - } - return (e << 8) | m; -} - -#if 0 - -unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol) -{ - unsigned int rvol; - unsigned short e, m; - - if (!gf1_vol) - return 0; - e = gf1_vol >> 8; - m = (unsigned char) gf1_vol; - rvol = 1 << e; - if (e > 8) - return rvol | (m << (e - 8)); - return rvol | (m >> (8 - e)); -} - -unsigned int snd_gf1_calc_ramp_rate(struct snd_gus_card * gus, - unsigned short start, - unsigned short end, - unsigned int us) -{ - static unsigned char vol_rates[19] = - { - 23, 24, 26, 28, 29, 31, 32, 34, - 36, 37, 39, 40, 42, 44, 45, 47, - 49, 50, 52 - }; - unsigned short range, increment, value, i; - - start >>= 4; - end >>= 4; - if (start < end) - us /= end - start; - else - us /= start - end; - range = 4; - value = gus->gf1.enh_mode ? - vol_rates[0] : - vol_rates[gus->gf1.active_voices - 14]; - for (i = 0; i < 3; i++) { - if (us < value) { - range = i; - break; - } else - value <<= 3; - } - if (range == 4) { - range = 3; - increment = 1; - } else - increment = (value + (value >> 1)) / us; - return (range << 6) | (increment & 0x3f); -} - -#endif /* 0 */ - -unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int freq16) -{ - freq16 >>= 3; - if (freq16 < 50) - freq16 = 50; - if (freq16 & 0xf8000000) { - freq16 = ~0xf8000000; - snd_printk(KERN_ERR "snd_gf1_translate_freq: overflow - freq = 0x%x\n", freq16); - } - return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; -} - -#if 0 - -short snd_gf1_compute_vibrato(short cents, unsigned short fc_register) -{ - static short vibrato_table[] = - { - 0, 0, 32, 592, 61, 1175, 93, 1808, - 124, 2433, 152, 3007, 182, 3632, 213, 4290, - 241, 4834, 255, 5200 - }; - - long depth; - short *vi1, *vi2, pcents, v1; - - pcents = cents < 0 ? -cents : cents; - for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2); - v1 = *(vi1 + 1); - /* The FC table above is a list of pairs. The first number in the pair */ - /* is the cents index from 0-255 cents, and the second number in the */ - /* pair is the FC adjustment needed to change the pitch by the indexed */ - /* number of cents. The table was created for an FC of 32768. */ - /* The following expression does a linear interpolation against the */ - /* approximated log curve in the table above, and then scales the number */ - /* by the FC before the LFO. This calculation also adjusts the output */ - /* value to produce the appropriate depth for the hardware. The depth */ - /* is 2 * desired FC + 1. */ - depth = (((int) (*(vi2 + 1) - *vi1) * (pcents - *vi1) / (*vi2 - *vi1)) + v1) * fc_register >> 14; - if (depth) - depth++; - if (depth > 255) - depth = 255; - return cents < 0 ? -(short) depth : (short) depth; -} - -unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens) -{ - static long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933}; - int wheel, sensitivity; - unsigned int mantissa, f1, f2; - unsigned short semitones, f1_index, f2_index, f1_power, f2_power; - char bend_down = 0; - int bend; - - if (!sens) - return 1024; - wheel = (int) pitchbend - 8192; - sensitivity = ((int) sens * wheel) / 128; - if (sensitivity < 0) { - bend_down = 1; - sensitivity = -sensitivity; - } - semitones = (unsigned int) (sensitivity >> 13); - mantissa = sensitivity % 8192; - f1_index = semitones % 12; - f2_index = (semitones + 1) % 12; - f1_power = semitones / 12; - f2_power = (semitones + 1) / 12; - f1 = log_table[f1_index] << f1_power; - f2 = log_table[f2_index] << f2_power; - bend = (int) ((((f2 - f1) * mantissa) >> 13) + f1); - if (bend_down) - bend = 1048576L / bend; - return bend; -} - -unsigned short snd_gf1_compute_freq(unsigned int freq, - unsigned int rate, - unsigned short mix_rate) -{ - unsigned int fc; - int scale = 0; - - while (freq >= 4194304L) { - scale++; - freq >>= 1; - } - fc = (freq << 10) / rate; - if (fc > 97391L) { - fc = 97391; - snd_printk(KERN_ERR "patch: (1) fc frequency overflow - %u\n", fc); - } - fc = (fc * 44100UL) / mix_rate; - while (scale--) - fc <<= 1; - if (fc > 65535L) { - fc = 65535; - snd_printk(KERN_ERR "patch: (2) fc frequency overflow - %u\n", fc); - } - return (unsigned short) fc; -} - -#endif /* 0 */ diff --git a/ANDROID_3.4.5/sound/isa/gus/gusclassic.c b/ANDROID_3.4.5/sound/isa/gus/gusclassic.c deleted file mode 100644 index bf633367..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gusclassic.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Driver for Gravis UltraSound Classic soundcard - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/delay.h> -#include <linux/time.h> -#include <linux/module.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/gus.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -#define CRD_NAME "Gravis UltraSound Classic" -#define DEV_NAME "gusclassic" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver."); -module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver."); - -static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n) -{ - return enable[n]; -} - -static int __devinit snd_gusclassic_create(struct snd_card *card, - struct device *dev, unsigned int n, struct snd_gus_card **rgus) -{ - static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260}; - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1}; - static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; - - int i, error; - - if (irq[n] == SNDRV_AUTO_IRQ) { - irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dma1[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma1[n] < 0) { - dev_err(dev, "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2[n] == SNDRV_AUTO_DMA) { - dma2[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma2[n] < 0) { - dev_err(dev, "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - if (port[n] != SNDRV_AUTO_PORT) - return snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n], - 0, channels[n], pcm_channels[n], 0, rgus); - - i = 0; - do { - port[n] = possible_ports[i]; - error = snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n], - 0, channels[n], pcm_channels[n], 0, rgus); - } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); - - return error; -} - -static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus) -{ - unsigned char d; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - return 0; -} - -static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_gus_card *gus; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, 0, &card); - if (error < 0) - return error; - - if (pcm_channels[n] < 2) - pcm_channels[n] = 2; - - error = snd_gusclassic_create(card, dev, n, &gus); - if (error < 0) - goto out; - - error = snd_gusclassic_detect(gus); - if (error < 0) - goto out; - - gus->joystick_dac = joystick_dac[n]; - - error = snd_gus_initialize(gus); - if (error < 0) - goto out; - - error = -ENODEV; - if (gus->max_flag || gus->ess_flag) { - dev_err(dev, "GUS Classic or ACE soundcard was " - "not detected at 0x%lx\n", gus->gf1.port); - goto out; - } - - error = snd_gf1_new_mixer(gus); - if (error < 0) - goto out; - - error = snd_gf1_pcm_new(gus, 0, 0, NULL); - if (error < 0) - goto out; - - if (!gus->ace_flag) { - error = snd_gf1_rawmidi_new(gus, 0, NULL); - if (error < 0) - goto out; - } - - sprintf(card->longname + strlen(card->longname), - " at 0x%lx, irq %d, dma %d", - gus->gf1.port, gus->gf1.irq, gus->gf1.dma1); - - if (gus->gf1.dma2 >= 0) - sprintf(card->longname + strlen(card->longname), - "&%d", gus->gf1.dma2); - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_gusclassic_driver = { - .match = snd_gusclassic_match, - .probe = snd_gusclassic_probe, - .remove = __devexit_p(snd_gusclassic_remove), -#if 0 /* FIXME */ - .suspend = snd_gusclassic_suspend, - .remove = snd_gusclassic_remove, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_gusclassic_init(void) -{ - return isa_register_driver(&snd_gusclassic_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_gusclassic_exit(void) -{ - isa_unregister_driver(&snd_gusclassic_driver); -} - -module_init(alsa_card_gusclassic_init); -module_exit(alsa_card_gusclassic_exit); diff --git a/ANDROID_3.4.5/sound/isa/gus/gusextreme.c b/ANDROID_3.4.5/sound/isa/gus/gusextreme.c deleted file mode 100644 index bc10cc26..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gusextreme.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Driver for Gravis UltraSound Extreme soundcards - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/delay.h> -#include <linux/time.h> -#include <linux/module.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/gus.h> -#include <sound/es1688.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#define SNDRV_LEGACY_AUTO_PROBE -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -#define CRD_NAME "Gravis UltraSound Extreme" -#define DEV_NAME "gusextreme" - -MODULE_DESCRIPTION(CRD_NAME); -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static long gf1_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x210,0x220,0x230,0x240,0x250,0x260,0x270 */ -static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x300,0x310,0x320 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int gf1_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver."); -module_param_array(gf1_port, long, NULL, 0444); -MODULE_PARM_DESC(gf1_port, "GF1 port # for " CRD_NAME " driver (optional)."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver."); -module_param_array(gf1_irq, int, NULL, 0444); -MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for " CRD_NAME " driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "GF1 DMA # for " CRD_NAME " driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver."); -module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver."); - -static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n) -{ - return enable[n]; -} - -static int __devinit snd_gusextreme_es1688_create(struct snd_card *card, - struct snd_es1688 *chip, struct device *dev, unsigned int n) -{ - static long possible_ports[] = {0x220, 0x240, 0x260}; - static int possible_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dmas[] = {1, 3, 0, -1}; - - int i, error; - - if (irq[n] == SNDRV_AUTO_IRQ) { - irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ for ES1688\n"); - return -EBUSY; - } - } - if (dma8[n] == SNDRV_AUTO_DMA) { - dma8[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma8[n] < 0) { - dev_err(dev, "unable to find a free DMA for ES1688\n"); - return -EBUSY; - } - } - - if (port[n] != SNDRV_AUTO_PORT) - return snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_1688); - - i = 0; - do { - port[n] = possible_ports[i]; - error = snd_es1688_create(card, chip, port[n], mpu_port[n], - irq[n], mpu_irq[n], dma8[n], ES1688_HW_1688); - } while (error < 0 && ++i < ARRAY_SIZE(possible_ports)); - - return error; -} - -static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card, - struct device *dev, unsigned int n, struct snd_gus_card **rgus) -{ - static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1}; - static int possible_dmas[] = {5, 6, 7, 3, 1, -1}; - - if (gf1_irq[n] == SNDRV_AUTO_IRQ) { - gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs); - if (gf1_irq[n] < 0) { - dev_err(dev, "unable to find a free IRQ for GF1\n"); - return -EBUSY; - } - } - if (dma1[n] == SNDRV_AUTO_DMA) { - dma1[n] = snd_legacy_find_free_dma(possible_dmas); - if (dma1[n] < 0) { - dev_err(dev, "unable to find a free DMA for GF1\n"); - return -EBUSY; - } - } - return snd_gus_create(card, gf1_port[n], gf1_irq[n], dma1[n], -1, - 0, channels[n], pcm_channels[n], 0, rgus); -} - -static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus, - struct snd_es1688 *es1688) -{ - unsigned long flags; - unsigned char d; - - /* - * This is main stuff - enable access to GF1 chip... - * I'm not sure, if this will work for card which have - * ES1688 chip in another place than 0x220. - * - * I used reverse-engineering in DOSEMU. [--jk] - * - * ULTRINIT.EXE: - * 0x230 = 0,2,3 - * 0x240 = 2,0,1 - * 0x250 = 2,0,3 - * 0x260 = 2,2,1 - */ - - spin_lock_irqsave(&es1688->mixer_lock, flags); - snd_es1688_mixer_write(es1688, 0x40, 0x0b); /* don't change!!! */ - spin_unlock_irqrestore(&es1688->mixer_lock, flags); - - spin_lock_irqsave(&es1688->reg_lock, flags); - outb(gus->gf1.port & 0x040 ? 2 : 0, ES1688P(es1688, INIT1)); - outb(0, 0x201); - outb(gus->gf1.port & 0x020 ? 2 : 0, ES1688P(es1688, INIT1)); - outb(0, 0x201); - outb(gus->gf1.port & 0x010 ? 3 : 1, ES1688P(es1688, INIT1)); - spin_unlock_irqrestore(&es1688->reg_lock, flags); - - udelay(100); - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -EIO; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -EIO; - } - - return 0; -} - -static int __devinit snd_gusextreme_mixer(struct snd_card *card) -{ - struct snd_ctl_elem_id id1, id2; - int error; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - - /* reassign AUX to SYNTHESIZER */ - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "Synth Playback Volume"); - error = snd_ctl_rename_id(card, &id1, &id2); - if (error < 0) - return error; - - /* reassign Master Playback Switch to Synth Playback Switch */ - strcpy(id1.name, "Master Playback Switch"); - strcpy(id2.name, "Synth Playback Switch"); - error = snd_ctl_rename_id(card, &id1, &id2); - if (error < 0) - return error; - - return 0; -} - -static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n) -{ - struct snd_card *card; - struct snd_gus_card *gus; - struct snd_es1688 *es1688; - struct snd_opl3 *opl3; - int error; - - error = snd_card_create(index[n], id[n], THIS_MODULE, - sizeof(struct snd_es1688), &card); - if (error < 0) - return error; - - es1688 = card->private_data; - - if (mpu_port[n] == SNDRV_AUTO_PORT) - mpu_port[n] = 0; - - if (mpu_irq[n] > 15) - mpu_irq[n] = -1; - - error = snd_gusextreme_es1688_create(card, es1688, dev, n); - if (error < 0) - goto out; - - if (gf1_port[n] < 0) - gf1_port[n] = es1688->port + 0x20; - - error = snd_gusextreme_gus_card_create(card, dev, n, &gus); - if (error < 0) - goto out; - - error = snd_gusextreme_detect(gus, es1688); - if (error < 0) - goto out; - - gus->joystick_dac = joystick_dac[n]; - - error = snd_gus_initialize(gus); - if (error < 0) - goto out; - - error = -ENODEV; - if (!gus->ess_flag) { - dev_err(dev, "GUS Extreme soundcard was not " - "detected at 0x%lx\n", gus->gf1.port); - goto out; - } - gus->codec_flag = 1; - - error = snd_es1688_pcm(card, es1688, 0, NULL); - if (error < 0) - goto out; - - error = snd_es1688_mixer(card, es1688); - if (error < 0) - goto out; - - snd_component_add(card, "ES1688"); - - if (pcm_channels[n] > 0) { - error = snd_gf1_pcm_new(gus, 1, 1, NULL); - if (error < 0) - goto out; - } - - error = snd_gf1_new_mixer(gus); - if (error < 0) - goto out; - - error = snd_gusextreme_mixer(card); - if (error < 0) - goto out; - - if (snd_opl3_create(card, es1688->port, es1688->port + 2, - OPL3_HW_OPL3, 0, &opl3) < 0) - dev_warn(dev, "opl3 not detected at 0x%lx\n", es1688->port); - else { - error = snd_opl3_hwdep_new(opl3, 0, 2, NULL); - if (error < 0) - goto out; - } - - if (es1688->mpu_port >= 0x300) { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, - es1688->mpu_port, 0, mpu_irq[n], NULL); - if (error < 0) - goto out; - } - - sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, " - "irq %i&%i, dma %i&%i", es1688->port, - gus->gf1.irq, es1688->irq, gus->gf1.dma1, es1688->dma8); - - snd_card_set_dev(card, dev); - - error = snd_card_register(card); - if (error < 0) - goto out; - - dev_set_drvdata(dev, card); - return 0; - -out: snd_card_free(card); - return error; -} - -static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n) -{ - snd_card_free(dev_get_drvdata(dev)); - dev_set_drvdata(dev, NULL); - return 0; -} - -static struct isa_driver snd_gusextreme_driver = { - .match = snd_gusextreme_match, - .probe = snd_gusextreme_probe, - .remove = __devexit_p(snd_gusextreme_remove), -#if 0 /* FIXME */ - .suspend = snd_gusextreme_suspend, - .resume = snd_gusextreme_resume, -#endif - .driver = { - .name = DEV_NAME - } -}; - -static int __init alsa_card_gusextreme_init(void) -{ - return isa_register_driver(&snd_gusextreme_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_gusextreme_exit(void) -{ - isa_unregister_driver(&snd_gusextreme_driver); -} - -module_init(alsa_card_gusextreme_init); -module_exit(alsa_card_gusextreme_exit); diff --git a/ANDROID_3.4.5/sound/isa/gus/gusmax.c b/ANDROID_3.4.5/sound/isa/gus/gusmax.c deleted file mode 100644 index 41c3f448..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/gusmax.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Driver for Gravis UltraSound MAX soundcard - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/delay.h> -#include <linux/time.h> -#include <linux/module.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/gus.h> -#include <sound/wss.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Gravis UltraSound MAX"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24}; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for GUS MAX soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for GUS MAX soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable GUS MAX soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for GUS MAX driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for GUS MAX driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for GUS MAX driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for GUS MAX driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS MAX driver."); -module_param_array(channels, int, NULL, 0444); -MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver."); - -struct snd_gusmax { - int irq; - struct snd_card *card; - struct snd_gus_card *gus; - struct snd_wss *wss; - unsigned short gus_status_reg; - unsigned short pcm_status_reg; -}; - -#define PFX "gusmax: " - -static int __devinit snd_gusmax_detect(struct snd_gus_card * gus) -{ - unsigned char d; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - - return 0; -} - -static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id) -{ - struct snd_gusmax *maxcard = dev_id; - int loop, max = 5; - int handled = 0; - - do { - loop = 0; - if (inb(maxcard->gus_status_reg)) { - handled = 1; - snd_gus_interrupt(irq, maxcard->gus); - loop++; - } - if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ - handled = 1; - snd_wss_interrupt(irq, maxcard->wss); - loop++; - } - } while (loop && --max > 0); - return IRQ_RETVAL(handled); -} - -static void __devinit snd_gusmax_init(int dev, struct snd_card *card, - struct snd_gus_card * gus) -{ - gus->equal_irq = 1; - gus->codec_flag = 1; - gus->joystick_dac = joystick_dac[dev]; - /* init control register */ - gus->max_cntrl_val = (gus->gf1.port >> 4) & 0x0f; - if (gus->gf1.dma1 > 3) - gus->max_cntrl_val |= 0x10; - if (gus->gf1.dma2 > 3) - gus->max_cntrl_val |= 0x20; - gus->max_cntrl_val |= 0x40; - outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT)); -} - -static int __devinit snd_gusmax_mixer(struct snd_wss *chip) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id1, id2; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUXA to SYNTHESIZER */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "Synth Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "Synth Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - /* reassign AUXB to CD */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; -#if 0 - /* reassign Mono Input to MIC */ - if (snd_mixer_group_rename(mixer, - SNDRV_MIXER_IN_MONO, 0, - SNDRV_MIXER_IN_MIC, 0) < 0) - goto __error; - if (snd_mixer_elem_rename(mixer, - SNDRV_MIXER_IN_MONO, 0, SNDRV_MIXER_ETYPE_INPUT, - SNDRV_MIXER_IN_MIC, 0) < 0) - goto __error; - if (snd_mixer_elem_rename(mixer, - "Mono Capture Volume", 0, SNDRV_MIXER_ETYPE_VOLUME1, - "Mic Capture Volume", 0) < 0) - goto __error; - if (snd_mixer_elem_rename(mixer, - "Mono Capture Switch", 0, SNDRV_MIXER_ETYPE_SWITCH1, - "Mic Capture Switch", 0) < 0) - goto __error; -#endif - return 0; -} - -static void snd_gusmax_free(struct snd_card *card) -{ - struct snd_gusmax *maxcard = card->private_data; - - if (maxcard == NULL) - return; - if (maxcard->irq >= 0) - free_irq(maxcard->irq, (void *)maxcard); -} - -static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev) -{ - return enable[dev]; -} - -static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev) -{ - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; - static int possible_dmas[] = {5, 6, 7, 1, 3, -1}; - int xirq, xdma1, xdma2, err; - struct snd_card *card; - struct snd_gus_card *gus = NULL; - struct snd_wss *wss; - struct snd_gusmax *maxcard; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_gusmax), &card); - if (err < 0) - return err; - card->private_free = snd_gusmax_free; - maxcard = card->private_data; - maxcard->card = card; - maxcard->irq = -1; - - xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - err = -EBUSY; - goto _err; - } - } - xdma1 = dma1[dev]; - if (xdma1 == SNDRV_AUTO_DMA) { - if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); - err = -EBUSY; - goto _err; - } - } - xdma2 = dma2[dev]; - if (xdma2 == SNDRV_AUTO_DMA) { - if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); - err = -EBUSY; - goto _err; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) { - err = snd_gus_create(card, - port[dev], - -xirq, xdma1, xdma2, - 0, channels[dev], - pcm_channels[dev], - 0, &gus); - } else { - static unsigned long possible_ports[] = { - 0x220, 0x230, 0x240, 0x250, 0x260 - }; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - err = snd_gus_create(card, - possible_ports[i], - -xirq, xdma1, xdma2, - 0, channels[dev], - pcm_channels[dev], - 0, &gus); - if (err >= 0) { - port[dev] = possible_ports[i]; - break; - } - } - } - if (err < 0) - goto _err; - - if ((err = snd_gusmax_detect(gus)) < 0) - goto _err; - - maxcard->gus_status_reg = gus->gf1.reg_irqstat; - maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; - snd_gusmax_init(dev, card, gus); - if ((err = snd_gus_initialize(gus)) < 0) - goto _err; - - if (!gus->max_flag) { - snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port); - err = -ENODEV; - goto _err; - } - - if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) { - snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); - err = -EBUSY; - goto _err; - } - maxcard->irq = xirq; - - err = snd_wss_create(card, - gus->gf1.port + 0x10c, -1, xirq, - xdma2 < 0 ? xdma1 : xdma2, xdma1, - WSS_HW_DETECT, - WSS_HWSHARE_IRQ | - WSS_HWSHARE_DMA1 | - WSS_HWSHARE_DMA2, - &wss); - if (err < 0) - goto _err; - - err = snd_wss_pcm(wss, 0, NULL); - if (err < 0) - goto _err; - - err = snd_wss_mixer(wss); - if (err < 0) - goto _err; - - err = snd_wss_timer(wss, 2, NULL); - if (err < 0) - goto _err; - - if (pcm_channels[dev] > 0) { - if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0) - goto _err; - } - err = snd_gusmax_mixer(wss); - if (err < 0) - goto _err; - - err = snd_gf1_rawmidi_new(gus, 0, NULL); - if (err < 0) - goto _err; - - sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1); - if (xdma2 >= 0) - sprintf(card->longname + strlen(card->longname), "&%i", xdma2); - - snd_card_set_dev(card, pdev); - - err = snd_card_register(card); - if (err < 0) - goto _err; - - maxcard->gus = gus; - maxcard->wss = wss; - - dev_set_drvdata(pdev, card); - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "gusmax" - -static struct isa_driver snd_gusmax_driver = { - .match = snd_gusmax_match, - .probe = snd_gusmax_probe, - .remove = __devexit_p(snd_gusmax_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -static int __init alsa_card_gusmax_init(void) -{ - return isa_register_driver(&snd_gusmax_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_gusmax_exit(void) -{ - isa_unregister_driver(&snd_gusmax_driver); -} - -module_init(alsa_card_gusmax_init) -module_exit(alsa_card_gusmax_exit) diff --git a/ANDROID_3.4.5/sound/isa/gus/interwave-stb.c b/ANDROID_3.4.5/sound/isa/gus/interwave-stb.c deleted file mode 100644 index dbe4f48a..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/interwave-stb.c +++ /dev/null @@ -1,2 +0,0 @@ -#define SNDRV_STB -#include "interwave.c" diff --git a/ANDROID_3.4.5/sound/isa/gus/interwave.c b/ANDROID_3.4.5/sound/isa/gus/interwave.c deleted file mode 100644 index a76bc8d2..00000000 --- a/ANDROID_3.4.5/sound/isa/gus/interwave.c +++ /dev/null @@ -1,947 +0,0 @@ -/* - * Driver for AMD InterWave soundcard - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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 - * - * 1999/07/22 Erik Inge Bolso <knan@mo.himolde.no> - * * mixer group handlers - * - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/isa.h> -#include <linux/delay.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/gus.h> -#include <sound/wss.h> -#ifdef SNDRV_STB -#include <sound/tea6330t.h> -#endif -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -#ifndef SNDRV_STB -MODULE_DESCRIPTION("AMD InterWave"); -MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Plug & Play}," - "{STB,SoundRage32}," - "{MED,MED3210}," - "{Dynasonix,Dynasonix Pro}," - "{Panasonic,PCA761AW}}"); -#else -MODULE_DESCRIPTION("AMD InterWave STB with TEA6330T"); -MODULE_SUPPORTED_DEVICE("{{AMD,InterWave STB with TEA6330T}}"); -#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_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x210,0x220,0x230,0x240,0x250,0x260 */ -#ifdef SNDRV_STB -static long port_tc[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x350,0x360,0x370,0x380 */ -#endif -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; - /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ -static int midi[SNDRV_CARDS]; -static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; -static int effect[SNDRV_CARDS]; - -#ifdef SNDRV_STB -#define PFX "interwave-stb: " -#define INTERWAVE_DRIVER "snd_interwave_stb" -#define INTERWAVE_PNP_DRIVER "interwave-stb" -#else -#define PFX "interwave: " -#define INTERWAVE_DRIVER "snd_interwave" -#define INTERWAVE_PNP_DRIVER "interwave" -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for InterWave soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for InterWave soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable InterWave soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for InterWave driver."); -#ifdef SNDRV_STB -module_param_array(port_tc, long, NULL, 0444); -MODULE_PARM_DESC(port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver."); -#endif -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for InterWave driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for InterWave driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for InterWave driver."); -module_param_array(joystick_dac, int, NULL, 0444); -MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver."); -module_param_array(midi, int, NULL, 0444); -MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver."); -module_param_array(pcm_channels, int, NULL, 0444); -MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver."); -module_param_array(effect, int, NULL, 0444); -MODULE_PARM_DESC(effect, "Effects enable for InterWave driver."); - -struct snd_interwave { - int irq; - struct snd_card *card; - struct snd_gus_card *gus; - struct snd_wss *wss; -#ifdef SNDRV_STB - struct resource *i2c_res; -#endif - unsigned short gus_status_reg; - unsigned short pcm_status_reg; -#ifdef CONFIG_PNP - struct pnp_dev *dev; -#ifdef SNDRV_STB - struct pnp_dev *devtc; -#endif -#endif -}; - - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id snd_interwave_pnpids[] = { -#ifndef SNDRV_STB - /* Gravis UltraSound Plug & Play */ - { .id = "GRV0001", .devs = { { .id = "GRV0000" } } }, - /* STB SoundRage32 */ - { .id = "STB011a", .devs = { { .id = "STB0010" } } }, - /* MED3210 */ - { .id = "DXP3201", .devs = { { .id = "DXP0010" } } }, - /* Dynasonic Pro */ - /* This device also have CDC1117:DynaSonix Pro Audio Effects Processor */ - { .id = "CDC1111", .devs = { { .id = "CDC1112" } } }, - /* Panasonic PCA761AW Audio Card */ - { .id = "ADV55ff", .devs = { { .id = "ADV0010" } } }, - /* InterWave STB without TEA6330T */ - { .id = "ADV550a", .devs = { { .id = "ADV0010" } } }, -#else - /* InterWave STB with TEA6330T */ - { .id = "ADV550a", .devs = { { .id = "ADV0010" }, { .id = "ADV0015" } } }, -#endif - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_interwave_pnpids); - -#endif /* CONFIG_PNP */ - - -#ifdef SNDRV_STB -static void snd_interwave_i2c_setlines(struct snd_i2c_bus *bus, int ctrl, int data) -{ - unsigned long port = bus->private_value; - -#if 0 - printk(KERN_DEBUG "i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data); -#endif - outb((data << 1) | ctrl, port); - udelay(10); -} - -static int snd_interwave_i2c_getclockline(struct snd_i2c_bus *bus) -{ - unsigned long port = bus->private_value; - unsigned char res; - - res = inb(port) & 1; -#if 0 - printk(KERN_DEBUG "i2c_getclockline - 0x%lx -> %i\n", port, res); -#endif - return res; -} - -static int snd_interwave_i2c_getdataline(struct snd_i2c_bus *bus, int ack) -{ - unsigned long port = bus->private_value; - unsigned char res; - - if (ack) - udelay(10); - res = (inb(port) & 2) >> 1; -#if 0 - printk(KERN_DEBUG "i2c_getdataline - 0x%lx -> %i\n", port, res); -#endif - return res; -} - -static struct snd_i2c_bit_ops snd_interwave_i2c_bit_ops = { - .setlines = snd_interwave_i2c_setlines, - .getclock = snd_interwave_i2c_getclockline, - .getdata = snd_interwave_i2c_getdataline, -}; - -static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard, - struct snd_gus_card * gus, int dev, - struct snd_i2c_bus **rbus) -{ - unsigned long port; - struct snd_i2c_bus *bus; - struct snd_card *card = iwcard->card; - char name[32]; - int err; - - *rbus = NULL; - port = port_tc[dev]; - if (port == SNDRV_AUTO_PORT) { - port = 0x350; - if (gus->gf1.port == 0x250) { - port = 0x360; - } - while (port <= 0x380) { - if ((iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)")) != NULL) - break; - port += 0x10; - } - } else { - iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)"); - } - if (iwcard->i2c_res == NULL) { - snd_printk(KERN_ERR "interwave: can't grab i2c bus port\n"); - return -ENODEV; - } - - sprintf(name, "InterWave-%i", card->number); - if ((err = snd_i2c_bus_create(card, name, NULL, &bus)) < 0) - return err; - bus->private_value = port; - bus->hw_ops.bit = &snd_interwave_i2c_bit_ops; - if ((err = snd_tea6330t_detect(bus, 0)) < 0) - return err; - *rbus = bus; - return 0; -} -#endif - -static int __devinit snd_interwave_detect(struct snd_interwave *iwcard, - struct snd_gus_card * gus, - int dev -#ifdef SNDRV_STB - , struct snd_i2c_bus **rbus -#endif - ) -{ - unsigned long flags; - unsigned char rev1, rev2; - int d; - - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { - snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - udelay(160); - snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ - udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { - snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); - return -ENODEV; - } - spin_lock_irqsave(&gus->reg_lock, flags); - rev1 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, ~rev1); - rev2 = snd_gf1_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, rev1); - spin_unlock_irqrestore(&gus->reg_lock, flags); - snd_printdd("[0x%lx] InterWave check - rev1=0x%x, rev2=0x%x\n", gus->gf1.port, rev1, rev2); - if ((rev1 & 0xf0) == (rev2 & 0xf0) && - (rev1 & 0x0f) != (rev2 & 0x0f)) { - snd_printdd("[0x%lx] InterWave check - passed\n", gus->gf1.port); - gus->interwave = 1; - strcpy(gus->card->shortname, "AMD InterWave"); - gus->revision = rev1 >> 4; -#ifndef SNDRV_STB - return 0; /* ok.. We have an InterWave board */ -#else - return snd_interwave_detect_stb(iwcard, gus, dev, rbus); -#endif - } - snd_printdd("[0x%lx] InterWave check - failed\n", gus->gf1.port); - return -ENODEV; -} - -static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id) -{ - struct snd_interwave *iwcard = dev_id; - int loop, max = 5; - int handled = 0; - - do { - loop = 0; - if (inb(iwcard->gus_status_reg)) { - handled = 1; - snd_gus_interrupt(irq, iwcard->gus); - loop++; - } - if (inb(iwcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */ - handled = 1; - snd_wss_interrupt(irq, iwcard->wss); - loop++; - } - } while (loop && --max > 0); - return IRQ_RETVAL(handled); -} - -static void __devinit snd_interwave_reset(struct snd_gus_card * gus) -{ - snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00); - udelay(160); - snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x01); - udelay(160); -} - -static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *sizes) -{ - unsigned int idx; - unsigned int local; - unsigned char d; - - for (idx = 0; idx < 4; idx++) { - sizes[idx] = 0; - d = 0x55; - for (local = idx << 22; - local < (idx << 22) + 0x400000; - local += 0x40000, d++) { - snd_gf1_poke(gus, local, d); - snd_gf1_poke(gus, local + 1, d + 1); -#if 0 - printk(KERN_DEBUG "d = 0x%x, local = 0x%x, " - "local + 1 = 0x%x, idx << 22 = 0x%x\n", - d, - snd_gf1_peek(gus, local), - snd_gf1_peek(gus, local + 1), - snd_gf1_peek(gus, idx << 22)); -#endif - if (snd_gf1_peek(gus, local) != d || - snd_gf1_peek(gus, local + 1) != d + 1 || - snd_gf1_peek(gus, idx << 22) != 0x55) - break; - sizes[idx]++; - } - } -#if 0 - printk(KERN_DEBUG "sizes: %i %i %i %i\n", - sizes[0], sizes[1], sizes[2], sizes[3]); -#endif -} - -struct rom_hdr { - /* 000 */ unsigned char iwave[8]; - /* 008 */ unsigned char rom_hdr_revision; - /* 009 */ unsigned char series_number; - /* 010 */ unsigned char series_name[16]; - /* 026 */ unsigned char date[10]; - /* 036 */ unsigned short vendor_revision_major; - /* 038 */ unsigned short vendor_revision_minor; - /* 040 */ unsigned int rom_size; - /* 044 */ unsigned char copyright[128]; - /* 172 */ unsigned char vendor_name[64]; - /* 236 */ unsigned char rom_description[128]; - /* 364 */ unsigned char pad[147]; - /* 511 */ unsigned char csum; -}; - -static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus) -{ - static unsigned int lmc[13] = - { - 0x00000001, 0x00000101, 0x01010101, 0x00000401, - 0x04040401, 0x00040101, 0x04040101, 0x00000004, - 0x00000404, 0x04040404, 0x00000010, 0x00001010, - 0x10101010 - }; - - int bank_pos, pages; - unsigned int i, lmct; - int psizes[4]; - unsigned char iwave[8]; - unsigned char csum; - - snd_interwave_reset(gus); - snd_gf1_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01); /* enhanced mode */ - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); /* DRAM I/O cycles selected */ - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff10) | 0x004c); - /* ok.. simple test of memory size */ - pages = 0; - snd_gf1_poke(gus, 0, 0x55); - snd_gf1_poke(gus, 1, 0xaa); -#if 1 - if (snd_gf1_peek(gus, 0) == 0x55 && snd_gf1_peek(gus, 1) == 0xaa) -#else - if (0) /* ok.. for testing of 0k RAM */ -#endif - { - snd_interwave_bank_sizes(gus, psizes); - lmct = (psizes[3] << 24) | (psizes[2] << 16) | - (psizes[1] << 8) | psizes[0]; -#if 0 - printk(KERN_DEBUG "lmct = 0x%08x\n", lmct); -#endif - for (i = 0; i < ARRAY_SIZE(lmc); i++) - if (lmct == lmc[i]) { -#if 0 - printk(KERN_DEBUG "found !!! %i\n", i); -#endif - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | i); - snd_interwave_bank_sizes(gus, psizes); - break; - } - if (i >= ARRAY_SIZE(lmc) && !gus->gf1.enh_mode) - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | 2); - for (i = 0; i < 4; i++) { - gus->gf1.mem_alloc.banks_8[i].address = - gus->gf1.mem_alloc.banks_16[i].address = i << 22; - gus->gf1.mem_alloc.banks_8[i].size = - gus->gf1.mem_alloc.banks_16[i].size = psizes[i] << 18; - pages += psizes[i]; - } - } - pages <<= 18; - gus->gf1.memory = pages; - - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x03); /* select ROM */ - snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xff1f) | (4 << 5)); - gus->gf1.rom_banks = 0; - gus->gf1.rom_memory = 0; - for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) { - for (i = 0; i < 8; ++i) - iwave[i] = snd_gf1_peek(gus, bank_pos + i); -#ifdef CONFIG_SND_DEBUG_ROM - printk(KERN_DEBUG "ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos, - iwave[0], iwave[1], iwave[2], iwave[3], - iwave[4], iwave[5], iwave[6], iwave[7]); -#endif - if (strncmp(iwave, "INTRWAVE", 8)) - continue; /* first check */ - csum = 0; - for (i = 0; i < sizeof(struct rom_hdr); i++) - csum += snd_gf1_peek(gus, bank_pos + i); -#ifdef CONFIG_SND_DEBUG_ROM - printk(KERN_DEBUG "ROM checksum = 0x%x (computed)\n", csum); -#endif - if (csum != 0) - continue; /* not valid rom */ - gus->gf1.rom_banks++; - gus->gf1.rom_present |= 1 << (bank_pos >> 22); - gus->gf1.rom_memory = snd_gf1_peek(gus, bank_pos + 40) | - (snd_gf1_peek(gus, bank_pos + 41) << 8) | - (snd_gf1_peek(gus, bank_pos + 42) << 16) | - (snd_gf1_peek(gus, bank_pos + 43) << 24); - } -#if 0 - if (gus->gf1.rom_memory > 0) { - if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8) - gus->card->type = SNDRV_CARD_TYPE_IW_DYNASONIC; - } -#endif - snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x00); /* select RAM */ - - if (!gus->gf1.enh_mode) - snd_interwave_reset(gus); -} - -static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus) -{ - unsigned long flags; - - /* ok.. some InterWave specific initialization */ - spin_lock_irqsave(&gus->reg_lock, flags); - snd_gf1_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0x00); - snd_gf1_write8(gus, SNDRV_GF1_GB_COMPATIBILITY, 0x1f); - snd_gf1_write8(gus, SNDRV_GF1_GB_DECODE_CONTROL, 0x49); - snd_gf1_write8(gus, SNDRV_GF1_GB_VERSION_NUMBER, 0x11); - snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A, 0x00); - snd_gf1_write8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B, 0x30); - snd_gf1_write8(gus, SNDRV_GF1_GB_EMULATION_IRQ, 0x00); - spin_unlock_irqrestore(&gus->reg_lock, flags); - gus->equal_irq = 1; - gus->codec_flag = 1; - gus->interwave = 1; - gus->max_flag = 1; - gus->joystick_dac = joystick_dac[dev]; - -} - -static struct snd_kcontrol_new snd_interwave_controls[] = { -WSS_DOUBLE("Master Playback Switch", 0, - CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE("Master Playback Volume", 0, - CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1), -WSS_DOUBLE("Mic Playback Switch", 0, - CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1), -WSS_DOUBLE("Mic Playback Volume", 0, - CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1) -}; - -static int __devinit snd_interwave_mixer(struct snd_wss *chip) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id1, id2; - unsigned int idx; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; -#if 0 - /* remove mono microphone controls */ - strcpy(id1.name, "Mic Playback Switch"); - if ((err = snd_ctl_remove_id(card, &id1)) < 0) - return err; - strcpy(id1.name, "Mic Playback Volume"); - if ((err = snd_ctl_remove_id(card, &id1)) < 0) - return err; -#endif - /* add new master and mic controls */ - for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0) - return err; - snd_wss_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f); - snd_wss_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f); - snd_wss_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f); - snd_wss_out(chip, CS4231_RIGHT_MIC_INPUT, 0x9f); - /* reassign AUXA to SYNTHESIZER */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "Synth Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "Synth Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - /* reassign AUXB to CD */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - return 0; -} - -#ifdef CONFIG_PNP - -static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - iwcard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (iwcard->dev == NULL) - return -EBUSY; - -#ifdef SNDRV_STB - iwcard->devtc = pnp_request_card_device(card, id->devs[1].id, NULL); - if (iwcard->devtc == NULL) - return -EBUSY; -#endif - /* Synth & Codec initialization */ - pdev = iwcard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "InterWave PnP configure failure (out of resources?)\n"); - return err; - } - if (pnp_port_start(pdev, 0) + 0x100 != pnp_port_start(pdev, 1) || - pnp_port_start(pdev, 0) + 0x10c != pnp_port_start(pdev, 2)) { - snd_printk(KERN_ERR "PnP configure failure (wrong ports)\n"); - return -ENOENT; - } - port[dev] = pnp_port_start(pdev, 0); - dma1[dev] = pnp_dma(pdev, 0); - if (dma2[dev] >= 0) - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("isapnp IW: sb port=0x%llx, gf1 port=0x%llx, codec port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0), - (unsigned long long)pnp_port_start(pdev, 1), - (unsigned long long)pnp_port_start(pdev, 2)); - snd_printdd("isapnp IW: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); -#ifdef SNDRV_STB - /* Tone Control initialization */ - pdev = iwcard->devtc; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "InterWave ToneControl PnP configure failure (out of resources?)\n"); - return err; - } - port_tc[dev] = pnp_port_start(pdev, 0); - snd_printdd("isapnp IW: tone control port=0x%lx\n", port_tc[dev]); -#endif - return 0; -} -#endif /* CONFIG_PNP */ - -static void snd_interwave_free(struct snd_card *card) -{ - struct snd_interwave *iwcard = card->private_data; - - if (iwcard == NULL) - return; -#ifdef SNDRV_STB - release_and_free_resource(iwcard->i2c_res); -#endif - if (iwcard->irq >= 0) - free_irq(iwcard->irq, (void *)iwcard); -} - -static int snd_interwave_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - struct snd_interwave *iwcard; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_interwave), &card); - if (err < 0) - return err; - iwcard = card->private_data; - iwcard->card = card; - iwcard->irq = -1; - card->private_free = snd_interwave_free; - *cardp = card; - return 0; -} - -static int __devinit snd_interwave_probe(struct snd_card *card, int dev) -{ - int xirq, xdma1, xdma2; - struct snd_interwave *iwcard = card->private_data; - struct snd_wss *wss; - struct snd_gus_card *gus; -#ifdef SNDRV_STB - struct snd_i2c_bus *i2c_bus; -#endif - struct snd_pcm *pcm; - char *str; - int err; - - xirq = irq[dev]; - xdma1 = dma1[dev]; - xdma2 = dma2[dev]; - - if ((err = snd_gus_create(card, - port[dev], - -xirq, xdma1, xdma2, - 0, 32, - pcm_channels[dev], effect[dev], &gus)) < 0) - return err; - - if ((err = snd_interwave_detect(iwcard, gus, dev -#ifdef SNDRV_STB - , &i2c_bus -#endif - )) < 0) - return err; - - iwcard->gus_status_reg = gus->gf1.reg_irqstat; - iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; - - snd_interwave_init(dev, gus); - snd_interwave_detect_memory(gus); - if ((err = snd_gus_initialize(gus)) < 0) - return err; - - if (request_irq(xirq, snd_interwave_interrupt, 0, - "InterWave", iwcard)) { - snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); - return -EBUSY; - } - iwcard->irq = xirq; - - err = snd_wss_create(card, - gus->gf1.port + 0x10c, -1, xirq, - xdma2 < 0 ? xdma1 : xdma2, xdma1, - WSS_HW_INTERWAVE, - WSS_HWSHARE_IRQ | - WSS_HWSHARE_DMA1 | - WSS_HWSHARE_DMA2, - &wss); - if (err < 0) - return err; - - err = snd_wss_pcm(wss, 0, &pcm); - if (err < 0) - return err; - - sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A'); - strcat(pcm->name, " (codec)"); - - err = snd_wss_timer(wss, 2, NULL); - if (err < 0) - return err; - - err = snd_wss_mixer(wss); - if (err < 0) - return err; - - if (pcm_channels[dev] > 0) { - err = snd_gf1_pcm_new(gus, 1, 1, NULL); - if (err < 0) - return err; - } - err = snd_interwave_mixer(wss); - if (err < 0) - return err; - -#ifdef SNDRV_STB - { - struct snd_ctl_elem_id id1, id2; - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id1.name, "Master Playback Switch"); - strcpy(id2.name, id1.name); - id2.index = 1; - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - strcpy(id1.name, "Master Playback Volume"); - strcpy(id2.name, id1.name); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) - return err; - if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) - return err; - } -#endif - - gus->uart_enable = midi[dev]; - if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0) - return err; - -#ifndef SNDRV_STB - str = "AMD InterWave"; - if (gus->gf1.rom_banks == 1 && gus->gf1.rom_present == 8) - str = "Dynasonic 3-D"; -#else - str = "InterWave STB"; -#endif - strcpy(card->driver, str); - strcpy(card->shortname, str); - sprintf(card->longname, "%s at 0x%lx, irq %i, dma %d", - str, - gus->gf1.port, - xirq, - xdma1); - if (xdma2 >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", xdma2); - - err = snd_card_register(card); - if (err < 0) - return err; - - iwcard->wss = wss; - iwcard->gus = gus; - return 0; -} - -static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr) -{ - struct snd_card *card; - int err; - - err = snd_interwave_card_new(dev, &card); - if (err < 0) - return err; - - snd_card_set_dev(card, devptr); - if ((err = snd_interwave_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devinit snd_interwave_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev]) - return 0; -#ifdef CONFIG_PNP - if (isapnp[dev]) - return 0; -#endif - return 1; -} - -static int __devinit snd_interwave_isa_probe(struct device *pdev, - unsigned int dev) -{ - int err; - static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1}; - static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; - - if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma1[dev] == SNDRV_AUTO_DMA) { - if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2[dev] == SNDRV_AUTO_DMA) { - if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) - return snd_interwave_isa_probe1(dev, pdev); - else { - static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260}; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - port[dev] = possible_ports[i]; - err = snd_interwave_isa_probe1(dev, pdev); - if (! err) - return 0; - } - return err; - } -} - -static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -static struct isa_driver snd_interwave_driver = { - .match = snd_interwave_isa_match, - .probe = snd_interwave_isa_probe, - .remove = __devexit_p(snd_interwave_isa_remove), - /* FIXME: suspend,resume */ - .driver = { - .name = INTERWAVE_DRIVER - }, -}; - -#ifdef CONFIG_PNP -static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_interwave_card_new(dev, &card); - if (res < 0) - return res; - - if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { - snd_card_free(card); - return res; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_interwave_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver interwave_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = INTERWAVE_PNP_DRIVER, - .id_table = snd_interwave_pnpids, - .probe = snd_interwave_pnp_detect, - .remove = __devexit_p(snd_interwave_pnp_remove), - /* FIXME: suspend,resume */ -}; - -#endif /* CONFIG_PNP */ - -static int __init alsa_card_interwave_init(void) -{ - int err; - - err = isa_register_driver(&snd_interwave_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&interwave_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_interwave_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&interwave_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_interwave_driver); -} - -module_init(alsa_card_interwave_init) -module_exit(alsa_card_interwave_exit) diff --git a/ANDROID_3.4.5/sound/isa/msnd/Makefile b/ANDROID_3.4.5/sound/isa/msnd/Makefile deleted file mode 100644 index 2171c0aa..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/Makefile +++ /dev/null @@ -1,9 +0,0 @@ - -snd-msnd-lib-objs := msnd.o msnd_midi.o msnd_pinnacle_mixer.o -snd-msnd-pinnacle-objs := msnd_pinnacle.o -snd-msnd-classic-objs := msnd_classic.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_MSND_PINNACLE) += snd-msnd-pinnacle.o snd-msnd-lib.o -obj-$(CONFIG_SND_MSND_CLASSIC) += snd-msnd-classic.o snd-msnd-lib.o - diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd.c b/ANDROID_3.4.5/sound/isa/msnd/msnd.c deleted file mode 100644 index 1cee18fb..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd.c +++ /dev/null @@ -1,708 +0,0 @@ -/********************************************************************* - * - * 2002/06/30 Karsten Wiese: - * removed kernel-version dependencies. - * ripped from linux kernel 2.4.18 (OSS Implementation) by me. - * In the OSS Version, this file is compiled to a separate MODULE, - * that is used by the pinnacle and the classic driver. - * since there is no classic driver for alsa yet (i dont have a classic - * & writing one blindfold is difficult) this file's object is statically - * linked into the pinnacle-driver-module for now. look for the string - * "uncomment this to make this a module again" - * to do guess what. - * - * the following is a copy of the 2.4.18 OSS FREE file-heading comment: - * - * msnd.c - Driver Base - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Copyright (C) 1998 Andrew Veliath - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/module.h> - -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> - -#include "msnd.h" - -#define LOGNAME "msnd" - - -void snd_msnd_init_queue(void *base, int start, int size) -{ - writew(PCTODSP_BASED(start), base + JQS_wStart); - writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize); - writew(0, base + JQS_wHead); - writew(0, base + JQS_wTail); -} -EXPORT_SYMBOL(snd_msnd_init_queue); - -static int snd_msnd_wait_TXDE(struct snd_msnd *dev) -{ - unsigned int io = dev->io; - int timeout = 1000; - - while (timeout-- > 0) - if (inb(io + HP_ISR) & HPISR_TXDE) - return 0; - - return -EIO; -} - -static int snd_msnd_wait_HC0(struct snd_msnd *dev) -{ - unsigned int io = dev->io; - int timeout = 1000; - - while (timeout-- > 0) - if (!(inb(io + HP_CVR) & HPCVR_HC)) - return 0; - - return -EIO; -} - -int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - if (snd_msnd_wait_HC0(dev) == 0) { - outb(cmd, dev->io + HP_CVR); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_send_dsp_cmd); - -int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high, - unsigned char mid, unsigned char low) -{ - unsigned int io = dev->io; - - if (snd_msnd_wait_TXDE(dev) == 0) { - outb(high, io + HP_TXH); - outb(mid, io + HP_TXM); - outb(low, io + HP_TXL); - return 0; - } - - snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_send_word); - -int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len) -{ - int i; - - if (len % 3 != 0) { - snd_printk(KERN_ERR LOGNAME - ": Upload host data not multiple of 3!\n"); - return -EINVAL; - } - - for (i = 0; i < len; i += 3) - if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2])) - return -EIO; - - inb(dev->io + HP_RXL); - inb(dev->io + HP_CVR); - - return 0; -} -EXPORT_SYMBOL(snd_msnd_upload_host); - -int snd_msnd_enable_irq(struct snd_msnd *dev) -{ - unsigned long flags; - - if (dev->irq_ref++) - return 0; - - snd_printdd(LOGNAME ": Enabling IRQ\n"); - - spin_lock_irqsave(&dev->lock, flags); - if (snd_msnd_wait_TXDE(dev) == 0) { - outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); - if (dev->type == msndClassic) - outb(dev->irqid, dev->io + HP_IRQM); - - outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR); - outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR); - enable_irq(dev->irq); - snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, - dev->dspq_buff_size); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_enable_irq); - -int snd_msnd_disable_irq(struct snd_msnd *dev) -{ - unsigned long flags; - - if (--dev->irq_ref > 0) - return 0; - - if (dev->irq_ref < 0) - snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", - dev->irq_ref); - - snd_printdd(LOGNAME ": Disabling IRQ\n"); - - spin_lock_irqsave(&dev->lock, flags); - if (snd_msnd_wait_TXDE(dev) == 0) { - outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); - if (dev->type == msndClassic) - outb(HPIRQ_NONE, dev->io + HP_IRQM); - disable_irq(dev->irq); - spin_unlock_irqrestore(&dev->lock, flags); - return 0; - } - spin_unlock_irqrestore(&dev->lock, flags); - - snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n"); - - return -EIO; -} -EXPORT_SYMBOL(snd_msnd_disable_irq); - -static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size) -{ - long tmp = (size * HZ * chip->play_sample_size) / 8; - return tmp / (chip->play_sample_rate * chip->play_channels); -} - -static void snd_msnd_dsp_write_flush(struct snd_msnd *chip) -{ - if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags)) - return; - set_bit(F_WRITEFLUSH, &chip->flags); -/* interruptible_sleep_on_timeout( - &chip->writeflush, - get_play_delay_jiffies(&chip, chip->DAPF.len));*/ - clear_bit(F_WRITEFLUSH, &chip->flags); - if (!signal_pending(current)) - schedule_timeout_interruptible( - get_play_delay_jiffies(chip, chip->play_period_bytes)); - clear_bit(F_WRITING, &chip->flags); -} - -void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) -{ - if ((file ? file->f_mode : chip->mode) & FMODE_READ) { - clear_bit(F_READING, &chip->flags); - snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); - snd_msnd_disable_irq(chip); - if (file) { - snd_printd(KERN_INFO LOGNAME - ": Stopping read for %p\n", file); - chip->mode &= ~FMODE_READ; - } - clear_bit(F_AUDIO_READ_INUSE, &chip->flags); - } - if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) { - if (test_bit(F_WRITING, &chip->flags)) { - snd_msnd_dsp_write_flush(chip); - snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); - } - snd_msnd_disable_irq(chip); - if (file) { - snd_printd(KERN_INFO - LOGNAME ": Stopping write for %p\n", file); - chip->mode &= ~FMODE_WRITE; - } - clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); - } -} -EXPORT_SYMBOL(snd_msnd_dsp_halt); - - -int snd_msnd_DARQ(struct snd_msnd *chip, int bank) -{ - int /*size, n,*/ timeout = 3; - u16 wTmp; - /* void *DAQD; */ - - /* Increment the tail and check for queue wrap */ - wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size); - if (wTmp > readw(chip->DARQ + JQS_wSize)) - wTmp = 0; - while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--) - udelay(1); - - if (chip->capturePeriods == 2) { - void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF + - bank * DAQDS__size + DAQDS_wStart; - unsigned short offset = 0x3000 + chip->capturePeriodBytes; - - if (readw(pDAQ) != PCTODSP_BASED(0x3000)) - offset = 0x3000; - writew(PCTODSP_BASED(offset), pDAQ); - } - - writew(wTmp, chip->DARQ + JQS_wTail); - -#if 0 - /* Get our digital audio queue struct */ - DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF; - - /* Get length of data */ - size = readw(DAQD + DAQDS_wSize); - - /* Read data from the head (unprotected bank 1 access okay - since this is only called inside an interrupt) */ - outb(HPBLKSEL_1, chip->io + HP_BLKS); - n = msnd_fifo_write(&chip->DARF, - (char *)(chip->base + bank * DAR_BUFF_SIZE), - size, 0); - if (n <= 0) { - outb(HPBLKSEL_0, chip->io + HP_BLKS); - return n; - } - outb(HPBLKSEL_0, chip->io + HP_BLKS); -#endif - - return 1; -} -EXPORT_SYMBOL(snd_msnd_DARQ); - -int snd_msnd_DAPQ(struct snd_msnd *chip, int start) -{ - u16 DAPQ_tail; - int protect = start, nbanks = 0; - void *DAQD; - static int play_banks_submitted; - /* unsigned long flags; - spin_lock_irqsave(&chip->lock, flags); not necessary */ - - DAPQ_tail = readw(chip->DAPQ + JQS_wTail); - while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) { - int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); - - if (start) { - start = 0; - play_banks_submitted = 0; - } - - /* Get our digital audio queue struct */ - DAQD = bank_num * DAQDS__size + chip->mappedbase + - DAPQ_DATA_BUFF; - - /* Write size of this bank */ - writew(chip->play_period_bytes, DAQD + DAQDS_wSize); - if (play_banks_submitted < 3) - ++play_banks_submitted; - else if (chip->playPeriods == 2) { - unsigned short offset = chip->play_period_bytes; - - if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0)) - offset = 0; - - writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart); - } - ++nbanks; - - /* Then advance the tail */ - /* - if (protect) - snd_printd(KERN_INFO "B %X %lX\n", - bank_num, xtime.tv_usec); - */ - - DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); - writew(DAPQ_tail, chip->DAPQ + JQS_wTail); - /* Tell the DSP to play the bank */ - snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START); - if (protect) - if (2 == bank_num) - break; - } - /* - if (protect) - snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); - */ - /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ - return nbanks; -} -EXPORT_SYMBOL(snd_msnd_DAPQ); - -static void snd_msnd_play_reset_queue(struct snd_msnd *chip, - unsigned int pcm_periods, - unsigned int pcm_count) -{ - int n; - void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; - - chip->last_playbank = -1; - chip->playLimit = pcm_count * (pcm_periods - 1); - chip->playPeriods = pcm_periods; - writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead); - writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail); - - chip->play_period_bytes = pcm_count; - - for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { - writew(PCTODSP_BASED((u32)(pcm_count * n)), - pDAQ + DAQDS_wStart); - writew(0, pDAQ + DAQDS_wSize); - writew(1, pDAQ + DAQDS_wFormat); - writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->play_channels, pDAQ + DAQDS_wChannels); - writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); - writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); - writew(n, pDAQ + DAQDS_wFlags); - } -} - -static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, - unsigned int pcm_periods, - unsigned int pcm_count) -{ - int n; - void *pDAQ; - /* unsigned long flags; */ - - /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ - - chip->last_recbank = 2; - chip->captureLimit = pcm_count * (pcm_periods - 1); - chip->capturePeriods = pcm_periods; - writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead); - writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size), - chip->DARQ + JQS_wTail); - -#if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/ - spin_lock_irqsave(&chip->lock, flags); - outb(HPBLKSEL_1, chip->io + HP_BLKS); - memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3); - outb(HPBLKSEL_0, chip->io + HP_BLKS); - spin_unlock_irqrestore(&chip->lock, flags); -#endif - - chip->capturePeriodBytes = pcm_count; - snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count); - - pDAQ = chip->mappedbase + DARQ_DATA_BUFF; - - for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { - u32 tmp = pcm_count * n; - - writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart); - writew(pcm_count, pDAQ + DAQDS_wSize); - writew(1, pDAQ + DAQDS_wFormat); - writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->capture_channels, pDAQ + DAQDS_wChannels); - writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); - writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); - writew(n, pDAQ + DAQDS_wFlags); - } -} - -static struct snd_pcm_hardware snd_msnd_playback = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH, - .formats = SNDRV_PCM_FMTBIT_U8 | 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 = 0x3000, - .period_bytes_min = 0x40, - .period_bytes_max = 0x1800, - .periods_min = 2, - .periods_max = 3, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_msnd_capture = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH, - .formats = SNDRV_PCM_FMTBIT_U8 | 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 = 0x3000, - .period_bytes_min = 0x40, - .period_bytes_max = 0x1800, - .periods_min = 2, - .periods_max = 3, - .fifo_size = 0, -}; - - -static int snd_msnd_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - set_bit(F_AUDIO_WRITE_INUSE, &chip->flags); - clear_bit(F_WRITING, &chip->flags); - snd_msnd_enable_irq(chip); - - runtime->dma_area = chip->mappedbase; - runtime->dma_bytes = 0x3000; - - chip->playback_substream = substream; - runtime->hw = snd_msnd_playback; - return 0; -} - -static int snd_msnd_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - snd_msnd_disable_irq(chip); - clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); - return 0; -} - - -static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int i; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; - - chip->play_sample_size = snd_pcm_format_width(params_format(params)); - chip->play_channels = params_channels(params); - chip->play_sample_rate = params_rate(params); - - for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { - writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->play_channels, pDAQ + DAQDS_wChannels); - writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); - } - /* dont do this here: - * snd_msnd_calibrate_adc(chip->play_sample_rate); - */ - - return 0; -} - -static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); - unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); - unsigned int pcm_periods = pcm_size / pcm_count; - - snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count); - chip->playDMAPos = 0; - return 0; -} - -static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - int result = 0; - - if (cmd == SNDRV_PCM_TRIGGER_START) { - snd_printdd("snd_msnd_playback_trigger(START)\n"); - chip->banksPlayed = 0; - set_bit(F_WRITING, &chip->flags); - snd_msnd_DAPQ(chip, 1); - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - snd_printdd("snd_msnd_playback_trigger(STop)\n"); - /* interrupt diagnostic, comment this out later */ - clear_bit(F_WRITING, &chip->flags); - snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); - } else { - snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); - result = -EINVAL; - } - - snd_printdd("snd_msnd_playback_trigger() ENDE\n"); - return result; -} - -static snd_pcm_uframes_t -snd_msnd_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - return bytes_to_frames(substream->runtime, chip->playDMAPos); -} - - -static struct snd_pcm_ops snd_msnd_playback_ops = { - .open = snd_msnd_playback_open, - .close = snd_msnd_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_msnd_playback_hw_params, - .prepare = snd_msnd_playback_prepare, - .trigger = snd_msnd_playback_trigger, - .pointer = snd_msnd_playback_pointer, -}; - -static int snd_msnd_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - set_bit(F_AUDIO_READ_INUSE, &chip->flags); - snd_msnd_enable_irq(chip); - runtime->dma_area = chip->mappedbase + 0x3000; - runtime->dma_bytes = 0x3000; - memset(runtime->dma_area, 0, runtime->dma_bytes); - chip->capture_substream = substream; - runtime->hw = snd_msnd_capture; - return 0; -} - -static int snd_msnd_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - snd_msnd_disable_irq(chip); - clear_bit(F_AUDIO_READ_INUSE, &chip->flags); - return 0; -} - -static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); - unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); - unsigned int pcm_periods = pcm_size / pcm_count; - - snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count); - chip->captureDMAPos = 0; - return 0; -} - -static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - if (cmd == SNDRV_PCM_TRIGGER_START) { - chip->last_recbank = -1; - set_bit(F_READING, &chip->flags); - if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0) - return 0; - - clear_bit(F_READING, &chip->flags); - } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { - clear_bit(F_READING, &chip->flags); - snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); - return 0; - } - return -EINVAL; -} - - -static snd_pcm_uframes_t -snd_msnd_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - - return bytes_to_frames(runtime, chip->captureDMAPos); -} - - -static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - int i; - struct snd_msnd *chip = snd_pcm_substream_chip(substream); - void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; - - chip->capture_sample_size = snd_pcm_format_width(params_format(params)); - chip->capture_channels = params_channels(params); - chip->capture_sample_rate = params_rate(params); - - for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { - writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); - writew(chip->capture_channels, pDAQ + DAQDS_wChannels); - writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); - } - return 0; -} - - -static struct snd_pcm_ops snd_msnd_capture_ops = { - .open = snd_msnd_capture_open, - .close = snd_msnd_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_msnd_capture_hw_params, - .prepare = snd_msnd_capture_prepare, - .trigger = snd_msnd_capture_trigger, - .pointer = snd_msnd_capture_pointer, -}; - - -int snd_msnd_pcm(struct snd_card *card, int device, - struct snd_pcm **rpcm) -{ - struct snd_msnd *chip = card->private_data; - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops); - - pcm->private_data = chip; - strcpy(pcm->name, "Hurricane"); - - - if (rpcm) - *rpcm = pcm; - return 0; -} -EXPORT_SYMBOL(snd_msnd_pcm); - -MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd.h b/ANDROID_3.4.5/sound/isa/msnd/msnd.h deleted file mode 100644 index a168ba33..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd.h +++ /dev/null @@ -1,308 +0,0 @@ -/********************************************************************* - * - * msnd.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_H -#define __MSND_H - -#define DEFSAMPLERATE 44100 -#define DEFSAMPLESIZE SNDRV_PCM_FORMAT_S16 -#define DEFCHANNELS 1 - -#define SRAM_BANK_SIZE 0x8000 -#define SRAM_CNTL_START 0x7F00 -#define SMA_STRUCT_START 0x7F40 - -#define DSP_BASE_ADDR 0x4000 -#define DSP_BANK_BASE 0x4000 - -#define AGND 0x01 -#define SIGNAL 0x02 - -#define EXT_DSP_BIT_DCAL 0x0001 -#define EXT_DSP_BIT_MIDI_CON 0x0002 - -#define BUFFSIZE 0x8000 -#define HOSTQ_SIZE 0x40 - -#define DAP_BUFF_SIZE 0x2400 - -#define DAPQ_STRUCT_SIZE 0x10 -#define DARQ_STRUCT_SIZE 0x10 -#define DAPQ_BUFF_SIZE (3 * 0x10) -#define DARQ_BUFF_SIZE (3 * 0x10) -#define MODQ_BUFF_SIZE 0x400 - -#define DAPQ_DATA_BUFF 0x6C00 -#define DARQ_DATA_BUFF 0x6C30 -#define MODQ_DATA_BUFF 0x6C60 -#define MIDQ_DATA_BUFF 0x7060 - -#define DAPQ_OFFSET SRAM_CNTL_START -#define DARQ_OFFSET (SRAM_CNTL_START + 0x08) -#define MODQ_OFFSET (SRAM_CNTL_START + 0x10) -#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18) -#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20) - -#define HP_ICR 0x00 -#define HP_CVR 0x01 -#define HP_ISR 0x02 -#define HP_IVR 0x03 -#define HP_NU 0x04 -#define HP_INFO 0x04 -#define HP_TXH 0x05 -#define HP_RXH 0x05 -#define HP_TXM 0x06 -#define HP_RXM 0x06 -#define HP_TXL 0x07 -#define HP_RXL 0x07 - -#define HP_ICR_DEF 0x00 -#define HP_CVR_DEF 0x12 -#define HP_ISR_DEF 0x06 -#define HP_IVR_DEF 0x0f -#define HP_NU_DEF 0x00 - -#define HP_IRQM 0x09 - -#define HPR_BLRC 0x08 -#define HPR_SPR1 0x09 -#define HPR_SPR2 0x0A -#define HPR_TCL0 0x0B -#define HPR_TCL1 0x0C -#define HPR_TCL2 0x0D -#define HPR_TCL3 0x0E -#define HPR_TCL4 0x0F - -#define HPICR_INIT 0x80 -#define HPICR_HM1 0x40 -#define HPICR_HM0 0x20 -#define HPICR_HF1 0x10 -#define HPICR_HF0 0x08 -#define HPICR_TREQ 0x02 -#define HPICR_RREQ 0x01 - -#define HPCVR_HC 0x80 - -#define HPISR_HREQ 0x80 -#define HPISR_DMA 0x40 -#define HPISR_HF3 0x10 -#define HPISR_HF2 0x08 -#define HPISR_TRDY 0x04 -#define HPISR_TXDE 0x02 -#define HPISR_RXDF 0x01 - -#define HPIO_290 0 -#define HPIO_260 1 -#define HPIO_250 2 -#define HPIO_240 3 -#define HPIO_230 4 -#define HPIO_220 5 -#define HPIO_210 6 -#define HPIO_3E0 7 - -#define HPMEM_NONE 0 -#define HPMEM_B000 1 -#define HPMEM_C800 2 -#define HPMEM_D000 3 -#define HPMEM_D400 4 -#define HPMEM_D800 5 -#define HPMEM_E000 6 -#define HPMEM_E800 7 - -#define HPIRQ_NONE 0 -#define HPIRQ_5 1 -#define HPIRQ_7 2 -#define HPIRQ_9 3 -#define HPIRQ_10 4 -#define HPIRQ_11 5 -#define HPIRQ_12 6 -#define HPIRQ_15 7 - -#define HIMT_PLAY_DONE 0x00 -#define HIMT_RECORD_DONE 0x01 -#define HIMT_MIDI_EOS 0x02 -#define HIMT_MIDI_OUT 0x03 - -#define HIMT_MIDI_IN_UCHAR 0x0E -#define HIMT_DSP 0x0F - -#define HDEX_BASE 0x92 -#define HDEX_PLAY_START (0 + HDEX_BASE) -#define HDEX_PLAY_STOP (1 + HDEX_BASE) -#define HDEX_PLAY_PAUSE (2 + HDEX_BASE) -#define HDEX_PLAY_RESUME (3 + HDEX_BASE) -#define HDEX_RECORD_START (4 + HDEX_BASE) -#define HDEX_RECORD_STOP (5 + HDEX_BASE) -#define HDEX_MIDI_IN_START (6 + HDEX_BASE) -#define HDEX_MIDI_IN_STOP (7 + HDEX_BASE) -#define HDEX_MIDI_OUT_START (8 + HDEX_BASE) -#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE) -#define HDEX_AUX_REQ (10 + HDEX_BASE) - -#define HDEXAR_CLEAR_PEAKS 1 -#define HDEXAR_IN_SET_POTS 2 -#define HDEXAR_AUX_SET_POTS 3 -#define HDEXAR_CAL_A_TO_D 4 -#define HDEXAR_RD_EXT_DSP_BITS 5 - -/* Pinnacle only HDEXAR defs */ -#define HDEXAR_SET_ANA_IN 0 -#define HDEXAR_SET_SYNTH_IN 4 -#define HDEXAR_READ_DAT_IN 5 -#define HDEXAR_MIC_SET_POTS 6 -#define HDEXAR_SET_DAT_IN 7 - -#define HDEXAR_SET_SYNTH_48 8 -#define HDEXAR_SET_SYNTH_44 9 - -#define HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF)) -#define LOWORD(l) ((u16)(u32)(l)) -#define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF)) -#define LOBYTE(w) ((u8)(w)) -#define MAKELONG(low, hi) ((long)(((u16)(low))|(((u32)((u16)(hi)))<<16))) -#define MAKEWORD(low, hi) ((u16)(((u8)(low))|(((u16)((u8)(hi)))<<8))) - -#define PCTODSP_OFFSET(w) (u16)((w)/2) -#define PCTODSP_BASED(w) (u16)(((w)/2) + DSP_BASE_ADDR) -#define DSPTOPC_BASED(w) (((w) - DSP_BASE_ADDR) * 2) - -#ifdef SLOWIO -# undef outb -# undef inb -# define outb outb_p -# define inb inb_p -#endif - -/* JobQueueStruct */ -#define JQS_wStart 0x00 -#define JQS_wSize 0x02 -#define JQS_wHead 0x04 -#define JQS_wTail 0x06 -#define JQS__size 0x08 - -/* DAQueueDataStruct */ -#define DAQDS_wStart 0x00 -#define DAQDS_wSize 0x02 -#define DAQDS_wFormat 0x04 -#define DAQDS_wSampleSize 0x06 -#define DAQDS_wChannels 0x08 -#define DAQDS_wSampleRate 0x0A -#define DAQDS_wIntMsg 0x0C -#define DAQDS_wFlags 0x0E -#define DAQDS__size 0x10 - -#include <sound/pcm.h> - -struct snd_msnd { - void __iomem *mappedbase; - int play_period_bytes; - int playLimit; - int playPeriods; - int playDMAPos; - int banksPlayed; - int captureDMAPos; - int capturePeriodBytes; - int captureLimit; - int capturePeriods; - struct snd_card *card; - void *msndmidi_mpu; - struct snd_rawmidi *rmidi; - - /* Hardware resources */ - long io; - int memid, irqid; - int irq, irq_ref; - unsigned long base; - - /* Motorola 56k DSP SMA */ - void __iomem *SMA; - void __iomem *DAPQ; - void __iomem *DARQ; - void __iomem *MODQ; - void __iomem *MIDQ; - void __iomem *DSPQ; - int dspq_data_buff, dspq_buff_size; - - /* State variables */ - enum { msndClassic, msndPinnacle } type; - fmode_t mode; - unsigned long flags; -#define F_RESETTING 0 -#define F_HAVEDIGITAL 1 -#define F_AUDIO_WRITE_INUSE 2 -#define F_WRITING 3 -#define F_WRITEBLOCK 4 -#define F_WRITEFLUSH 5 -#define F_AUDIO_READ_INUSE 6 -#define F_READING 7 -#define F_READBLOCK 8 -#define F_EXT_MIDI_INUSE 9 -#define F_HDR_MIDI_INUSE 10 -#define F_DISABLE_WRITE_NDELAY 11 - spinlock_t lock; - spinlock_t mixer_lock; - int nresets; - unsigned recsrc; -#define LEVEL_ENTRIES 32 - int left_levels[LEVEL_ENTRIES]; - int right_levels[LEVEL_ENTRIES]; - int calibrate_signal; - int play_sample_size, play_sample_rate, play_channels; - int play_ndelay; - int capture_sample_size, capture_sample_rate, capture_channels; - int capture_ndelay; - u8 bCurrentMidiPatch; - - int last_playbank, last_recbank; - struct snd_pcm_substream *playback_substream; - struct snd_pcm_substream *capture_substream; - -}; - -void snd_msnd_init_queue(void *base, int start, int size); - -int snd_msnd_send_dsp_cmd(struct snd_msnd *chip, u8 cmd); -int snd_msnd_send_word(struct snd_msnd *chip, - unsigned char high, - unsigned char mid, - unsigned char low); -int snd_msnd_upload_host(struct snd_msnd *chip, - const u8 *bin, int len); -int snd_msnd_enable_irq(struct snd_msnd *chip); -int snd_msnd_disable_irq(struct snd_msnd *chip); -void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file); -int snd_msnd_DAPQ(struct snd_msnd *chip, int start); -int snd_msnd_DARQ(struct snd_msnd *chip, int start); -int snd_msnd_pcm(struct snd_card *card, int device, struct snd_pcm **rpcm); - -int snd_msndmidi_new(struct snd_card *card, int device); -void snd_msndmidi_input_read(void *mpu); - -void snd_msndmix_setup(struct snd_msnd *chip); -int __devinit snd_msndmix_new(struct snd_card *card); -int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc); -#endif /* __MSND_H */ diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c deleted file mode 100644 index 3b23a096..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.c +++ /dev/null @@ -1,3 +0,0 @@ -/* The work is in msnd_pinnacle.c, just define MSND_CLASSIC before it. */ -#define MSND_CLASSIC -#include "msnd_pinnacle.c" diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h b/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h deleted file mode 100644 index f18d5fa5..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_classic.h +++ /dev/null @@ -1,129 +0,0 @@ -/********************************************************************* - * - * msnd_classic.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_CLASSIC_H -#define __MSND_CLASSIC_H - -#define DSP_NUMIO 0x10 - -#define HP_MEMM 0x08 - -#define HP_BITM 0x0E -#define HP_WAIT 0x0D -#define HP_DSPR 0x0A -#define HP_PROR 0x0B -#define HP_BLKS 0x0C - -#define HPPRORESET_OFF 0 -#define HPPRORESET_ON 1 - -#define HPDSPRESET_OFF 0 -#define HPDSPRESET_ON 1 - -#define HPBLKSEL_0 0 -#define HPBLKSEL_1 1 - -#define HPWAITSTATE_0 0 -#define HPWAITSTATE_1 1 - -#define HPBITMODE_16 0 -#define HPBITMODE_8 1 - -#define HIDSP_INT_PLAY_UNDER 0x00 -#define HIDSP_INT_RECORD_OVER 0x01 -#define HIDSP_INPUT_CLIPPING 0x02 -#define HIDSP_MIDI_IN_OVER 0x10 -#define HIDSP_MIDI_OVERRUN_ERR 0x13 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x0040 -#define TIME_PRO_RESET 0x0032 - -#define DAR_BUFF_SIZE 0x2000 - -#define MIDQ_BUFF_SIZE 0x200 -#define DSPQ_BUFF_SIZE 0x40 - -#define DSPQ_DATA_BUFF 0x7260 - -#define MOP_SYNTH 0x10 -#define MOP_EXTOUT 0x32 -#define MOP_EXTTHRU 0x02 -#define MOP_OUTMASK 0x01 - -#define MIP_EXTIN 0x01 -#define MIP_SYNTH 0x00 -#define MIP_INMASK 0x32 - -/* Classic SMA Common Data */ -#define SMA_wCurrPlayBytes 0x0000 -#define SMA_wCurrRecordBytes 0x0002 -#define SMA_wCurrPlayVolLeft 0x0004 -#define SMA_wCurrPlayVolRight 0x0006 -#define SMA_wCurrInVolLeft 0x0008 -#define SMA_wCurrInVolRight 0x000a -#define SMA_wUser_3 0x000c -#define SMA_wUser_4 0x000e -#define SMA_dwUser_5 0x0010 -#define SMA_dwUser_6 0x0014 -#define SMA_wUser_7 0x0018 -#define SMA_wReserved_A 0x001a -#define SMA_wReserved_B 0x001c -#define SMA_wReserved_C 0x001e -#define SMA_wReserved_D 0x0020 -#define SMA_wReserved_E 0x0022 -#define SMA_wReserved_F 0x0024 -#define SMA_wReserved_G 0x0026 -#define SMA_wReserved_H 0x0028 -#define SMA_wCurrDSPStatusFlags 0x002a -#define SMA_wCurrHostStatusFlags 0x002c -#define SMA_wCurrInputTagBits 0x002e -#define SMA_wCurrLeftPeak 0x0030 -#define SMA_wCurrRightPeak 0x0032 -#define SMA_wExtDSPbits 0x0034 -#define SMA_bExtHostbits 0x0036 -#define SMA_bBoardLevel 0x0037 -#define SMA_bInPotPosRight 0x0038 -#define SMA_bInPotPosLeft 0x0039 -#define SMA_bAuxPotPosRight 0x003a -#define SMA_bAuxPotPosLeft 0x003b -#define SMA_wCurrMastVolLeft 0x003c -#define SMA_wCurrMastVolRight 0x003e -#define SMA_bUser_12 0x0040 -#define SMA_bUser_13 0x0041 -#define SMA_wUser_14 0x0042 -#define SMA_wUser_15 0x0044 -#define SMA_wCalFreqAtoD 0x0046 -#define SMA_wUser_16 0x0048 -#define SMA_wUser_17 0x004a -#define SMA__size 0x004c - -#define INITCODEFILE "turtlebeach/msndinit.bin" -#define PERMCODEFILE "turtlebeach/msndperm.bin" -#define LONGNAME "MultiSound (Classic/Monterey/Tahiti)" - -#endif /* __MSND_CLASSIC_H */ diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c deleted file mode 100644 index ffc67fd8..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_midi.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Copyright (c) 2009 by Krzysztof Helt - * Routines for control of MPU-401 in UART mode - * - * MPU-401 supports UART mode which is not capable generate transmit - * interrupts thus output is done via polling. Also, if irq < 0, then - * input is done also via polling. Do not expect good performance. - * - * - * 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/io.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/export.h> -#include <sound/core.h> -#include <sound/rawmidi.h> - -#include "msnd.h" - -#define MSNDMIDI_MODE_BIT_INPUT 0 -#define MSNDMIDI_MODE_BIT_OUTPUT 1 -#define MSNDMIDI_MODE_BIT_INPUT_TRIGGER 2 -#define MSNDMIDI_MODE_BIT_OUTPUT_TRIGGER 3 - -struct snd_msndmidi { - struct snd_msnd *dev; - - unsigned long mode; /* MSNDMIDI_MODE_XXXX */ - - struct snd_rawmidi_substream *substream_input; - - spinlock_t input_lock; -}; - -/* - * input/output open/close - protected by open_mutex in rawmidi.c - */ -static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream) -{ - struct snd_msndmidi *mpu; - - snd_printdd("snd_msndmidi_input_open()\n"); - - mpu = substream->rmidi->private_data; - - mpu->substream_input = substream; - - snd_msnd_enable_irq(mpu->dev); - - snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_START); - set_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); - return 0; -} - -static int snd_msndmidi_input_close(struct snd_rawmidi_substream *substream) -{ - struct snd_msndmidi *mpu; - - mpu = substream->rmidi->private_data; - snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_STOP); - clear_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); - mpu->substream_input = NULL; - snd_msnd_disable_irq(mpu->dev); - return 0; -} - -static void snd_msndmidi_input_drop(struct snd_msndmidi *mpu) -{ - u16 tail; - - tail = readw(mpu->dev->MIDQ + JQS_wTail); - writew(tail, mpu->dev->MIDQ + JQS_wHead); -} - -/* - * trigger input - */ -static void snd_msndmidi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - unsigned long flags; - struct snd_msndmidi *mpu; - - snd_printdd("snd_msndmidi_input_trigger(, %i)\n", up); - - mpu = substream->rmidi->private_data; - spin_lock_irqsave(&mpu->input_lock, flags); - if (up) { - if (!test_and_set_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) - snd_msndmidi_input_drop(mpu); - } else { - clear_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode); - } - spin_unlock_irqrestore(&mpu->input_lock, flags); - if (up) - snd_msndmidi_input_read(mpu); -} - -void snd_msndmidi_input_read(void *mpuv) -{ - unsigned long flags; - struct snd_msndmidi *mpu = mpuv; - void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; - - spin_lock_irqsave(&mpu->input_lock, flags); - while (readw(mpu->dev->MIDQ + JQS_wTail) != - readw(mpu->dev->MIDQ + JQS_wHead)) { - u16 wTmp, val; - val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); - - if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) - snd_rawmidi_receive(mpu->substream_input, - (unsigned char *)&val, 1); - - wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; - if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) - writew(0, mpu->dev->MIDQ + JQS_wHead); - else - writew(wTmp, mpu->dev->MIDQ + JQS_wHead); - } - spin_unlock_irqrestore(&mpu->input_lock, flags); -} -EXPORT_SYMBOL(snd_msndmidi_input_read); - -static struct snd_rawmidi_ops snd_msndmidi_input = { - .open = snd_msndmidi_input_open, - .close = snd_msndmidi_input_close, - .trigger = snd_msndmidi_input_trigger, -}; - -static void snd_msndmidi_free(struct snd_rawmidi *rmidi) -{ - struct snd_msndmidi *mpu = rmidi->private_data; - kfree(mpu); -} - -int snd_msndmidi_new(struct snd_card *card, int device) -{ - struct snd_msnd *chip = card->private_data; - struct snd_msndmidi *mpu; - struct snd_rawmidi *rmidi; - int err; - - err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi); - if (err < 0) - return err; - mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); - if (mpu == NULL) { - snd_device_free(card, rmidi); - return -ENOMEM; - } - mpu->dev = chip; - chip->msndmidi_mpu = mpu; - rmidi->private_data = mpu; - rmidi->private_free = snd_msndmidi_free; - spin_lock_init(&mpu->input_lock); - strcpy(rmidi->name, "MSND MIDI"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_msndmidi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c deleted file mode 100644 index 29cc8e16..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.c +++ /dev/null @@ -1,1245 +0,0 @@ -/********************************************************************* - * - * Linux multisound pinnacle/fiji driver for ALSA. - * - * 2002/06/30 Karsten Wiese: - * for now this is only used to build a pinnacle / fiji driver. - * the OSS parent of this code is designed to also support - * the multisound classic via the file msnd_classic.c. - * to make it easier for some brave heart to implemt classic - * support in alsa, i left all the MSND_CLASSIC tokens in this file. - * but for now this untested & undone. - * - * - * ripped from linux kernel 2.4.18 by Karsten Wiese. - * - * the following is a copy of the 2.4.18 OSS FREE file-heading comment: - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * msnd_pinnacle.c / msnd_classic.c - * - * -- If MSND_CLASSIC is defined: - * - * -> driver for Turtle Beach Classic/Monterey/Tahiti - * - * -- Else - * - * -> driver for Turtle Beach Pinnacle/Fiji - * - * 12-3-2000 Modified IO port validation Steve Sycamore - * - * Copyright (C) 1998 Andrew Veliath - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/firmware.h> -#include <linux/isa.h> -#include <linux/isapnp.h> -#include <linux/irq.h> -#include <linux/io.h> - -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/asound.h> -#include <sound/pcm.h> -#include <sound/mpu401.h> - -#ifdef MSND_CLASSIC -# ifndef __alpha__ -# define SLOWIO -# endif -#endif -#include "msnd.h" -#ifdef MSND_CLASSIC -# include "msnd_classic.h" -# define LOGNAME "msnd_classic" -#else -# include "msnd_pinnacle.h" -# define LOGNAME "snd_msnd_pinnacle" -#endif - -static void __devinit set_default_audio_parameters(struct snd_msnd *chip) -{ - chip->play_sample_size = DEFSAMPLESIZE; - chip->play_sample_rate = DEFSAMPLERATE; - chip->play_channels = DEFCHANNELS; - chip->capture_sample_size = DEFSAMPLESIZE; - chip->capture_sample_rate = DEFSAMPLERATE; - chip->capture_channels = DEFCHANNELS; -} - -static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage) -{ - switch (HIBYTE(wMessage)) { - case HIMT_PLAY_DONE: { - if (chip->banksPlayed < 3) - snd_printdd("%08X: HIMT_PLAY_DONE: %i\n", - (unsigned)jiffies, LOBYTE(wMessage)); - - if (chip->last_playbank == LOBYTE(wMessage)) { - snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n"); - break; - } - chip->banksPlayed++; - - if (test_bit(F_WRITING, &chip->flags)) - snd_msnd_DAPQ(chip, 0); - - chip->last_playbank = LOBYTE(wMessage); - chip->playDMAPos += chip->play_period_bytes; - if (chip->playDMAPos > chip->playLimit) - chip->playDMAPos = 0; - snd_pcm_period_elapsed(chip->playback_substream); - - break; - } - case HIMT_RECORD_DONE: - if (chip->last_recbank == LOBYTE(wMessage)) - break; - chip->last_recbank = LOBYTE(wMessage); - chip->captureDMAPos += chip->capturePeriodBytes; - if (chip->captureDMAPos > (chip->captureLimit)) - chip->captureDMAPos = 0; - - if (test_bit(F_READING, &chip->flags)) - snd_msnd_DARQ(chip, chip->last_recbank); - - snd_pcm_period_elapsed(chip->capture_substream); - break; - - case HIMT_DSP: - switch (LOBYTE(wMessage)) { -#ifndef MSND_CLASSIC - case HIDSP_PLAY_UNDER: -#endif - case HIDSP_INT_PLAY_UNDER: - snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n", - chip->banksPlayed); - if (chip->banksPlayed > 2) - clear_bit(F_WRITING, &chip->flags); - break; - - case HIDSP_INT_RECORD_OVER: - snd_printd(KERN_WARNING LOGNAME ": Record overflow\n"); - clear_bit(F_READING, &chip->flags); - break; - - default: - snd_printd(KERN_WARNING LOGNAME - ": DSP message %d 0x%02x\n", - LOBYTE(wMessage), LOBYTE(wMessage)); - break; - } - break; - - case HIMT_MIDI_IN_UCHAR: - if (chip->msndmidi_mpu) - snd_msndmidi_input_read(chip->msndmidi_mpu); - break; - - default: - snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n", - HIBYTE(wMessage), HIBYTE(wMessage)); - break; - } -} - -static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) -{ - struct snd_msnd *chip = dev_id; - void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; - - /* Send ack to DSP */ - /* inb(chip->io + HP_RXL); */ - - /* Evaluate queued DSP messages */ - while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { - u16 wTmp; - - snd_msnd_eval_dsp_msg(chip, - readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); - - wTmp = readw(chip->DSPQ + JQS_wHead) + 1; - if (wTmp > readw(chip->DSPQ + JQS_wSize)) - writew(0, chip->DSPQ + JQS_wHead); - else - writew(wTmp, chip->DSPQ + JQS_wHead); - } - /* Send ack to DSP */ - inb(chip->io + HP_RXL); - return IRQ_HANDLED; -} - - -static int snd_msnd_reset_dsp(long io, unsigned char *info) -{ - int timeout = 100; - - outb(HPDSPRESET_ON, io + HP_DSPR); - msleep(1); -#ifndef MSND_CLASSIC - if (info) - *info = inb(io + HP_INFO); -#endif - outb(HPDSPRESET_OFF, io + HP_DSPR); - msleep(1); - while (timeout-- > 0) { - if (inb(io + HP_CVR) == HP_CVR_DEF) - return 0; - msleep(1); - } - snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n"); - - return -EIO; -} - -static int __devinit snd_msnd_probe(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - unsigned char info; -#ifndef MSND_CLASSIC - char *xv, *rev = NULL; - char *pin = "TB Pinnacle", *fiji = "TB Fiji"; - char *pinfiji = "TB Pinnacle/Fiji"; -#endif - - if (!request_region(chip->io, DSP_NUMIO, "probing")) { - snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n"); - return -ENODEV; - } - - if (snd_msnd_reset_dsp(chip->io, &info) < 0) { - release_region(chip->io, DSP_NUMIO); - return -ENODEV; - } - -#ifdef MSND_CLASSIC - strcpy(card->shortname, "Classic/Tahiti/Monterey"); - strcpy(card->longname, "Turtle Beach Multisound"); - printk(KERN_INFO LOGNAME ": %s, " - "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", - card->shortname, - chip->io, chip->io + DSP_NUMIO - 1, - chip->irq, - chip->base, chip->base + 0x7fff); -#else - switch (info >> 4) { - case 0xf: - xv = "<= 1.15"; - break; - case 0x1: - xv = "1.18/1.2"; - break; - case 0x2: - xv = "1.3"; - break; - case 0x3: - xv = "1.4"; - break; - default: - xv = "unknown"; - break; - } - - switch (info & 0x7) { - case 0x0: - rev = "I"; - strcpy(card->shortname, pin); - break; - case 0x1: - rev = "F"; - strcpy(card->shortname, pin); - break; - case 0x2: - rev = "G"; - strcpy(card->shortname, pin); - break; - case 0x3: - rev = "H"; - strcpy(card->shortname, pin); - break; - case 0x4: - rev = "E"; - strcpy(card->shortname, fiji); - break; - case 0x5: - rev = "C"; - strcpy(card->shortname, fiji); - break; - case 0x6: - rev = "D"; - strcpy(card->shortname, fiji); - break; - case 0x7: - rev = "A-B (Fiji) or A-E (Pinnacle)"; - strcpy(card->shortname, pinfiji); - break; - } - strcpy(card->longname, "Turtle Beach Multisound Pinnacle"); - printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, " - "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n", - card->shortname, - rev, xv, - chip->io, chip->io + DSP_NUMIO - 1, - chip->irq, - chip->base, chip->base + 0x7fff); -#endif - - release_region(chip->io, DSP_NUMIO); - return 0; -} - -static int snd_msnd_init_sma(struct snd_msnd *chip) -{ - static int initted; - u16 mastVolLeft, mastVolRight; - unsigned long flags; - -#ifdef MSND_CLASSIC - outb(chip->memid, chip->io + HP_MEMM); -#endif - outb(HPBLKSEL_0, chip->io + HP_BLKS); - /* Motorola 56k shared memory base */ - chip->SMA = chip->mappedbase + SMA_STRUCT_START; - - if (initted) { - mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft); - mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight); - } else - mastVolLeft = mastVolRight = 0; - memset_io(chip->mappedbase, 0, 0x8000); - - /* Critical section: bank 1 access */ - spin_lock_irqsave(&chip->lock, flags); - outb(HPBLKSEL_1, chip->io + HP_BLKS); - memset_io(chip->mappedbase, 0, 0x8000); - outb(HPBLKSEL_0, chip->io + HP_BLKS); - spin_unlock_irqrestore(&chip->lock, flags); - - /* Digital audio play queue */ - chip->DAPQ = chip->mappedbase + DAPQ_OFFSET; - snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE); - - /* Digital audio record queue */ - chip->DARQ = chip->mappedbase + DARQ_OFFSET; - snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); - - /* MIDI out queue */ - chip->MODQ = chip->mappedbase + MODQ_OFFSET; - snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE); - - /* MIDI in queue */ - chip->MIDQ = chip->mappedbase + MIDQ_OFFSET; - snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE); - - /* DSP -> host message queue */ - chip->DSPQ = chip->mappedbase + DSPQ_OFFSET; - snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE); - - /* Setup some DSP values */ -#ifndef MSND_CLASSIC - writew(1, chip->SMA + SMA_wCurrPlayFormat); - writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize); - writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels); - writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate); -#endif - writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD); - writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft); - writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight); -#ifndef MSND_CLASSIC - writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch); - writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate); -#endif - writew(0x303, chip->SMA + SMA_wCurrInputTagBits); - - initted = 1; - - return 0; -} - - -static int upload_dsp_code(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - const struct firmware *init_fw = NULL, *perm_fw = NULL; - int err; - - outb(HPBLKSEL_0, chip->io + HP_BLKS); - - err = request_firmware(&init_fw, INITCODEFILE, card->dev); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE); - goto cleanup1; - } - err = request_firmware(&perm_fw, PERMCODEFILE, card->dev); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE); - goto cleanup; - } - - memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size); - if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) { - printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n"); - err = -ENODEV; - goto cleanup; - } - printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n"); - err = 0; - -cleanup: - release_firmware(perm_fw); -cleanup1: - release_firmware(init_fw); - return err; -} - -#ifdef MSND_CLASSIC -static void reset_proteus(struct snd_msnd *chip) -{ - outb(HPPRORESET_ON, chip->io + HP_PROR); - msleep(TIME_PRO_RESET); - outb(HPPRORESET_OFF, chip->io + HP_PROR); - msleep(TIME_PRO_RESET_DONE); -} -#endif - -static int snd_msnd_initialize(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - int err, timeout; - -#ifdef MSND_CLASSIC - outb(HPWAITSTATE_0, chip->io + HP_WAIT); - outb(HPBITMODE_16, chip->io + HP_BITM); - - reset_proteus(chip); -#endif - err = snd_msnd_init_sma(chip); - if (err < 0) { - printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n"); - return err; - } - - err = snd_msnd_reset_dsp(chip->io, NULL); - if (err < 0) - return err; - - err = upload_dsp_code(card); - if (err < 0) { - printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n"); - return err; - } - - timeout = 200; - - while (readw(chip->mappedbase)) { - msleep(1); - if (!timeout--) { - snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n"); - return -EIO; - } - } - - snd_msndmix_setup(chip); - return 0; -} - -static int snd_msnd_dsp_full_reset(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - int rv; - - if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10) - return 0; - - set_bit(F_RESETTING, &chip->flags); - snd_msnd_dsp_halt(chip, NULL); /* Unconditionally halt */ - - rv = snd_msnd_initialize(card); - if (rv) - printk(KERN_WARNING LOGNAME ": DSP reset failed\n"); - snd_msndmix_force_recsrc(chip, 0); - clear_bit(F_RESETTING, &chip->flags); - return rv; -} - -static int snd_msnd_dev_free(struct snd_device *device) -{ - snd_printdd("snd_msnd_chip_free()\n"); - return 0; -} - -static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd) -{ - if (snd_msnd_send_dsp_cmd(chip, cmd) == 0) - return 0; - snd_msnd_dsp_full_reset(chip->card); - return snd_msnd_send_dsp_cmd(chip, cmd); -} - -static int __devinit snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate) -{ - snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate); - writew(srate, chip->SMA + SMA_wCalFreqAtoD); - if (chip->calibrate_signal == 0) - writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) - | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags); - else - writew(readw(chip->SMA + SMA_wCurrHostStatusFlags) - & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags); - if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 && - snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) { - schedule_timeout_interruptible(msecs_to_jiffies(333)); - return 0; - } - printk(KERN_WARNING LOGNAME ": ADC calibration failed\n"); - return -EIO; -} - -/* - * ALSA callback function, called when attempting to open the MIDI device. - */ -static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu) -{ - snd_msnd_enable_irq(mpu->private_data); - snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START); - return 0; -} - -static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu) -{ - snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP); - snd_msnd_disable_irq(mpu->private_data); -} - -static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; - -static int __devinit snd_msnd_attach(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_msnd_dev_free, - }; - - err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname, - chip); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq); - return err; - } - if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) { - free_irq(chip->irq, chip); - return -EBUSY; - } - - if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) { - printk(KERN_ERR LOGNAME - ": unable to grab memory region 0x%lx-0x%lx\n", - chip->base, chip->base + BUFFSIZE - 1); - release_region(chip->io, DSP_NUMIO); - free_irq(chip->irq, chip); - return -EBUSY; - } - chip->mappedbase = ioremap_nocache(chip->base, 0x8000); - if (!chip->mappedbase) { - printk(KERN_ERR LOGNAME - ": unable to map memory region 0x%lx-0x%lx\n", - chip->base, chip->base + BUFFSIZE - 1); - err = -EIO; - goto err_release_region; - } - - err = snd_msnd_dsp_full_reset(card); - if (err < 0) - goto err_release_region; - - /* Register device */ - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) - goto err_release_region; - - err = snd_msnd_pcm(card, 0, NULL); - if (err < 0) { - printk(KERN_ERR LOGNAME ": error creating new PCM device\n"); - goto err_release_region; - } - - err = snd_msndmix_new(card); - if (err < 0) { - printk(KERN_ERR LOGNAME ": error creating new Mixer device\n"); - goto err_release_region; - } - - - if (mpu_io[0] != SNDRV_AUTO_PORT) { - struct snd_mpu401 *mpu; - - err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_io[0], - MPU401_MODE_INPUT | - MPU401_MODE_OUTPUT, - mpu_irq[0], - &chip->rmidi); - if (err < 0) { - printk(KERN_ERR LOGNAME - ": error creating new Midi device\n"); - goto err_release_region; - } - mpu = chip->rmidi->private_data; - - mpu->open_input = snd_msnd_mpu401_open; - mpu->close_input = snd_msnd_mpu401_close; - mpu->private_data = chip; - } - - disable_irq(chip->irq); - snd_msnd_calibrate_adc(chip, chip->play_sample_rate); - snd_msndmix_force_recsrc(chip, 0); - - err = snd_card_register(card); - if (err < 0) - goto err_release_region; - - return 0; - -err_release_region: - if (chip->mappedbase) - iounmap(chip->mappedbase); - release_mem_region(chip->base, BUFFSIZE); - release_region(chip->io, DSP_NUMIO); - free_irq(chip->irq, chip); - return err; -} - - -static void __devexit snd_msnd_unload(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - - iounmap(chip->mappedbase); - release_mem_region(chip->base, BUFFSIZE); - release_region(chip->io, DSP_NUMIO); - free_irq(chip->irq, chip); - snd_card_free(card); -} - -#ifndef MSND_CLASSIC - -/* Pinnacle/Fiji Logical Device Configuration */ - -static int __devinit snd_msnd_write_cfg(int cfg, int reg, int value) -{ - outb(reg, cfg); - outb(value, cfg + 1); - if (value != inb(cfg + 1)) { - printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n"); - return -EIO; - } - return 0; -} - -static int __devinit snd_msnd_write_cfg_io0(int cfg, int num, u16 io) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io))) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_io1(int cfg, int num, u16 io) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io))) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_irq(int cfg, int num, u16 irq) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_mem(int cfg, int num, int mem) -{ - u16 wmem; - - mem >>= 8; - wmem = (u16)(mem & 0xfff); - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem))) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem))) - return -EIO; - if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL, - MEMTYPE_HIADDR | MEMTYPE_16BIT)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_activate_logical(int cfg, int num) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_write_cfg_logical(int cfg, int num, u16 io0, - u16 io1, u16 irq, int mem) -{ - if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num)) - return -EIO; - if (snd_msnd_write_cfg_io0(cfg, num, io0)) - return -EIO; - if (snd_msnd_write_cfg_io1(cfg, num, io1)) - return -EIO; - if (snd_msnd_write_cfg_irq(cfg, num, irq)) - return -EIO; - if (snd_msnd_write_cfg_mem(cfg, num, mem)) - return -EIO; - if (snd_msnd_activate_logical(cfg, num)) - return -EIO; - return 0; -} - -static int __devinit snd_msnd_pinnacle_cfg_reset(int cfg) -{ - int i; - - /* Reset devices if told to */ - printk(KERN_INFO LOGNAME ": Resetting all devices\n"); - for (i = 0; i < 4; ++i) - if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0)) - return -EIO; - - return 0; -} -#endif - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard."); -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard."); - -static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - -#ifndef MSND_CLASSIC -static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - -/* Extra Peripheral Configuration (Default: Disable) */ -static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; - -static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -/* If we have the digital daugherboard... */ -static int digital[SNDRV_CARDS]; - -/* Extra Peripheral Configuration */ -static int reset[SNDRV_CARDS]; -#endif - -static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; - -static int calibrate_signal; - -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard."); -#define has_isapnp(x) isapnp[x] -#else -#define has_isapnp(x) 0 -#endif - -MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); -MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(INITCODEFILE); -MODULE_FIRMWARE(PERMCODEFILE); - -module_param_array(io, long, NULL, S_IRUGO); -MODULE_PARM_DESC(io, "IO port #"); -module_param_array(irq, int, NULL, S_IRUGO); -module_param_array(mem, long, NULL, S_IRUGO); -module_param_array(write_ndelay, int, NULL, S_IRUGO); -module_param(calibrate_signal, int, S_IRUGO); -#ifndef MSND_CLASSIC -module_param_array(digital, int, NULL, S_IRUGO); -module_param_array(cfg, long, NULL, S_IRUGO); -module_param_array(reset, int, 0, S_IRUGO); -module_param_array(mpu_io, long, NULL, S_IRUGO); -module_param_array(mpu_irq, int, NULL, S_IRUGO); -module_param_array(ide_io0, long, NULL, S_IRUGO); -module_param_array(ide_io1, long, NULL, S_IRUGO); -module_param_array(ide_irq, int, NULL, S_IRUGO); -module_param_array(joystick_io, long, NULL, S_IRUGO); -#endif - - -static int __devinit snd_msnd_isa_match(struct device *pdev, unsigned int i) -{ - if (io[i] == SNDRV_AUTO_PORT) - return 0; - - if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) { - printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n"); - return 0; - } - -#ifdef MSND_CLASSIC - if (!(io[i] == 0x290 || - io[i] == 0x260 || - io[i] == 0x250 || - io[i] == 0x240 || - io[i] == 0x230 || - io[i] == 0x220 || - io[i] == 0x210 || - io[i] == 0x3e0)) { - printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set " - " to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, " - "or 0x3E0\n"); - return 0; - } -#else - if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) { - printk(KERN_ERR LOGNAME - ": \"io\" - DSP I/O base must within the range 0x100 " - "to 0x3E0 and must be evenly divisible by 0x10\n"); - return 0; - } -#endif /* MSND_CLASSIC */ - - if (!(irq[i] == 5 || - irq[i] == 7 || - irq[i] == 9 || - irq[i] == 10 || - irq[i] == 11 || - irq[i] == 12)) { - printk(KERN_ERR LOGNAME - ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n"); - return 0; - } - - if (!(mem[i] == 0xb0000 || - mem[i] == 0xc8000 || - mem[i] == 0xd0000 || - mem[i] == 0xd8000 || - mem[i] == 0xe0000 || - mem[i] == 0xe8000)) { - printk(KERN_ERR LOGNAME ": \"mem\" - must be set to " - "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or " - "0xe8000\n"); - return 0; - } - -#ifndef MSND_CLASSIC - if (cfg[i] == SNDRV_AUTO_PORT) { - printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); - } else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) { - printk(KERN_INFO LOGNAME - ": Config port must be 0x250, 0x260 or 0x270 " - "(or unspecified for PnP mode)\n"); - return 0; - } -#endif /* MSND_CLASSIC */ - - return 1; -} - -static int __devinit snd_msnd_isa_probe(struct device *pdev, unsigned int idx) -{ - int err; - struct snd_card *card; - struct snd_msnd *chip; - - if (has_isapnp(idx) -#ifndef MSND_CLASSIC - || cfg[idx] == SNDRV_AUTO_PORT -#endif - ) { - printk(KERN_INFO LOGNAME ": Assuming PnP mode\n"); - return -ENODEV; - } - - err = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct snd_msnd), &card); - if (err < 0) - return err; - - snd_card_set_dev(card, pdev); - chip = card->private_data; - chip->card = card; - -#ifdef MSND_CLASSIC - switch (irq[idx]) { - case 5: - chip->irqid = HPIRQ_5; break; - case 7: - chip->irqid = HPIRQ_7; break; - case 9: - chip->irqid = HPIRQ_9; break; - case 10: - chip->irqid = HPIRQ_10; break; - case 11: - chip->irqid = HPIRQ_11; break; - case 12: - chip->irqid = HPIRQ_12; break; - } - - switch (mem[idx]) { - case 0xb0000: - chip->memid = HPMEM_B000; break; - case 0xc8000: - chip->memid = HPMEM_C800; break; - case 0xd0000: - chip->memid = HPMEM_D000; break; - case 0xd8000: - chip->memid = HPMEM_D800; break; - case 0xe0000: - chip->memid = HPMEM_E000; break; - case 0xe8000: - chip->memid = HPMEM_E800; break; - } -#else - printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n", - cfg[idx]); - - if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) { - printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n", - cfg[idx]); - snd_card_free(card); - return -EIO; - } - if (reset[idx]) - if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) { - err = -EIO; - goto cfg_error; - } - - /* DSP */ - err = snd_msnd_write_cfg_logical(cfg[idx], 0, - io[idx], 0, - irq[idx], mem[idx]); - - if (err) - goto cfg_error; - - /* The following are Pinnacle specific */ - - /* MPU */ - if (mpu_io[idx] != SNDRV_AUTO_PORT - && mpu_irq[idx] != SNDRV_AUTO_IRQ) { - printk(KERN_INFO LOGNAME - ": Configuring MPU to I/O 0x%lx IRQ %d\n", - mpu_io[idx], mpu_irq[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 1, - mpu_io[idx], 0, - mpu_irq[idx], 0); - - if (err) - goto cfg_error; - } - - /* IDE */ - if (ide_io0[idx] != SNDRV_AUTO_PORT - && ide_io1[idx] != SNDRV_AUTO_PORT - && ide_irq[idx] != SNDRV_AUTO_IRQ) { - printk(KERN_INFO LOGNAME - ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n", - ide_io0[idx], ide_io1[idx], ide_irq[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 2, - ide_io0[idx], ide_io1[idx], - ide_irq[idx], 0); - - if (err) - goto cfg_error; - } - - /* Joystick */ - if (joystick_io[idx] != SNDRV_AUTO_PORT) { - printk(KERN_INFO LOGNAME - ": Configuring joystick to I/O 0x%lx\n", - joystick_io[idx]); - err = snd_msnd_write_cfg_logical(cfg[idx], 3, - joystick_io[idx], 0, - 0, 0); - - if (err) - goto cfg_error; - } - release_region(cfg[idx], 2); - -#endif /* MSND_CLASSIC */ - - set_default_audio_parameters(chip); -#ifdef MSND_CLASSIC - chip->type = msndClassic; -#else - chip->type = msndPinnacle; -#endif - chip->io = io[idx]; - chip->irq = irq[idx]; - chip->base = mem[idx]; - - chip->calibrate_signal = calibrate_signal ? 1 : 0; - chip->recsrc = 0; - chip->dspq_data_buff = DSPQ_DATA_BUFF; - chip->dspq_buff_size = DSPQ_BUFF_SIZE; - if (write_ndelay[idx]) - clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); - else - set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); -#ifndef MSND_CLASSIC - if (digital[idx]) - set_bit(F_HAVEDIGITAL, &chip->flags); -#endif - spin_lock_init(&chip->lock); - err = snd_msnd_probe(card); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Probe failed\n"); - snd_card_free(card); - return err; - } - - err = snd_msnd_attach(card); - if (err < 0) { - printk(KERN_ERR LOGNAME ": Attach failed\n"); - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - - return 0; - -#ifndef MSND_CLASSIC -cfg_error: - release_region(cfg[idx], 2); - snd_card_free(card); - return err; -#endif -} - -static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev) -{ - snd_msnd_unload(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#define DEV_NAME "msnd-pinnacle" - -static struct isa_driver snd_msnd_driver = { - .match = snd_msnd_isa_match, - .probe = snd_msnd_isa_probe, - .remove = __devexit_p(snd_msnd_isa_remove), - /* FIXME: suspend, resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP -static int __devinit snd_msnd_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int idx; - struct pnp_dev *pnp_dev; - struct pnp_dev *mpu_dev; - struct snd_card *card; - struct snd_msnd *chip; - int ret; - - for ( ; idx < SNDRV_CARDS; idx++) { - if (has_isapnp(idx)) - break; - } - if (idx >= SNDRV_CARDS) - return -ENODEV; - - /* - * Check that we still have room for another sound card ... - */ - pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); - if (!pnp_dev) - return -ENODEV; - - mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL); - if (!mpu_dev) - return -ENODEV; - - if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) { - printk(KERN_INFO "msnd_pinnacle: device is inactive\n"); - return -EBUSY; - } - - if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) { - printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n"); - return -EBUSY; - } - - /* - * Create a new ALSA sound card entry, in anticipation - * of detecting our hardware ... - */ - ret = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct snd_msnd), &card); - if (ret < 0) - return ret; - - chip = card->private_data; - chip->card = card; - snd_card_set_dev(card, &pcard->card->dev); - - /* - * Read the correct parameters off the ISA PnP bus ... - */ - io[idx] = pnp_port_start(pnp_dev, 0); - irq[idx] = pnp_irq(pnp_dev, 0); - mem[idx] = pnp_mem_start(pnp_dev, 0); - mpu_io[idx] = pnp_port_start(mpu_dev, 0); - mpu_irq[idx] = pnp_irq(mpu_dev, 0); - - set_default_audio_parameters(chip); -#ifdef MSND_CLASSIC - chip->type = msndClassic; -#else - chip->type = msndPinnacle; -#endif - chip->io = io[idx]; - chip->irq = irq[idx]; - chip->base = mem[idx]; - - chip->calibrate_signal = calibrate_signal ? 1 : 0; - chip->recsrc = 0; - chip->dspq_data_buff = DSPQ_DATA_BUFF; - chip->dspq_buff_size = DSPQ_BUFF_SIZE; - if (write_ndelay[idx]) - clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); - else - set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags); -#ifndef MSND_CLASSIC - if (digital[idx]) - set_bit(F_HAVEDIGITAL, &chip->flags); -#endif - spin_lock_init(&chip->lock); - ret = snd_msnd_probe(card); - if (ret < 0) { - printk(KERN_ERR LOGNAME ": Probe failed\n"); - goto _release_card; - } - - ret = snd_msnd_attach(card); - if (ret < 0) { - printk(KERN_ERR LOGNAME ": Attach failed\n"); - goto _release_card; - } - - pnp_set_card_drvdata(pcard, card); - ++idx; - return 0; - -_release_card: - snd_card_free(card); - return ret; -} - -static void __devexit snd_msnd_pnp_remove(struct pnp_card_link *pcard) -{ - snd_msnd_unload(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id msnd_pnpids[] = { - /* Pinnacle PnP */ - { .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids); - -static struct pnp_card_driver msnd_pnpc_driver = { - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - .name = "msnd_pinnacle", - .id_table = msnd_pnpids, - .probe = snd_msnd_pnp_detect, - .remove = __devexit_p(snd_msnd_pnp_remove), -}; -#endif /* CONFIG_PNP */ - -static int __init snd_msnd_init(void) -{ - int err; - - err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&msnd_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit snd_msnd_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&msnd_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_msnd_driver); -} - -module_init(snd_msnd_init); -module_exit(snd_msnd_exit); - diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h b/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h deleted file mode 100644 index 48318d1e..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle.h +++ /dev/null @@ -1,181 +0,0 @@ -/********************************************************************* - * - * msnd_pinnacle.h - * - * Turtle Beach MultiSound Sound Card Driver for Linux - * - * Some parts of this header file were derived from the Turtle Beach - * MultiSound Driver Development Kit. - * - * Copyright (C) 1998 Andrew Veliath - * Copyright (C) 1993 Turtle Beach Systems, Inc. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ********************************************************************/ -#ifndef __MSND_PINNACLE_H -#define __MSND_PINNACLE_H - -#define DSP_NUMIO 0x08 - -#define IREG_LOGDEVICE 0x07 -#define IREG_ACTIVATE 0x30 -#define LD_ACTIVATE 0x01 -#define LD_DISACTIVATE 0x00 -#define IREG_EECONTROL 0x3F -#define IREG_MEMBASEHI 0x40 -#define IREG_MEMBASELO 0x41 -#define IREG_MEMCONTROL 0x42 -#define IREG_MEMRANGEHI 0x43 -#define IREG_MEMRANGELO 0x44 -#define MEMTYPE_8BIT 0x00 -#define MEMTYPE_16BIT 0x02 -#define MEMTYPE_RANGE 0x00 -#define MEMTYPE_HIADDR 0x01 -#define IREG_IO0_BASEHI 0x60 -#define IREG_IO0_BASELO 0x61 -#define IREG_IO1_BASEHI 0x62 -#define IREG_IO1_BASELO 0x63 -#define IREG_IRQ_NUMBER 0x70 -#define IREG_IRQ_TYPE 0x71 -#define IRQTYPE_HIGH 0x02 -#define IRQTYPE_LOW 0x00 -#define IRQTYPE_LEVEL 0x01 -#define IRQTYPE_EDGE 0x00 - -#define HP_DSPR 0x04 -#define HP_BLKS 0x04 - -#define HPDSPRESET_OFF 2 -#define HPDSPRESET_ON 0 - -#define HPBLKSEL_0 2 -#define HPBLKSEL_1 3 - -#define HIMT_DAT_OFF 0x03 - -#define HIDSP_PLAY_UNDER 0x00 -#define HIDSP_INT_PLAY_UNDER 0x01 -#define HIDSP_SSI_TX_UNDER 0x02 -#define HIDSP_RECQ_OVERFLOW 0x08 -#define HIDSP_INT_RECORD_OVER 0x09 -#define HIDSP_SSI_RX_OVERFLOW 0x0a - -#define HIDSP_MIDI_IN_OVER 0x10 - -#define HIDSP_MIDI_FRAME_ERR 0x11 -#define HIDSP_MIDI_PARITY_ERR 0x12 -#define HIDSP_MIDI_OVERRUN_ERR 0x13 - -#define HIDSP_INPUT_CLIPPING 0x20 -#define HIDSP_MIX_CLIPPING 0x30 -#define HIDSP_DAT_IN_OFF 0x21 - -#define TIME_PRO_RESET_DONE 0x028A -#define TIME_PRO_SYSEX 0x001E -#define TIME_PRO_RESET 0x0032 - -#define DAR_BUFF_SIZE 0x1000 - -#define MIDQ_BUFF_SIZE 0x800 -#define DSPQ_BUFF_SIZE 0x5A0 - -#define DSPQ_DATA_BUFF 0x7860 - -#define MOP_WAVEHDR 0 -#define MOP_EXTOUT 1 -#define MOP_HWINIT 0xfe -#define MOP_NONE 0xff -#define MOP_MAX 1 - -#define MIP_EXTIN 0 -#define MIP_WAVEHDR 1 -#define MIP_HWINIT 0xfe -#define MIP_MAX 1 - -/* Pinnacle/Fiji SMA Common Data */ -#define SMA_wCurrPlayBytes 0x0000 -#define SMA_wCurrRecordBytes 0x0002 -#define SMA_wCurrPlayVolLeft 0x0004 -#define SMA_wCurrPlayVolRight 0x0006 -#define SMA_wCurrInVolLeft 0x0008 -#define SMA_wCurrInVolRight 0x000a -#define SMA_wCurrMHdrVolLeft 0x000c -#define SMA_wCurrMHdrVolRight 0x000e -#define SMA_dwCurrPlayPitch 0x0010 -#define SMA_dwCurrPlayRate 0x0014 -#define SMA_wCurrMIDIIOPatch 0x0018 -#define SMA_wCurrPlayFormat 0x001a -#define SMA_wCurrPlaySampleSize 0x001c -#define SMA_wCurrPlayChannels 0x001e -#define SMA_wCurrPlaySampleRate 0x0020 -#define SMA_wCurrRecordFormat 0x0022 -#define SMA_wCurrRecordSampleSize 0x0024 -#define SMA_wCurrRecordChannels 0x0026 -#define SMA_wCurrRecordSampleRate 0x0028 -#define SMA_wCurrDSPStatusFlags 0x002a -#define SMA_wCurrHostStatusFlags 0x002c -#define SMA_wCurrInputTagBits 0x002e -#define SMA_wCurrLeftPeak 0x0030 -#define SMA_wCurrRightPeak 0x0032 -#define SMA_bMicPotPosLeft 0x0034 -#define SMA_bMicPotPosRight 0x0035 -#define SMA_bMicPotMaxLeft 0x0036 -#define SMA_bMicPotMaxRight 0x0037 -#define SMA_bInPotPosLeft 0x0038 -#define SMA_bInPotPosRight 0x0039 -#define SMA_bAuxPotPosLeft 0x003a -#define SMA_bAuxPotPosRight 0x003b -#define SMA_bInPotMaxLeft 0x003c -#define SMA_bInPotMaxRight 0x003d -#define SMA_bAuxPotMaxLeft 0x003e -#define SMA_bAuxPotMaxRight 0x003f -#define SMA_bInPotMaxMethod 0x0040 -#define SMA_bAuxPotMaxMethod 0x0041 -#define SMA_wCurrMastVolLeft 0x0042 -#define SMA_wCurrMastVolRight 0x0044 -#define SMA_wCalFreqAtoD 0x0046 -#define SMA_wCurrAuxVolLeft 0x0048 -#define SMA_wCurrAuxVolRight 0x004a -#define SMA_wCurrPlay1VolLeft 0x004c -#define SMA_wCurrPlay1VolRight 0x004e -#define SMA_wCurrPlay2VolLeft 0x0050 -#define SMA_wCurrPlay2VolRight 0x0052 -#define SMA_wCurrPlay3VolLeft 0x0054 -#define SMA_wCurrPlay3VolRight 0x0056 -#define SMA_wCurrPlay4VolLeft 0x0058 -#define SMA_wCurrPlay4VolRight 0x005a -#define SMA_wCurrPlay1PeakLeft 0x005c -#define SMA_wCurrPlay1PeakRight 0x005e -#define SMA_wCurrPlay2PeakLeft 0x0060 -#define SMA_wCurrPlay2PeakRight 0x0062 -#define SMA_wCurrPlay3PeakLeft 0x0064 -#define SMA_wCurrPlay3PeakRight 0x0066 -#define SMA_wCurrPlay4PeakLeft 0x0068 -#define SMA_wCurrPlay4PeakRight 0x006a -#define SMA_wCurrPlayPeakLeft 0x006c -#define SMA_wCurrPlayPeakRight 0x006e -#define SMA_wCurrDATSR 0x0070 -#define SMA_wCurrDATRXCHNL 0x0072 -#define SMA_wCurrDATTXCHNL 0x0074 -#define SMA_wCurrDATRXRate 0x0076 -#define SMA_dwDSPPlayCount 0x0078 -#define SMA__size 0x007c - -#define INITCODEFILE "turtlebeach/pndspini.bin" -#define PERMCODEFILE "turtlebeach/pndsperm.bin" -#define LONGNAME "MultiSound (Pinnacle/Fiji)" - -#endif /* __MSND_PINNACLE_H */ diff --git a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c b/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c deleted file mode 100644 index 1de59d44..00000000 --- a/ANDROID_3.4.5/sound/isa/msnd/msnd_pinnacle_mixer.c +++ /dev/null @@ -1,344 +0,0 @@ -/*************************************************************************** - msnd_pinnacle_mixer.c - description - ------------------- - begin : Fre Jun 7 2002 - copyright : (C) 2002 by karsten wiese - email : annabellesgarden@yahoo.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. * - * * - ***************************************************************************/ - -#include <linux/io.h> -#include <linux/export.h> - -#include <sound/core.h> -#include <sound/control.h> -#include "msnd.h" -#include "msnd_pinnacle.h" - - -#define MSND_MIXER_VOLUME 0 -#define MSND_MIXER_PCM 1 -#define MSND_MIXER_AUX 2 /* Input source 1 (aux1) */ -#define MSND_MIXER_IMIX 3 /* Recording monitor */ -#define MSND_MIXER_SYNTH 4 -#define MSND_MIXER_SPEAKER 5 -#define MSND_MIXER_LINE 6 -#define MSND_MIXER_MIC 7 -#define MSND_MIXER_RECLEV 11 /* Recording level */ -#define MSND_MIXER_IGAIN 12 /* Input gain */ -#define MSND_MIXER_OGAIN 13 /* Output gain */ -#define MSND_MIXER_DIGITAL 17 /* Digital (input) 1 */ - -/* Device mask bits */ - -#define MSND_MASK_VOLUME (1 << MSND_MIXER_VOLUME) -#define MSND_MASK_SYNTH (1 << MSND_MIXER_SYNTH) -#define MSND_MASK_PCM (1 << MSND_MIXER_PCM) -#define MSND_MASK_SPEAKER (1 << MSND_MIXER_SPEAKER) -#define MSND_MASK_LINE (1 << MSND_MIXER_LINE) -#define MSND_MASK_MIC (1 << MSND_MIXER_MIC) -#define MSND_MASK_IMIX (1 << MSND_MIXER_IMIX) -#define MSND_MASK_RECLEV (1 << MSND_MIXER_RECLEV) -#define MSND_MASK_IGAIN (1 << MSND_MIXER_IGAIN) -#define MSND_MASK_OGAIN (1 << MSND_MIXER_OGAIN) -#define MSND_MASK_AUX (1 << MSND_MIXER_AUX) -#define MSND_MASK_DIGITAL (1 << MSND_MIXER_DIGITAL) - -static int snd_msndmix_info_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { - "Analog", "MASS", "SPDIF", - }; - struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); - unsigned items = test_bit(F_HAVEDIGITAL, &chip->flags) ? 3 : 2; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = items; - if (uinfo->value.enumerated.item >= items) - uinfo->value.enumerated.item = items - 1; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_msndmix_get_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *chip = snd_kcontrol_chip(kcontrol); - /* MSND_MASK_IMIX is the default */ - ucontrol->value.enumerated.item[0] = 0; - - if (chip->recsrc & MSND_MASK_SYNTH) { - ucontrol->value.enumerated.item[0] = 1; - } else if ((chip->recsrc & MSND_MASK_DIGITAL) && - test_bit(F_HAVEDIGITAL, &chip->flags)) { - ucontrol->value.enumerated.item[0] = 2; - } - - - return 0; -} - -static int snd_msndmix_set_mux(struct snd_msnd *chip, int val) -{ - unsigned newrecsrc; - int change; - unsigned char msndbyte; - - switch (val) { - case 0: - newrecsrc = MSND_MASK_IMIX; - msndbyte = HDEXAR_SET_ANA_IN; - break; - case 1: - newrecsrc = MSND_MASK_SYNTH; - msndbyte = HDEXAR_SET_SYNTH_IN; - break; - case 2: - newrecsrc = MSND_MASK_DIGITAL; - msndbyte = HDEXAR_SET_DAT_IN; - break; - default: - return -EINVAL; - } - change = newrecsrc != chip->recsrc; - if (change) { - change = 0; - if (!snd_msnd_send_word(chip, 0, 0, msndbyte)) - if (!snd_msnd_send_dsp_cmd(chip, HDEX_AUX_REQ)) { - chip->recsrc = newrecsrc; - change = 1; - } - } - return change; -} - -static int snd_msndmix_put_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); - return snd_msndmix_set_mux(msnd, ucontrol->value.enumerated.item[0]); -} - - -static int snd_msndmix_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 = 100; - return 0; -} - -static int snd_msndmix_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); - int addr = kcontrol->private_value; - unsigned long flags; - - spin_lock_irqsave(&msnd->mixer_lock, flags); - ucontrol->value.integer.value[0] = msnd->left_levels[addr] * 100; - ucontrol->value.integer.value[0] /= 0xFFFF; - ucontrol->value.integer.value[1] = msnd->right_levels[addr] * 100; - ucontrol->value.integer.value[1] /= 0xFFFF; - spin_unlock_irqrestore(&msnd->mixer_lock, flags); - return 0; -} - -#define update_volm(a, b) \ - do { \ - writew((dev->left_levels[a] >> 1) * \ - readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ - dev->SMA + SMA_##b##Left); \ - writew((dev->right_levels[a] >> 1) * \ - readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ - dev->SMA + SMA_##b##Right); \ - } while (0); - -#define update_potm(d, s, ar) \ - do { \ - writeb((dev->left_levels[d] >> 8) * \ - readw(dev->SMA + SMA_wCurrMastVolLeft) / 0xffff, \ - dev->SMA + SMA_##s##Left); \ - writeb((dev->right_levels[d] >> 8) * \ - readw(dev->SMA + SMA_wCurrMastVolRight) / 0xffff, \ - dev->SMA + SMA_##s##Right); \ - if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ - } while (0); - -#define update_pot(d, s, ar) \ - do { \ - writeb(dev->left_levels[d] >> 8, \ - dev->SMA + SMA_##s##Left); \ - writeb(dev->right_levels[d] >> 8, \ - dev->SMA + SMA_##s##Right); \ - if (snd_msnd_send_word(dev, 0, 0, ar) == 0) \ - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); \ - } while (0); - - -static int snd_msndmix_set(struct snd_msnd *dev, int d, int left, int right) -{ - int bLeft, bRight; - int wLeft, wRight; - int updatemaster = 0; - - if (d >= LEVEL_ENTRIES) - return -EINVAL; - - bLeft = left * 0xff / 100; - wLeft = left * 0xffff / 100; - - bRight = right * 0xff / 100; - wRight = right * 0xffff / 100; - - dev->left_levels[d] = wLeft; - dev->right_levels[d] = wRight; - - switch (d) { - /* master volume unscaled controls */ - case MSND_MIXER_LINE: /* line pot control */ - /* scaled by IMIX in digital mix */ - writeb(bLeft, dev->SMA + SMA_bInPotPosLeft); - writeb(bRight, dev->SMA + SMA_bInPotPosRight); - if (snd_msnd_send_word(dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); - break; - case MSND_MIXER_MIC: /* mic pot control */ - if (dev->type == msndClassic) - return -EINVAL; - /* scaled by IMIX in digital mix */ - writeb(bLeft, dev->SMA + SMA_bMicPotPosLeft); - writeb(bRight, dev->SMA + SMA_bMicPotPosRight); - if (snd_msnd_send_word(dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) - snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); - break; - case MSND_MIXER_VOLUME: /* master volume */ - writew(wLeft, dev->SMA + SMA_wCurrMastVolLeft); - writew(wRight, dev->SMA + SMA_wCurrMastVolRight); - /* fall through */ - - case MSND_MIXER_AUX: /* aux pot control */ - /* scaled by master volume */ - /* fall through */ - - /* digital controls */ - case MSND_MIXER_SYNTH: /* synth vol (dsp mix) */ - case MSND_MIXER_PCM: /* pcm vol (dsp mix) */ - case MSND_MIXER_IMIX: /* input monitor (dsp mix) */ - /* scaled by master volume */ - updatemaster = 1; - break; - - default: - return -EINVAL; - } - - if (updatemaster) { - /* update master volume scaled controls */ - update_volm(MSND_MIXER_PCM, wCurrPlayVol); - update_volm(MSND_MIXER_IMIX, wCurrInVol); - if (dev->type == msndPinnacle) - update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); - update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); - } - - return 0; -} - -static int snd_msndmix_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_msnd *msnd = snd_kcontrol_chip(kcontrol); - int change, addr = kcontrol->private_value; - int left, right; - unsigned long flags; - - left = ucontrol->value.integer.value[0] % 101; - right = ucontrol->value.integer.value[1] % 101; - spin_lock_irqsave(&msnd->mixer_lock, flags); - change = msnd->left_levels[addr] != left - || msnd->right_levels[addr] != right; - snd_msndmix_set(msnd, addr, left, right); - spin_unlock_irqrestore(&msnd->mixer_lock, flags); - return change; -} - - -#define DUMMY_VOLUME(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_msndmix_volume_info, \ - .get = snd_msndmix_volume_get, .put = snd_msndmix_volume_put, \ - .private_value = addr } - - -static struct snd_kcontrol_new snd_msnd_controls[] = { -DUMMY_VOLUME("Master Volume", 0, MSND_MIXER_VOLUME), -DUMMY_VOLUME("PCM Volume", 0, MSND_MIXER_PCM), -DUMMY_VOLUME("Aux Volume", 0, MSND_MIXER_AUX), -DUMMY_VOLUME("Line Volume", 0, MSND_MIXER_LINE), -DUMMY_VOLUME("Mic Volume", 0, MSND_MIXER_MIC), -DUMMY_VOLUME("Monitor", 0, MSND_MIXER_IMIX), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_msndmix_info_mux, - .get = snd_msndmix_get_mux, - .put = snd_msndmix_put_mux, -} -}; - - -int __devinit snd_msndmix_new(struct snd_card *card) -{ - struct snd_msnd *chip = card->private_data; - unsigned int idx; - int err; - - if (snd_BUG_ON(!chip)) - return -EINVAL; - spin_lock_init(&chip->mixer_lock); - strcpy(card->mixername, "MSND Pinnacle Mixer"); - - for (idx = 0; idx < ARRAY_SIZE(snd_msnd_controls); idx++) - err = snd_ctl_add(card, - snd_ctl_new1(snd_msnd_controls + idx, chip)); - if (err < 0) - return err; - - return 0; -} -EXPORT_SYMBOL(snd_msndmix_new); - -void snd_msndmix_setup(struct snd_msnd *dev) -{ - update_pot(MSND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS); - update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); - update_volm(MSND_MIXER_PCM, wCurrPlayVol); - update_volm(MSND_MIXER_IMIX, wCurrInVol); - if (dev->type == msndPinnacle) { - update_pot(MSND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS); - update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); - } -} -EXPORT_SYMBOL(snd_msndmix_setup); - -int snd_msndmix_force_recsrc(struct snd_msnd *dev, int recsrc) -{ - dev->recsrc = -1; - return snd_msndmix_set_mux(dev, recsrc); -} -EXPORT_SYMBOL(snd_msndmix_force_recsrc); diff --git a/ANDROID_3.4.5/sound/isa/opl3sa2.c b/ANDROID_3.4.5/sound/isa/opl3sa2.c deleted file mode 100644 index f6cc0b91..00000000 --- a/ANDROID_3.4.5/sound/isa/opl3sa2.c +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Driver for Yamaha OPL3-SA[2,3] soundcards - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/interrupt.h> -#include <linux/pm.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#include <sound/initval.h> -#include <sound/tlv.h> - -#include <asm/io.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Yamaha OPL3SA2+"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S}," - "{Genius,Sound Maker 3DX}," - "{Yamaha,OPL3SA3}," - "{Intel,AL440LX sound}," - "{NeoMagic,MagicWave 3DX}}"); - -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_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0xf86,0x370,0x100 */ -static long sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x530,0xe80,0xf40,0x604 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x388 */ -static long midi_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x330,0x300 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ -static int opl3sa3_ymode[SNDRV_CARDS]; /* 0,1,2,3 */ /*SL Added*/ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for OPL3-SA soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable OPL3-SA soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for OPL3-SA driver."); -module_param_array(sb_port, long, NULL, 0444); -MODULE_PARM_DESC(sb_port, "SB port # for OPL3-SA driver."); -module_param_array(wss_port, long, NULL, 0444); -MODULE_PARM_DESC(wss_port, "WSS port # for OPL3-SA driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for OPL3-SA driver."); -module_param_array(midi_port, long, NULL, 0444); -MODULE_PARM_DESC(midi_port, "MIDI port # for OPL3-SA driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for OPL3-SA driver."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for OPL3-SA driver."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver."); -module_param_array(opl3sa3_ymode, int, NULL, 0444); -MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -static int pnpc_registered; -#endif - -/* control ports */ -#define OPL3SA2_PM_CTRL 0x01 -#define OPL3SA2_SYS_CTRL 0x02 -#define OPL3SA2_IRQ_CONFIG 0x03 -#define OPL3SA2_IRQ_STATUS 0x04 -#define OPL3SA2_DMA_CONFIG 0x06 -#define OPL3SA2_MASTER_LEFT 0x07 -#define OPL3SA2_MASTER_RIGHT 0x08 -#define OPL3SA2_MIC 0x09 -#define OPL3SA2_MISC 0x0A - -/* opl3sa3 only */ -#define OPL3SA3_DGTL_DOWN 0x12 -#define OPL3SA3_ANLG_DOWN 0x13 -#define OPL3SA3_WIDE 0x14 -#define OPL3SA3_BASS 0x15 -#define OPL3SA3_TREBLE 0x16 - -/* power management bits */ -#define OPL3SA2_PM_ADOWN 0x20 -#define OPL3SA2_PM_PSV 0x04 -#define OPL3SA2_PM_PDN 0x02 -#define OPL3SA2_PM_PDX 0x01 - -#define OPL3SA2_PM_D0 0x00 -#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX) - -struct snd_opl3sa2 { - int version; /* 2 or 3 */ - unsigned long port; /* control port */ - struct resource *res_port; /* control port resource */ - int irq; - int single_dma; - spinlock_t reg_lock; - struct snd_hwdep *synth; - struct snd_rawmidi *rmidi; - struct snd_wss *wss; - unsigned char ctlregs[0x20]; - int ymode; /* SL added */ - struct snd_kcontrol *master_switch; - struct snd_kcontrol *master_volume; -}; - -#define PFX "opl3sa2: " - -#ifdef CONFIG_PNP - -static struct pnp_device_id snd_opl3sa2_pnpbiosids[] = { - { .id = "YMH0021" }, - { .id = "NMX2210" }, /* Gateway Solo 2500 */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp, snd_opl3sa2_pnpbiosids); - -static struct pnp_card_device_id snd_opl3sa2_pnpids[] = { - /* Yamaha YMF719E-S (Genius Sound Maker 3DX) */ - { .id = "YMH0020", .devs = { { "YMH0021" } } }, - /* Yamaha OPL3-SA3 (integrated on Intel's Pentium II AL440LX motherboard) */ - { .id = "YMH0030", .devs = { { "YMH0021" } } }, - /* Yamaha OPL3-SA2 */ - { .id = "YMH0800", .devs = { { "YMH0021" } } }, - /* Yamaha OPL3-SA2 */ - { .id = "YMH0801", .devs = { { "YMH0021" } } }, - /* NeoMagic MagicWave 3DX */ - { .id = "NMX2200", .devs = { { "YMH2210" } } }, - /* NeoMagic MagicWave 3D */ - { .id = "NMX2200", .devs = { { "NMX2210" } } }, - /* --- */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_opl3sa2_pnpids); - -#endif /* CONFIG_PNP */ - - -/* read control port (w/o spinlock) */ -static unsigned char __snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char reg) -{ - unsigned char result; -#if 0 - outb(0x1d, port); /* password */ - printk(KERN_DEBUG "read [0x%lx] = 0x%x\n", port, inb(port)); -#endif - outb(reg, chip->port); /* register */ - result = inb(chip->port + 1); -#if 0 - printk(KERN_DEBUG "read [0x%lx] = 0x%x [0x%x]\n", - port, result, inb(port)); -#endif - return result; -} - -/* read control port (with spinlock) */ -static unsigned char snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char reg) -{ - unsigned long flags; - unsigned char result; - - spin_lock_irqsave(&chip->reg_lock, flags); - result = __snd_opl3sa2_read(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; -} - -/* write control port (w/o spinlock) */ -static void __snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsigned char value) -{ -#if 0 - outb(0x1d, port); /* password */ -#endif - outb(reg, chip->port); /* register */ - outb(value, chip->port + 1); - chip->ctlregs[reg] = value; -} - -/* write control port (with spinlock) */ -static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsigned char value) -{ - unsigned long flags; - spin_lock_irqsave(&chip->reg_lock, flags); - __snd_opl3sa2_write(chip, reg, value); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static int __devinit snd_opl3sa2_detect(struct snd_card *card) -{ - struct snd_opl3sa2 *chip = card->private_data; - unsigned long port; - unsigned char tmp, tmp1; - char str[2]; - - port = chip->port; - if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) { - snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); - return -EBUSY; - } - /* - snd_printk(KERN_DEBUG "REG 0A = 0x%x\n", - snd_opl3sa2_read(chip, 0x0a)); - */ - chip->version = 0; - tmp = snd_opl3sa2_read(chip, OPL3SA2_MISC); - if (tmp == 0xff) { - snd_printd("OPL3-SA [0x%lx] detect = 0x%x\n", port, tmp); - return -ENODEV; - } - switch (tmp & 0x07) { - case 0x01: - chip->version = 2; /* YMF711 */ - break; - default: - chip->version = 3; - /* 0x02 - standard */ - /* 0x03 - YM715B */ - /* 0x04 - YM719 - OPL-SA4? */ - /* 0x05 - OPL3-SA3 - Libretto 100 */ - /* 0x07 - unknown - Neomagic MagicWave 3D */ - break; - } - str[0] = chip->version + '0'; - str[1] = 0; - strcat(card->shortname, str); - snd_opl3sa2_write(chip, OPL3SA2_MISC, tmp ^ 7); - if ((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MISC)) != tmp) { - snd_printd("OPL3-SA [0x%lx] detect (1) = 0x%x (0x%x)\n", port, tmp, tmp1); - return -ENODEV; - } - /* try if the MIC register is accessible */ - tmp = snd_opl3sa2_read(chip, OPL3SA2_MIC); - snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x8a); - if (((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MIC)) & 0x9f) != 0x8a) { - snd_printd("OPL3-SA [0x%lx] detect (2) = 0x%x (0x%x)\n", port, tmp, tmp1); - return -ENODEV; - } - snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x9f); - /* initialization */ - /* Power Management - full on */ - snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0); - if (chip->version > 2) { - /* ymode is bits 4&5 (of 0 to 7) on all but opl3sa2 versions */ - snd_opl3sa2_write(chip, OPL3SA2_SYS_CTRL, (chip->ymode << 4)); - } else { - /* default for opl3sa2 versions */ - snd_opl3sa2_write(chip, OPL3SA2_SYS_CTRL, 0x00); - } - snd_opl3sa2_write(chip, OPL3SA2_IRQ_CONFIG, 0x0d); /* Interrupt Channel Configuration - IRQ A = OPL3 + MPU + WSS */ - if (chip->single_dma) { - snd_opl3sa2_write(chip, OPL3SA2_DMA_CONFIG, 0x03); /* DMA Configuration - DMA A = WSS-R + WSS-P */ - } else { - snd_opl3sa2_write(chip, OPL3SA2_DMA_CONFIG, 0x21); /* DMA Configuration - DMA B = WSS-R, DMA A = WSS-P */ - } - snd_opl3sa2_write(chip, OPL3SA2_MISC, 0x80 | (tmp & 7)); /* Miscellaneous - default */ - if (chip->version > 2) { - snd_opl3sa2_write(chip, OPL3SA3_DGTL_DOWN, 0x00); /* Digital Block Partial Power Down - default */ - snd_opl3sa2_write(chip, OPL3SA3_ANLG_DOWN, 0x00); /* Analog Block Partial Power Down - default */ - } - return 0; -} - -static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id) -{ - unsigned short status; - struct snd_card *card = dev_id; - struct snd_opl3sa2 *chip; - int handled = 0; - - if (card == NULL) - return IRQ_NONE; - - chip = card->private_data; - status = snd_opl3sa2_read(chip, OPL3SA2_IRQ_STATUS); - - if (status & 0x20) { - handled = 1; - snd_opl3_interrupt(chip->synth); - } - - if ((status & 0x10) && chip->rmidi != NULL) { - handled = 1; - snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); - } - - if (status & 0x07) { /* TI,CI,PI */ - handled = 1; - snd_wss_interrupt(irq, chip->wss); - } - - if (status & 0x40) { /* hardware volume change */ - handled = 1; - /* reading from Master Lch register at 0x07 clears this bit */ - snd_opl3sa2_read(chip, OPL3SA2_MASTER_RIGHT); - snd_opl3sa2_read(chip, OPL3SA2_MASTER_LEFT); - if (chip->master_switch && chip->master_volume) { - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_switch->id); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - } - } - return IRQ_RETVAL(handled); -} - -#define OPL3SA2_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_wss_info_single, \ - .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } -#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_wss_info_single, \ - .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - -static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->ctlregs[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} - -static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val, oval; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = chip->ctlregs[reg]; - val = (oval & ~(mask << shift)) | val; - change = val != oval; - __snd_opl3sa2_write(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -#define OPL3SA2_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_wss_info_double, \ - .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } -#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_wss_info_double, \ - .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } - -static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->ctlregs[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->ctlregs[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} - -static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2, oval1, oval2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - oval1 = chip->ctlregs[left_reg]; - oval2 = chip->ctlregs[right_reg]; - val1 = (oval1 & ~(mask << shift_left)) | val1; - val2 = (oval2 & ~(mask << shift_right)) | val2; - change = val1 != oval1 || val2 != oval2; - __snd_opl3sa2_write(chip, left_reg, val1); - __snd_opl3sa2_write(chip, right_reg, val2); - } else { - oval1 = chip->ctlregs[left_reg]; - val1 = (oval1 & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2; - change = val1 != oval1; - __snd_opl3sa2_write(chip, left_reg, val1); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static const DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); - -static struct snd_kcontrol_new snd_opl3sa2_controls[] = { -OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1), -OPL3SA2_DOUBLE_TLV("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1, - db_scale_master), -OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1), -OPL3SA2_SINGLE_TLV("Mic Playback Volume", 0, 0x09, 0, 31, 1, - db_scale_5bit_12db_max), -OPL3SA2_SINGLE("ZV Port Switch", 0, 0x02, 0, 1, 0), -}; - -static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = { -OPL3SA2_DOUBLE("3D Control - Wide", 0, 0x14, 0x14, 4, 0, 7, 0), -OPL3SA2_DOUBLE("Tone Control - Bass", 0, 0x15, 0x15, 4, 0, 7, 0), -OPL3SA2_DOUBLE("Tone Control - Treble", 0, 0x16, 0x16, 4, 0, 7, 0) -}; - -static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol) -{ - struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol); - chip->master_switch = NULL; - chip->master_volume = NULL; -} - -static int __devinit snd_opl3sa2_mixer(struct snd_card *card) -{ - struct snd_opl3sa2 *chip = card->private_data; - struct snd_ctl_elem_id id1, id2; - struct snd_kcontrol *kctl; - unsigned int idx; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUX0 to CD */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - /* reassign AUX1 to FM */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "FM Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "FM Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { - snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); - return err; - } - /* add OPL3SA2 controls */ - for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0) - return err; - switch (idx) { - case 0: chip->master_switch = kctl; kctl->private_free = snd_opl3sa2_master_free; break; - case 1: chip->master_volume = kctl; kctl->private_free = snd_opl3sa2_master_free; break; - } - } - if (chip->version > 2) { - for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_tone_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opl3sa2_tone_controls[idx], chip))) < 0) - return err; - } - return 0; -} - -/* Power Management support functions */ -#ifdef CONFIG_PM -static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state) -{ - if (card) { - struct snd_opl3sa2 *chip = card->private_data; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - chip->wss->suspend(chip->wss); - /* power down */ - snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3); - } - - return 0; -} - -static int snd_opl3sa2_resume(struct snd_card *card) -{ - struct snd_opl3sa2 *chip; - int i; - - if (!card) - return 0; - - chip = card->private_data; - /* power up */ - snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D0); - - /* restore registers */ - for (i = 2; i <= 0x0a; i++) { - if (i != OPL3SA2_IRQ_STATUS) - snd_opl3sa2_write(chip, i, chip->ctlregs[i]); - } - if (chip->version > 2) { - for (i = 0x12; i <= 0x16; i++) - snd_opl3sa2_write(chip, i, chip->ctlregs[i]); - } - /* restore wss */ - chip->wss->resume(chip->wss); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif /* CONFIG_PM */ - -#ifdef CONFIG_PNP -static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, - struct pnp_dev *pdev) -{ - if (pnp_activate_dev(pdev) < 0) { - snd_printk(KERN_ERR "PnP configure failure (out of resources?)\n"); - return -EBUSY; - } - sb_port[dev] = pnp_port_start(pdev, 0); - wss_port[dev] = pnp_port_start(pdev, 1); - fm_port[dev] = pnp_port_start(pdev, 2); - midi_port[dev] = pnp_port_start(pdev, 3); - port[dev] = pnp_port_start(pdev, 4); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("%sPnP OPL3-SA: sb port=0x%lx, wss port=0x%lx, fm port=0x%lx, midi port=0x%lx\n", - pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", sb_port[dev], wss_port[dev], fm_port[dev], midi_port[dev]); - snd_printdd("%sPnP OPL3-SA: control port=0x%lx, dma1=%i, dma2=%i, irq=%i\n", - pnp_device_is_pnpbios(pdev) ? "BIOS" : "ISA", port[dev], dma1[dev], dma2[dev], irq[dev]); - return 0; -} -#endif /* CONFIG_PNP */ - -static void snd_opl3sa2_free(struct snd_card *card) -{ - struct snd_opl3sa2 *chip = card->private_data; - if (chip->irq >= 0) - free_irq(chip->irq, card); - release_and_free_resource(chip->res_port); -} - -static int snd_opl3sa2_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - struct snd_opl3sa2 *chip; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_opl3sa2), &card); - if (err < 0) - return err; - strcpy(card->driver, "OPL3SA2"); - strcpy(card->shortname, "Yamaha OPL3-SA"); - chip = card->private_data; - spin_lock_init(&chip->reg_lock); - chip->irq = -1; - card->private_free = snd_opl3sa2_free; - *cardp = card; - return 0; -} - -static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) -{ - int xirq, xdma1, xdma2; - struct snd_opl3sa2 *chip; - struct snd_wss *wss; - struct snd_opl3 *opl3; - int err; - - /* initialise this card from supplied (or default) parameter*/ - chip = card->private_data; - chip->ymode = opl3sa3_ymode[dev] & 0x03 ; - chip->port = port[dev]; - xirq = irq[dev]; - xdma1 = dma1[dev]; - xdma2 = dma2[dev]; - if (xdma2 < 0) - chip->single_dma = 1; - err = snd_opl3sa2_detect(card); - if (err < 0) - return err; - err = request_irq(xirq, snd_opl3sa2_interrupt, 0, - "OPL3-SA2", card); - if (err) { - snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); - return -ENODEV; - } - chip->irq = xirq; - err = snd_wss_create(card, - wss_port[dev] + 4, -1, - xirq, xdma1, xdma2, - WSS_HW_OPL3SA2, WSS_HWSHARE_IRQ, &wss); - if (err < 0) { - snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4); - return err; - } - chip->wss = wss; - err = snd_wss_pcm(wss, 0, NULL); - if (err < 0) - return err; - err = snd_wss_mixer(wss); - if (err < 0) - return err; - err = snd_opl3sa2_mixer(card); - if (err < 0) - return err; - err = snd_wss_timer(wss, 0, NULL); - if (err < 0) - return err; - if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { - if ((err = snd_opl3_create(card, fm_port[dev], - fm_port[dev] + 2, - OPL3_HW_OPL3, 0, &opl3)) < 0) - return err; - if ((err = snd_opl3_timer_new(opl3, 1, 2)) < 0) - return err; - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth)) < 0) - return err; - } - if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2, - midi_port[dev], - MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi)) < 0) - return err; - } - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - card->shortname, chip->port, xirq, xdma1); - if (xdma2 >= 0) - sprintf(card->longname + strlen(card->longname), "&%d", xdma2); - - return snd_card_register(card); -} - -#ifdef CONFIG_PNP -static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, - const struct pnp_device_id *id) -{ - static int dev; - int err; - struct snd_card *card; - - if (pnp_device_is_isapnp(pdev)) - return -ENOENT; /* we have another procedure - card */ - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - err = snd_opl3sa2_card_new(dev, &card); - if (err < 0) - return err; - if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_drvdata(pdev, card); - dev++; - return 0; -} - -static void __devexit snd_opl3sa2_pnp_remove(struct pnp_dev * pdev) -{ - snd_card_free(pnp_get_drvdata(pdev)); - pnp_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM -static int snd_opl3sa2_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - return snd_opl3sa2_suspend(pnp_get_drvdata(pdev), state); -} -static int snd_opl3sa2_pnp_resume(struct pnp_dev *pdev) -{ - return snd_opl3sa2_resume(pnp_get_drvdata(pdev)); -} -#endif - -static struct pnp_driver opl3sa2_pnp_driver = { - .name = "snd-opl3sa2-pnpbios", - .id_table = snd_opl3sa2_pnpbiosids, - .probe = snd_opl3sa2_pnp_detect, - .remove = __devexit_p(snd_opl3sa2_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_opl3sa2_pnp_suspend, - .resume = snd_opl3sa2_pnp_resume, -#endif -}; - -static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *id) -{ - static int dev; - struct pnp_dev *pdev; - int err; - struct snd_card *card; - - pdev = pnp_request_card_device(pcard, id->devs[0].id, NULL); - if (pdev == NULL) { - snd_printk(KERN_ERR PFX "can't get pnp device from id '%s'\n", - id->devs[0].id); - return -EBUSY; - } - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - err = snd_opl3sa2_card_new(dev, &card); - if (err < 0) - return err; - if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_opl3sa2_pnp_csuspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_opl3sa2_suspend(pnp_get_card_drvdata(pcard), state); -} -static int snd_opl3sa2_pnp_cresume(struct pnp_card_link *pcard) -{ - return snd_opl3sa2_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver opl3sa2_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "snd-opl3sa2-cpnp", - .id_table = snd_opl3sa2_pnpids, - .probe = snd_opl3sa2_pnp_cdetect, - .remove = __devexit_p(snd_opl3sa2_pnp_cremove), -#ifdef CONFIG_PM - .suspend = snd_opl3sa2_pnp_csuspend, - .resume = snd_opl3sa2_pnp_cresume, -#endif -}; -#endif /* CONFIG_PNP */ - -static int __devinit snd_opl3sa2_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev]) - return 0; -#ifdef CONFIG_PNP - if (isapnp[dev]) - return 0; -#endif - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify port\n"); - return 0; - } - if (wss_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify wss_port\n"); - return 0; - } - if (fm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify fm_port\n"); - return 0; - } - if (midi_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR PFX "specify midi_port\n"); - return 0; - } - return 1; -} - -static int __devinit snd_opl3sa2_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_opl3sa2_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_opl3sa2_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_opl3sa2_suspend(dev_get_drvdata(dev), state); -} - -static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n) -{ - return snd_opl3sa2_resume(dev_get_drvdata(dev)); -} -#endif - -#define DEV_NAME "opl3sa2" - -static struct isa_driver snd_opl3sa2_isa_driver = { - .match = snd_opl3sa2_isa_match, - .probe = snd_opl3sa2_isa_probe, - .remove = __devexit_p(snd_opl3sa2_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_opl3sa2_isa_suspend, - .resume = snd_opl3sa2_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - -static int __init alsa_card_opl3sa2_init(void) -{ - int err; - - err = isa_register_driver(&snd_opl3sa2_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_driver(&opl3sa2_pnp_driver); - if (!err) - pnp_registered = 1; - - err = pnp_register_card_driver(&opl3sa2_pnpc_driver); - if (!err) - pnpc_registered = 1; - - if (isa_registered || pnp_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_opl3sa2_exit(void) -{ -#ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&opl3sa2_pnpc_driver); - if (pnp_registered) - pnp_unregister_driver(&opl3sa2_pnp_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_opl3sa2_isa_driver); -} - -module_init(alsa_card_opl3sa2_init) -module_exit(alsa_card_opl3sa2_exit) diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/Makefile b/ANDROID_3.4.5/sound/isa/opti9xx/Makefile deleted file mode 100644 index b4d894db..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-opti92x-ad1848-objs := opti92x-ad1848.o -snd-opti92x-cs4231-objs := opti92x-cs4231.o -snd-opti93x-objs := opti93x.o -snd-miro-objs := miro.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o -obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o -obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o -obj-$(CONFIG_SND_MIRO) += snd-miro.o diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/miro.c b/ANDROID_3.4.5/sound/isa/opti9xx/miro.c deleted file mode 100644 index c24594c8..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/miro.c +++ /dev/null @@ -1,1680 +0,0 @@ -/* - * ALSA soundcard driver for Miro miroSOUND PCM1 pro - * miroSOUND PCM12 - * miroSOUND PCM20 Radio - * - * Copyright (C) 2004-2005 Martin Langer <martin-langer@gmx.de> - * - * Based on OSS ACI and ALSA OPTi9xx drivers - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/pnp.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/opl4.h> -#include <sound/control.h> -#include <sound/info.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> -#include <sound/aci.h> - -MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio"); -MODULE_SUPPORTED_DEVICE("{{Miro,miroSOUND PCM1 pro}, " - "{Miro,miroSOUND PCM12}, " - "{Miro,miroSOUND PCM20 Radio}}"); - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */ -static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */ -static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */ -static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */ -static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */ -static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -static int wss; -static int ide; -#ifdef CONFIG_PNP -static bool isapnp = 1; /* Enable ISA PnP detection */ -#endif - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for miro soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for miro soundcard."); -module_param(port, long, 0444); -MODULE_PARM_DESC(port, "WSS port # for miro driver."); -module_param(mpu_port, long, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver."); -module_param(fm_port, long, 0444); -MODULE_PARM_DESC(fm_port, "FM Port # for miro driver."); -module_param(irq, int, 0444); -MODULE_PARM_DESC(irq, "WSS irq # for miro driver."); -module_param(mpu_irq, int, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver."); -module_param(dma1, int, 0444); -MODULE_PARM_DESC(dma1, "1st dma # for miro driver."); -module_param(dma2, int, 0444); -MODULE_PARM_DESC(dma2, "2nd dma # for miro driver."); -module_param(wss, int, 0444); -MODULE_PARM_DESC(wss, "wss mode"); -module_param(ide, int, 0444); -MODULE_PARM_DESC(ide, "enable ide port"); -#ifdef CONFIG_PNP -module_param(isapnp, bool, 0444); -MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard."); -#endif - -#define OPTi9XX_HW_DETECT 0 -#define OPTi9XX_HW_82C928 1 -#define OPTi9XX_HW_82C929 2 -#define OPTi9XX_HW_82C924 3 -#define OPTi9XX_HW_82C925 4 -#define OPTi9XX_HW_82C930 5 -#define OPTi9XX_HW_82C931 6 -#define OPTi9XX_HW_82C933 7 -#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933 - -#define OPTi9XX_MC_REG(n) n - -struct snd_miro { - unsigned short hardware; - unsigned char password; - char name[7]; - - struct resource *res_mc_base; - struct resource *res_aci_port; - - unsigned long mc_base; - unsigned long mc_base_size; - unsigned long pwd_reg; - - spinlock_t lock; - struct snd_pcm *pcm; - - long wss_base; - int irq; - int dma1; - int dma2; - - long mpu_port; - int mpu_irq; - - struct snd_miro_aci *aci; -}; - -static struct snd_miro_aci aci_device; - -static char * snd_opti9xx_names[] = { - "unknown", - "82C928", "82C929", - "82C924", "82C925", - "82C930", "82C931", "82C933" -}; - -static int snd_miro_pnp_is_probed; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_miro_pnpids[] = { - /* PCM20 and PCM12 in PnP mode */ - { .id = "MIR0924", - .devs = { { "MIR0000" }, { "MIR0002" }, { "MIR0005" } }, }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_miro_pnpids); - -#endif /* CONFIG_PNP */ - -/* - * ACI control - */ - -static int aci_busy_wait(struct snd_miro_aci *aci) -{ - long timeout; - unsigned char byte; - - for (timeout = 1; timeout <= ACI_MINTIME + 30; timeout++) { - byte = inb(aci->aci_port + ACI_REG_BUSY); - if ((byte & 1) == 0) { - if (timeout >= ACI_MINTIME) - snd_printd("aci ready in round %ld.\n", - timeout-ACI_MINTIME); - return byte; - } - if (timeout >= ACI_MINTIME) { - long out=10*HZ; - switch (timeout-ACI_MINTIME) { - case 0 ... 9: - out /= 10; - case 10 ... 19: - out /= 10; - case 20 ... 30: - out /= 10; - default: - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(out); - break; - } - } - } - snd_printk(KERN_ERR "aci_busy_wait() time out\n"); - return -EBUSY; -} - -static inline int aci_write(struct snd_miro_aci *aci, unsigned char byte) -{ - if (aci_busy_wait(aci) >= 0) { - outb(byte, aci->aci_port + ACI_REG_COMMAND); - return 0; - } else { - snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte); - return -EBUSY; - } -} - -static inline int aci_read(struct snd_miro_aci *aci) -{ - unsigned char byte; - - if (aci_busy_wait(aci) >= 0) { - byte = inb(aci->aci_port + ACI_REG_STATUS); - return byte; - } else { - snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n"); - return -EBUSY; - } -} - -int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3) -{ - int write[] = {write1, write2, write3}; - int value, i; - - if (mutex_lock_interruptible(&aci->aci_mutex)) - return -EINTR; - - for (i=0; i<3; i++) { - if (write[i]< 0 || write[i] > 255) - break; - else { - value = aci_write(aci, write[i]); - if (value < 0) - goto out; - } - } - - value = aci_read(aci); - -out: mutex_unlock(&aci->aci_mutex); - return value; -} -EXPORT_SYMBOL(snd_aci_cmd); - -static int aci_getvalue(struct snd_miro_aci *aci, unsigned char index) -{ - return snd_aci_cmd(aci, ACI_STATUS, index, -1); -} - -static int aci_setvalue(struct snd_miro_aci *aci, unsigned char index, - int value) -{ - return snd_aci_cmd(aci, index, value, -1); -} - -struct snd_miro_aci *snd_aci_get_aci(void) -{ - if (aci_device.aci_port == 0) - return NULL; - return &aci_device; -} -EXPORT_SYMBOL(snd_aci_get_aci); - -/* - * MIXER part - */ - -#define snd_miro_info_capture snd_ctl_boolean_mono_info - -static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int value; - - value = aci_getvalue(miro->aci, ACI_S_GENERAL); - if (value < 0) { - snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", - value); - return value; - } - - ucontrol->value.integer.value[0] = value & 0x20; - - return 0; -} - -static int snd_miro_put_capture(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int change, value, error; - - value = !(ucontrol->value.integer.value[0]); - - error = aci_setvalue(miro->aci, ACI_SET_SOLOMODE, value); - if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", - error); - return error; - } - - change = (value != miro->aci->aci_solomode); - miro->aci->aci_solomode = value; - - return change; -} - -static int snd_miro_info_preamp(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 = 3; - - return 0; -} - -static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int value; - - if (miro->aci->aci_version <= 176) { - - /* - OSS says it's not readable with versions < 176. - But it doesn't work on my card, - which is a PCM12 with aci_version = 176. - */ - - ucontrol->value.integer.value[0] = miro->aci->aci_preamp; - return 0; - } - - value = aci_getvalue(miro->aci, ACI_GET_PREAMP); - if (value < 0) { - snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", - value); - return value; - } - - ucontrol->value.integer.value[0] = value; - - return 0; -} - -static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int error, value, change; - - value = ucontrol->value.integer.value[0]; - - error = aci_setvalue(miro->aci, ACI_SET_PREAMP, value); - if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", - error); - return error; - } - - change = (value != miro->aci->aci_preamp); - miro->aci->aci_preamp = value; - - return change; -} - -#define snd_miro_info_amp snd_ctl_boolean_mono_info - -static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = miro->aci->aci_amp; - - return 0; -} - -static int snd_miro_put_amp(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int error, value, change; - - value = ucontrol->value.integer.value[0]; - - error = aci_setvalue(miro->aci, ACI_SET_POWERAMP, value); - if (error < 0) { - snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error); - return error; - } - - change = (value != miro->aci->aci_amp); - miro->aci->aci_amp = value; - - return change; -} - -#define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = ctl_name, \ - .index = ctl_index, \ - .info = snd_miro_info_double, \ - .get = snd_miro_get_double, \ - .put = snd_miro_put_double, \ - .private_value = get_right_reg | (set_right_reg << 8) \ -} - -static int snd_miro_info_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int reg = kcontrol->private_value & 0xff; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - - if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) { - - /* equalizer elements */ - - uinfo->value.integer.min = - 0x7f; - uinfo->value.integer.max = 0x7f; - } else { - - /* non-equalizer elements */ - - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 0x20; - } - - return 0; -} - -static int snd_miro_get_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *uinfo) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - int left_val, right_val; - - int right_reg = kcontrol->private_value & 0xff; - int left_reg = right_reg + 1; - - right_val = aci_getvalue(miro->aci, right_reg); - if (right_val < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val); - return right_val; - } - - left_val = aci_getvalue(miro->aci, left_reg); - if (left_val < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val); - return left_val; - } - - if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) { - - /* equalizer elements */ - - if (left_val < 0x80) { - uinfo->value.integer.value[0] = left_val; - } else { - uinfo->value.integer.value[0] = 0x80 - left_val; - } - - if (right_val < 0x80) { - uinfo->value.integer.value[1] = right_val; - } else { - uinfo->value.integer.value[1] = 0x80 - right_val; - } - - } else { - - /* non-equalizer elements */ - - uinfo->value.integer.value[0] = 0x20 - left_val; - uinfo->value.integer.value[1] = 0x20 - right_val; - } - - return 0; -} - -static int snd_miro_put_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_miro *miro = snd_kcontrol_chip(kcontrol); - struct snd_miro_aci *aci = miro->aci; - int left, right, left_old, right_old; - int setreg_left, setreg_right, getreg_left, getreg_right; - int change, error; - - left = ucontrol->value.integer.value[0]; - right = ucontrol->value.integer.value[1]; - - setreg_right = (kcontrol->private_value >> 8) & 0xff; - setreg_left = setreg_right + 8; - if (setreg_right == ACI_SET_MASTER) - setreg_left -= 7; - - getreg_right = kcontrol->private_value & 0xff; - getreg_left = getreg_right + 1; - - left_old = aci_getvalue(aci, getreg_left); - if (left_old < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old); - return left_old; - } - - right_old = aci_getvalue(aci, getreg_right); - if (right_old < 0) { - snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old); - return right_old; - } - - if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) { - - /* equalizer elements */ - - if (left < -0x7f || left > 0x7f || - right < -0x7f || right > 0x7f) - return -EINVAL; - - if (left_old > 0x80) - left_old = 0x80 - left_old; - if (right_old > 0x80) - right_old = 0x80 - right_old; - - if (left >= 0) { - error = aci_setvalue(aci, setreg_left, left); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - left, error); - return error; - } - } else { - error = aci_setvalue(aci, setreg_left, 0x80 - left); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x80 - left, error); - return error; - } - } - - if (right >= 0) { - error = aci_setvalue(aci, setreg_right, right); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - right, error); - return error; - } - } else { - error = aci_setvalue(aci, setreg_right, 0x80 - right); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x80 - right, error); - return error; - } - } - - } else { - - /* non-equalizer elements */ - - if (left < 0 || left > 0x20 || - right < 0 || right > 0x20) - return -EINVAL; - - left_old = 0x20 - left_old; - right_old = 0x20 - right_old; - - error = aci_setvalue(aci, setreg_left, 0x20 - left); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x20 - left, error); - return error; - } - error = aci_setvalue(aci, setreg_right, 0x20 - right); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - 0x20 - right, error); - return error; - } - } - - change = (left != left_old) || (right != right_old); - - return change; -} - -static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = { -MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER), -MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC), -MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE), -MIRO_DOUBLE("CD Playback Volume", 0, ACI_GET_CD, ACI_SET_CD), -MIRO_DOUBLE("Synth Playback Volume", 0, ACI_GET_SYNTH, ACI_SET_SYNTH), -MIRO_DOUBLE("PCM Playback Volume", 1, ACI_GET_PCM, ACI_SET_PCM), -MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2), -}; - -/* Equalizer with seven bands (only PCM20) - from -12dB up to +12dB on each band */ -static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = { -MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1), -MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2), -MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3), -MIRO_DOUBLE("Tone Control - 1 kHz", 0, ACI_GET_EQ4, ACI_SET_EQ4), -MIRO_DOUBLE("Tone Control - 2.5 kHz", 0, ACI_GET_EQ5, ACI_SET_EQ5), -MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6), -MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7), -}; - -static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = { -MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1), -}; - -static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = { -MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1), -}; - -static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Boost", - .index = 1, - .info = snd_miro_info_preamp, - .get = snd_miro_get_preamp, - .put = snd_miro_put_preamp, -}}; - -static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Boost", - .index = 0, - .info = snd_miro_info_amp, - .get = snd_miro_get_amp, - .put = snd_miro_put_amp, -}}; - -static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = { -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "PCM Capture Switch", - .index = 0, - .info = snd_miro_info_capture, - .get = snd_miro_get_capture, - .put = snd_miro_put_capture, -}}; - -static unsigned char aci_init_values[][2] __devinitdata = { - { ACI_SET_MUTE, 0x00 }, - { ACI_SET_POWERAMP, 0x00 }, - { ACI_SET_PREAMP, 0x00 }, - { ACI_SET_SOLOMODE, 0x00 }, - { ACI_SET_MIC + 0, 0x20 }, - { ACI_SET_MIC + 8, 0x20 }, - { ACI_SET_LINE + 0, 0x20 }, - { ACI_SET_LINE + 8, 0x20 }, - { ACI_SET_CD + 0, 0x20 }, - { ACI_SET_CD + 8, 0x20 }, - { ACI_SET_PCM + 0, 0x20 }, - { ACI_SET_PCM + 8, 0x20 }, - { ACI_SET_LINE1 + 0, 0x20 }, - { ACI_SET_LINE1 + 8, 0x20 }, - { ACI_SET_LINE2 + 0, 0x20 }, - { ACI_SET_LINE2 + 8, 0x20 }, - { ACI_SET_SYNTH + 0, 0x20 }, - { ACI_SET_SYNTH + 8, 0x20 }, - { ACI_SET_MASTER + 0, 0x20 }, - { ACI_SET_MASTER + 1, 0x20 }, -}; - -static int __devinit snd_set_aci_init_values(struct snd_miro *miro) -{ - int idx, error; - struct snd_miro_aci *aci = miro->aci; - - /* enable WSS on PCM1 */ - - if ((aci->aci_product == 'A') && wss) { - error = aci_setvalue(aci, ACI_SET_WSS, wss); - if (error < 0) { - snd_printk(KERN_ERR "enabling WSS mode failed\n"); - return error; - } - } - - /* enable IDE port */ - - if (ide) { - error = aci_setvalue(aci, ACI_SET_IDE, ide); - if (error < 0) { - snd_printk(KERN_ERR "enabling IDE port failed\n"); - return error; - } - } - - /* set common aci values */ - - for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) { - error = aci_setvalue(aci, aci_init_values[idx][0], - aci_init_values[idx][1]); - if (error < 0) { - snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n", - aci_init_values[idx][0], error); - return error; - } - } - aci->aci_amp = 0; - aci->aci_preamp = 0; - aci->aci_solomode = 1; - - return 0; -} - -static int __devinit snd_miro_mixer(struct snd_card *card, - struct snd_miro *miro) -{ - unsigned int idx; - int err; - - if (snd_BUG_ON(!miro || !card)) - return -EINVAL; - - switch (miro->hardware) { - case OPTi9XX_HW_82C924: - strcpy(card->mixername, "ACI & OPTi924"); - break; - case OPTi9XX_HW_82C929: - strcpy(card->mixername, "ACI & OPTi929"); - break; - default: - snd_BUG(); - break; - } - - for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0) - return err; - } - - if ((miro->aci->aci_product == 'A') || - (miro->aci->aci_product == 'B')) { - /* PCM1/PCM12 with power-amp and Line 2 */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) - return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0) - return err; - } - - if ((miro->aci->aci_product == 'B') || - (miro->aci->aci_product == 'C')) { - /* PCM12/PCM20 with mic-preamp */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) - return err; - if (miro->aci->aci_version >= 176) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) - return err; - } - - if (miro->aci->aci_product == 'C') { - /* PCM20 with radio and 7 band equalizer */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) - return err; - for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0) - return err; - } - } - - return 0; -} - -static long snd_legacy_find_free_ioport(long *port_table, long size) -{ - while (*port_table != -1) { - struct resource *res; - if ((res = request_region(*port_table, size, - "ALSA test")) != NULL) { - release_and_free_resource(res); - return *port_table; - } - port_table++; - } - return -1; -} - -static int __devinit snd_miro_init(struct snd_miro *chip, - unsigned short hardware) -{ - static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; - - chip->hardware = hardware; - strcpy(chip->name, snd_opti9xx_names[hardware]); - - chip->mc_base_size = opti9xx_mc_size[hardware]; - - spin_lock_init(&chip->lock); - - chip->wss_base = -1; - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - chip->mpu_port = -1; - chip->mpu_irq = -1; - - chip->pwd_reg = 3; - -#ifdef CONFIG_PNP - if (isapnp && chip->mc_base) - /* PnP resource gives the least 10 bits */ - chip->mc_base |= 0xc00; - else -#endif - chip->mc_base = 0xf8c; - - switch (hardware) { - case OPTi9XX_HW_82C929: - chip->password = 0xe3; - break; - - case OPTi9XX_HW_82C924: - chip->password = 0xe5; - break; - - default: - snd_printk(KERN_ERR "sorry, no support for %d\n", hardware); - return -ENODEV; - } - - return 0; -} - -static unsigned char snd_miro_read(struct snd_miro *chip, - unsigned char reg) -{ - unsigned long flags; - unsigned char retval = 0xff; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { - case OPTi9XX_HW_82C924: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - retval = inb(chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C929: - retval = inb(chip->mc_base + reg); - break; - - default: - snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); - return retval; -} - -static void snd_miro_write(struct snd_miro *chip, unsigned char reg, - unsigned char value) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { - case OPTi9XX_HW_82C924: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(value, chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C929: - outb(value, chip->mc_base + reg); - break; - - default: - snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); -} - - -#define snd_miro_write_mask(chip, reg, value, mask) \ - snd_miro_write(chip, reg, \ - (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask))) - -/* - * Proc Interface - */ - -static void snd_miro_proc_read(struct snd_info_entry * entry, - struct snd_info_buffer *buffer) -{ - struct snd_miro *miro = (struct snd_miro *) entry->private_data; - struct snd_miro_aci *aci = miro->aci; - char* model = "unknown"; - - /* miroSOUND PCM1 pro, early PCM12 */ - - if ((miro->hardware == OPTi9XX_HW_82C929) && - (aci->aci_vendor == 'm') && - (aci->aci_product == 'A')) { - switch (aci->aci_version) { - case 3: - model = "miroSOUND PCM1 pro"; - break; - default: - model = "miroSOUND PCM1 pro / (early) PCM12"; - break; - } - } - - /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ - - if ((miro->hardware == OPTi9XX_HW_82C924) && - (aci->aci_vendor == 'm') && - (aci->aci_product == 'B')) { - switch (aci->aci_version) { - case 4: - model = "miroSOUND PCM12"; - break; - case 176: - model = "miroSOUND PCM12 (Rev. E)"; - break; - default: - model = "miroSOUND PCM12 / PCM12 pnp"; - break; - } - } - - /* miroSOUND PCM20 radio */ - - if ((miro->hardware == OPTi9XX_HW_82C924) && - (aci->aci_vendor == 'm') && - (aci->aci_product == 'C')) { - switch (aci->aci_version) { - case 7: - model = "miroSOUND PCM20 radio (Rev. E)"; - break; - default: - model = "miroSOUND PCM20 radio"; - break; - } - } - - snd_iprintf(buffer, "\nGeneral information:\n"); - snd_iprintf(buffer, " model : %s\n", model); - snd_iprintf(buffer, " opti : %s\n", miro->name); - snd_iprintf(buffer, " codec : %s\n", miro->pcm->name); - snd_iprintf(buffer, " port : 0x%lx\n", miro->wss_base); - snd_iprintf(buffer, " irq : %d\n", miro->irq); - snd_iprintf(buffer, " dma : %d,%d\n\n", miro->dma1, miro->dma2); - - snd_iprintf(buffer, "MPU-401:\n"); - snd_iprintf(buffer, " port : 0x%lx\n", miro->mpu_port); - snd_iprintf(buffer, " irq : %d\n\n", miro->mpu_irq); - - snd_iprintf(buffer, "ACI information:\n"); - snd_iprintf(buffer, " vendor : "); - switch (aci->aci_vendor) { - case 'm': - snd_iprintf(buffer, "Miro\n"); - break; - default: - snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_vendor); - break; - } - - snd_iprintf(buffer, " product : "); - switch (aci->aci_product) { - case 'A': - snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n"); - break; - case 'B': - snd_iprintf(buffer, "miroSOUND PCM12\n"); - break; - case 'C': - snd_iprintf(buffer, "miroSOUND PCM20 radio\n"); - break; - default: - snd_iprintf(buffer, "unknown (0x%x)\n", aci->aci_product); - break; - } - - snd_iprintf(buffer, " firmware: %d (0x%x)\n", - aci->aci_version, aci->aci_version); - snd_iprintf(buffer, " port : 0x%lx-0x%lx\n", - aci->aci_port, aci->aci_port+2); - snd_iprintf(buffer, " wss : 0x%x\n", wss); - snd_iprintf(buffer, " ide : 0x%x\n", ide); - snd_iprintf(buffer, " solomode: 0x%x\n", aci->aci_solomode); - snd_iprintf(buffer, " amp : 0x%x\n", aci->aci_amp); - snd_iprintf(buffer, " preamp : 0x%x\n", aci->aci_preamp); -} - -static void __devinit snd_miro_proc_init(struct snd_card *card, - struct snd_miro *miro) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(card, "miro", &entry)) - snd_info_set_text_ops(entry, miro, snd_miro_proc_read); -} - -/* - * Init - */ - -static int __devinit snd_miro_configure(struct snd_miro *chip) -{ - unsigned char wss_base_bits; - unsigned char irq_bits; - unsigned char dma_bits; - unsigned char mpu_port_bits = 0; - unsigned char mpu_irq_bits; - unsigned long flags; - - snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); - snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */ - snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); - - switch (chip->hardware) { - case OPTi9XX_HW_82C924: - snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); - snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); - break; - case OPTi9XX_HW_82C929: - /* untested init commands for OPTi929 */ - snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c); - break; - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - return -EINVAL; - } - - /* PnP resource says it decodes only 10 bits of address */ - switch (chip->wss_base & 0x3ff) { - case 0x130: - chip->wss_base = 0x530; - wss_base_bits = 0x00; - break; - case 0x204: - chip->wss_base = 0x604; - wss_base_bits = 0x03; - break; - case 0x280: - chip->wss_base = 0xe80; - wss_base_bits = 0x01; - break; - case 0x340: - chip->wss_base = 0xf40; - wss_base_bits = 0x02; - break; - default: - snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base); - goto __skip_base; - } - snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); - -__skip_base: - switch (chip->irq) { - case 5: - irq_bits = 0x05; - break; - case 7: - irq_bits = 0x01; - break; - case 9: - irq_bits = 0x02; - break; - case 10: - irq_bits = 0x03; - break; - case 11: - irq_bits = 0x04; - break; - default: - snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq); - goto __skip_resources; - } - - switch (chip->dma1) { - case 0: - dma_bits = 0x01; - break; - case 1: - dma_bits = 0x02; - break; - case 3: - dma_bits = 0x03; - break; - default: - snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1); - goto __skip_resources; - } - - if (chip->dma1 == chip->dma2) { - snd_printk(KERN_ERR "don't want to share dmas\n"); - return -EBUSY; - } - - switch (chip->dma2) { - case 0: - case 1: - break; - default: - snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2); - goto __skip_resources; - } - dma_bits |= 0x04; - - spin_lock_irqsave(&chip->lock, flags); - outb(irq_bits << 3 | dma_bits, chip->wss_base); - spin_unlock_irqrestore(&chip->lock, flags); - -__skip_resources: - if (chip->hardware > OPTi9XX_HW_82C928) { - switch (chip->mpu_port) { - case 0: - case -1: - break; - case 0x300: - mpu_port_bits = 0x03; - break; - case 0x310: - mpu_port_bits = 0x02; - break; - case 0x320: - mpu_port_bits = 0x01; - break; - case 0x330: - mpu_port_bits = 0x00; - break; - default: - snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n", - chip->mpu_port); - goto __skip_mpu; - } - - switch (chip->mpu_irq) { - case 5: - mpu_irq_bits = 0x02; - break; - case 7: - mpu_irq_bits = 0x03; - break; - case 9: - mpu_irq_bits = 0x00; - break; - case 10: - mpu_irq_bits = 0x01; - break; - default: - snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n", - chip->mpu_irq); - goto __skip_mpu; - } - - snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), - (chip->mpu_port <= 0) ? 0x00 : - 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, - 0xf8); - } -__skip_mpu: - - return 0; -} - -static int __devinit snd_miro_opti_check(struct snd_miro *chip) -{ - unsigned char value; - - chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, - "OPTi9xx MC"); - if (chip->res_mc_base == NULL) - return -ENOMEM; - - value = snd_miro_read(chip, OPTi9XX_MC_REG(1)); - if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1))) - if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1))) - return 0; - - release_and_free_resource(chip->res_mc_base); - chip->res_mc_base = NULL; - - return -ENODEV; -} - -static int __devinit snd_card_miro_detect(struct snd_card *card, - struct snd_miro *chip) -{ - int i, err; - - for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { - - if ((err = snd_miro_init(chip, i)) < 0) - return err; - - err = snd_miro_opti_check(chip); - if (err == 0) - return 1; - } - - return -ENODEV; -} - -static int __devinit snd_card_miro_aci_detect(struct snd_card *card, - struct snd_miro *miro) -{ - unsigned char regval; - int i; - struct snd_miro_aci *aci = &aci_device; - - miro->aci = aci; - - mutex_init(&aci->aci_mutex); - - /* get ACI port from OPTi9xx MC 4 */ - - regval=inb(miro->mc_base + 4); - aci->aci_port = (regval & 0x10) ? 0x344 : 0x354; - - miro->res_aci_port = request_region(aci->aci_port, 3, "miro aci"); - if (miro->res_aci_port == NULL) { - snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n", - aci->aci_port, aci->aci_port+2); - return -ENOMEM; - } - - /* force ACI into a known state */ - for (i = 0; i < 3; i++) - if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) { - snd_printk(KERN_ERR "can't force aci into known state.\n"); - return -ENXIO; - } - - aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); - aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); - if (aci->aci_vendor < 0 || aci->aci_product < 0) { - snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", - aci->aci_port); - return -ENXIO; - } - - aci->aci_version = snd_aci_cmd(aci, ACI_READ_VERSION, -1, -1); - if (aci->aci_version < 0) { - snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n", - aci->aci_port); - return -ENXIO; - } - - if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 || - snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || - snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { - snd_printk(KERN_ERR "can't initialize aci.\n"); - return -ENXIO; - } - - return 0; -} - -static void snd_card_miro_free(struct snd_card *card) -{ - struct snd_miro *miro = card->private_data; - - release_and_free_resource(miro->res_aci_port); - if (miro->aci) - miro->aci->aci_port = 0; - release_and_free_resource(miro->res_mc_base); -} - -static int __devinit snd_miro_probe(struct snd_card *card) -{ - int error; - struct snd_miro *miro = card->private_data; - struct snd_wss *codec; - struct snd_timer *timer; - struct snd_pcm *pcm; - struct snd_rawmidi *rmidi; - - if (!miro->res_mc_base) { - miro->res_mc_base = request_region(miro->mc_base, - miro->mc_base_size, - "miro (OPTi9xx MC)"); - if (miro->res_mc_base == NULL) { - snd_printk(KERN_ERR "request for OPTI9xx MC failed\n"); - return -ENOMEM; - } - } - - error = snd_card_miro_aci_detect(card, miro); - if (error < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to detect aci chip\n"); - return -ENODEV; - } - - miro->wss_base = port; - miro->mpu_port = mpu_port; - miro->irq = irq; - miro->mpu_irq = mpu_irq; - miro->dma1 = dma1; - miro->dma2 = dma2; - - /* init proc interface */ - snd_miro_proc_init(card, miro); - - error = snd_miro_configure(miro); - if (error) - return error; - - error = snd_wss_create(card, miro->wss_base + 4, -1, - miro->irq, miro->dma1, miro->dma2, - WSS_HW_DETECT, 0, &codec); - if (error < 0) - return error; - - error = snd_wss_pcm(codec, 0, &pcm); - if (error < 0) - return error; - - error = snd_wss_mixer(codec); - if (error < 0) - return error; - - error = snd_wss_timer(codec, 0, &timer); - if (error < 0) - return error; - - miro->pcm = pcm; - - error = snd_miro_mixer(card, miro); - if (error < 0) - return error; - - if (miro->aci->aci_vendor == 'm') { - /* It looks like a miro sound card. */ - switch (miro->aci->aci_product) { - case 'A': - sprintf(card->shortname, - "miroSOUND PCM1 pro / PCM12"); - break; - case 'B': - sprintf(card->shortname, - "miroSOUND PCM12"); - break; - case 'C': - sprintf(card->shortname, - "miroSOUND PCM20 radio"); - break; - default: - sprintf(card->shortname, - "unknown miro"); - snd_printk(KERN_INFO "unknown miro aci id\n"); - break; - } - } else { - snd_printk(KERN_INFO "found unsupported aci card\n"); - sprintf(card->shortname, "unknown Cardinal Technologies"); - } - - strcpy(card->driver, "miro"); - sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, miro->name, pcm->name, miro->wss_base + 4, - miro->irq, miro->dma1, miro->dma2); - - if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) - rmidi = NULL; - else { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, miro->mpu_irq, &rmidi); - if (error < 0) - snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", - mpu_port); - } - - if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { - struct snd_opl3 *opl3 = NULL; - struct snd_opl4 *opl4; - - if (snd_opl4_create(card, fm_port, fm_port - 8, - 2, &opl3, &opl4) < 0) - snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", - fm_port); - } - - error = snd_set_aci_init_values(miro); - if (error < 0) - return error; - - return snd_card_register(card); -} - -static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n) -{ -#ifdef CONFIG_PNP - if (snd_miro_pnp_is_probed) - return 0; - if (isapnp) - return 0; -#endif - return 1; -} - -static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n) -{ - static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; - static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; - static int possible_irqs[] = {11, 9, 10, 7, -1}; - static int possible_mpu_irqs[] = {10, 5, 9, 7, -1}; - static int possible_dma1s[] = {3, 1, 0, -1}; - static int possible_dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, - {0, -1} }; - - int error; - struct snd_miro *miro; - struct snd_card *card; - - error = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); - if (error < 0) - return error; - - card->private_free = snd_card_miro_free; - miro = card->private_data; - - error = snd_card_miro_detect(card, miro); - if (error < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n"); - return -ENODEV; - } - - if (port == SNDRV_AUTO_PORT) { - port = snd_legacy_find_free_ioport(possible_ports, 4); - if (port < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free WSS port\n"); - return -EBUSY; - } - } - - if (mpu_port == SNDRV_AUTO_PORT) { - mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2); - if (mpu_port < 0) { - snd_card_free(card); - snd_printk(KERN_ERR - "unable to find a free MPU401 port\n"); - return -EBUSY; - } - } - - if (irq == SNDRV_AUTO_IRQ) { - irq = snd_legacy_find_free_irq(possible_irqs); - if (irq < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (mpu_irq == SNDRV_AUTO_IRQ) { - mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs); - if (mpu_irq < 0) { - snd_card_free(card); - snd_printk(KERN_ERR - "unable to find a free MPU401 IRQ\n"); - return -EBUSY; - } - } - if (dma1 == SNDRV_AUTO_DMA) { - dma1 = snd_legacy_find_free_dma(possible_dma1s); - if (dma1 < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free DMA1\n"); - return -EBUSY; - } - } - if (dma2 == SNDRV_AUTO_DMA) { - dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]); - if (dma2 < 0) { - snd_card_free(card); - snd_printk(KERN_ERR "unable to find a free DMA2\n"); - return -EBUSY; - } - } - - snd_card_set_dev(card, devptr); - - error = snd_miro_probe(card); - if (error < 0) { - snd_card_free(card); - return error; - } - - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devexit snd_miro_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "miro" - -static struct isa_driver snd_miro_driver = { - .match = snd_miro_isa_match, - .probe = snd_miro_isa_probe, - .remove = __devexit_p(snd_miro_isa_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP - -static int __devinit snd_card_miro_pnp(struct snd_miro *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *pid) -{ - struct pnp_dev *pdev; - int err; - struct pnp_dev *devmpu; - struct pnp_dev *devmc; - - pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (pdev == NULL) - return -EBUSY; - - devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - if (devmpu == NULL) - return -EBUSY; - - devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); - if (devmc == NULL) - return -EBUSY; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); - return err; - } - - err = pnp_activate_dev(devmc); - if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", - err); - return err; - } - - port = pnp_port_start(pdev, 1); - fm_port = pnp_port_start(pdev, 2) + 8; - - /* - * The MC(0) is never accessed and the miroSOUND PCM20 card does not - * include it in the PnP resource range. OPTI93x include it. - */ - chip->mc_base = pnp_port_start(devmc, 0) - 1; - chip->mc_base_size = pnp_port_len(devmc, 0) + 1; - - irq = pnp_irq(pdev, 0); - dma1 = pnp_dma(pdev, 0); - dma2 = pnp_dma(pdev, 1); - - if (mpu_port > 0) { - err = pnp_activate_dev(devmpu); - if (err < 0) { - snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); - mpu_port = -1; - return err; - } - mpu_port = pnp_port_start(devmpu, 0); - mpu_irq = pnp_irq(devmpu, 0); - } - return 0; -} - -static int __devinit snd_miro_pnp_probe(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_card *card; - int err; - struct snd_miro *miro; - - if (snd_miro_pnp_is_probed) - return -EBUSY; - if (!isapnp) - return -ENODEV; - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_miro), &card); - if (err < 0) - return err; - - card->private_free = snd_card_miro_free; - miro = card->private_data; - - err = snd_card_miro_pnp(miro, pcard, pid); - if (err) { - snd_card_free(card); - return err; - } - - /* only miroSOUND PCM20 and PCM12 == OPTi924 */ - err = snd_miro_init(miro, OPTi9XX_HW_82C924); - if (err) { - snd_card_free(card); - return err; - } - - err = snd_miro_opti_check(miro); - if (err) { - snd_printk(KERN_ERR "OPTI chip not found\n"); - snd_card_free(card); - return err; - } - - snd_card_set_dev(card, &pcard->card->dev); - err = snd_miro_probe(card); - if (err < 0) { - snd_card_free(card); - return err; - } - pnp_set_card_drvdata(pcard, card); - snd_miro_pnp_is_probed = 1; - return 0; -} - -static void __devexit snd_miro_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); - snd_miro_pnp_is_probed = 0; -} - -static struct pnp_card_driver miro_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "miro", - .id_table = snd_miro_pnpids, - .probe = snd_miro_pnp_probe, - .remove = __devexit_p(snd_miro_pnp_remove), -}; -#endif - -static int __init alsa_card_miro_init(void) -{ -#ifdef CONFIG_PNP - pnp_register_card_driver(&miro_pnpc_driver); - if (snd_miro_pnp_is_probed) - return 0; - pnp_unregister_card_driver(&miro_pnpc_driver); -#endif - return isa_register_driver(&snd_miro_driver, 1); -} - -static void __exit alsa_card_miro_exit(void) -{ - if (!snd_miro_pnp_is_probed) { - isa_unregister_driver(&snd_miro_driver); - return; - } -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&miro_pnpc_driver); -#endif -} - -module_init(alsa_card_miro_init) -module_exit(alsa_card_miro_exit) diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c b/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c deleted file mode 100644 index d7ccf28b..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-ad1848.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* - card-opti92x-ad1848.c - driver for OPTi 82c92x based soundcards. - Copyright (C) 1998-2000 by Massimo Piccioni <dafastidio@libero.it> - - Part of this code was developed at the Italian Ministry of Air Defence, - Sixth Division (oh, che pace ...), Rome. - - Thanks to Maria Grazia Pollarini, Salvatore Vassallo. - - 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/err.h> -#include <linux/isa.h> -#include <linux/delay.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/tlv.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#ifndef OPTi93X -#include <sound/opl4.h> -#endif -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>"); -MODULE_LICENSE("GPL"); -#ifdef OPTi93X -MODULE_DESCRIPTION("OPTi93X"); -MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}"); -#else /* OPTi93X */ -#ifdef CS4231 -MODULE_DESCRIPTION("OPTi92X - CS4231"); -MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)}," - "{OPTi,82C925 (CS4231)}}"); -#else /* CS4231 */ -MODULE_DESCRIPTION("OPTi92X - AD1848"); -MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)}," - "{OPTi,82C925 (AD1848)}," - "{OAK,Mozart}}"); -#endif /* CS4231 */ -#endif /* OPTi93X */ - -static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ -static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -//static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp = true; /* Enable ISA PnP detection */ -#endif -static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */ -static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */ -static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */ -static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */ -static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */ -static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -#if defined(CS4231) || defined(OPTi93X) -static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ -#endif /* CS4231 || OPTi93X */ - -module_param(index, int, 0444); -MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard."); -module_param(id, charp, 0444); -MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard."); -//module_param(enable, bool, 0444); -//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard."); -#ifdef CONFIG_PNP -module_param(isapnp, bool, 0444); -MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard."); -#endif -module_param(port, long, 0444); -MODULE_PARM_DESC(port, "WSS port # for opti9xx driver."); -module_param(mpu_port, long, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver."); -module_param(fm_port, long, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver."); -module_param(irq, int, 0444); -MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver."); -module_param(mpu_irq, int, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver."); -module_param(dma1, int, 0444); -MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver."); -#if defined(CS4231) || defined(OPTi93X) -module_param(dma2, int, 0444); -MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver."); -#endif /* CS4231 || OPTi93X */ - -#define OPTi9XX_HW_82C928 1 -#define OPTi9XX_HW_82C929 2 -#define OPTi9XX_HW_82C924 3 -#define OPTi9XX_HW_82C925 4 -#define OPTi9XX_HW_82C930 5 -#define OPTi9XX_HW_82C931 6 -#define OPTi9XX_HW_82C933 7 -#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933 - -#define OPTi9XX_MC_REG(n) n - -#ifdef OPTi93X - -#define OPTi93X_STATUS 0x02 -#define OPTi93X_PORT(chip, r) ((chip)->port + OPTi93X_##r) - -#define OPTi93X_IRQ_PLAYBACK 0x04 -#define OPTi93X_IRQ_CAPTURE 0x08 - -#endif /* OPTi93X */ - -struct snd_opti9xx { - unsigned short hardware; - unsigned char password; - char name[7]; - - unsigned long mc_base; - struct resource *res_mc_base; - unsigned long mc_base_size; -#ifdef OPTi93X - unsigned long mc_indir_index; - unsigned long mc_indir_size; - struct resource *res_mc_indir; - struct snd_wss *codec; -#endif /* OPTi93X */ - unsigned long pwd_reg; - - spinlock_t lock; - - long wss_base; - int irq; -}; - -static int snd_opti9xx_pnp_is_probed; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_opti9xx_pnpids[] = { -#ifndef OPTi93X - /* OPTi 82C924 */ - { .id = "OPT0924", - .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } }, - .driver_data = 0x0924 }, - /* OPTi 82C925 */ - { .id = "OPT0925", - .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } }, - .driver_data = 0x0925 }, -#else - /* OPTi 82C931/3 */ - { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, - .driver_data = 0x0931 }, -#endif /* OPTi93X */ - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids); - -#endif /* CONFIG_PNP */ - -#ifdef OPTi93X -#define DEV_NAME "opti93x" -#else -#define DEV_NAME "opti92x" -#endif - -static char * snd_opti9xx_names[] = { - "unknown", - "82C928", "82C929", - "82C924", "82C925", - "82C930", "82C931", "82C933" -}; - - -static long __devinit snd_legacy_find_free_ioport(long *port_table, long size) -{ - while (*port_table != -1) { - if (request_region(*port_table, size, "ALSA test")) { - release_region(*port_table, size); - return *port_table; - } - port_table++; - } - return -1; -} - -static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, - unsigned short hardware) -{ - static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; - - chip->hardware = hardware; - strcpy(chip->name, snd_opti9xx_names[hardware]); - - spin_lock_init(&chip->lock); - - chip->irq = -1; - -#ifndef OPTi93X -#ifdef CONFIG_PNP - if (isapnp && chip->mc_base) - /* PnP resource gives the least 10 bits */ - chip->mc_base |= 0xc00; - else -#endif /* CONFIG_PNP */ - { - chip->mc_base = 0xf8c; - chip->mc_base_size = opti9xx_mc_size[hardware]; - } -#else - chip->mc_base_size = opti9xx_mc_size[hardware]; -#endif - - switch (hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; - chip->pwd_reg = 3; - break; - - case OPTi9XX_HW_82C924: - case OPTi9XX_HW_82C925: - chip->password = 0xe5; - chip->pwd_reg = 3; - break; -#else /* OPTi93X */ - - case OPTi9XX_HW_82C930: - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d; - if (!chip->mc_indir_index) { - chip->mc_indir_index = 0xe0e; - chip->mc_indir_size = 2; - } - chip->password = 0xe4; - chip->pwd_reg = 0; - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", hardware); - return -ENODEV; - } - return 0; -} - -static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, - unsigned char reg) -{ - unsigned long flags; - unsigned char retval = 0xff; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C924: - case OPTi9XX_HW_82C925: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - retval = inb(chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - retval = inb(chip->mc_base + reg); - break; -#else /* OPTi93X */ - - case OPTi9XX_HW_82C930: - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - outb(reg, chip->mc_indir_index); - outb(chip->password, chip->mc_base + chip->pwd_reg); - retval = inb(chip->mc_indir_index + 1); - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); - return retval; -} - -static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, - unsigned char value) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - - switch (chip->hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C924: - case OPTi9XX_HW_82C925: - if (reg > 7) { - outb(reg, chip->mc_base + 8); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(value, chip->mc_base + 9); - break; - } - - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - outb(value, chip->mc_base + reg); - break; -#else /* OPTi93X */ - - case OPTi9XX_HW_82C930: - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - outb(reg, chip->mc_indir_index); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(value, chip->mc_indir_index + 1); - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - } - - spin_unlock_irqrestore(&chip->lock, flags); -} - - -#define snd_opti9xx_write_mask(chip, reg, value, mask) \ - snd_opti9xx_write(chip, reg, \ - (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask))) - - -static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, - long port, - int irq, int dma1, int dma2, - long mpu_port, int mpu_irq) -{ - unsigned char wss_base_bits; - unsigned char irq_bits; - unsigned char dma_bits; - unsigned char mpu_port_bits = 0; - unsigned char mpu_irq_bits; - - switch (chip->hardware) { -#ifndef OPTi93X - case OPTi9XX_HW_82C924: - /* opti 929 mode (?), OPL3 clock output, audio enable */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); - /* enable wave audio */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); - - case OPTi9XX_HW_82C925: - /* enable WSS mode */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); - /* OPL3 FM synthesis */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); - /* disable Sound Blaster IRQ and DMA */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); -#ifdef CS4231 - /* cs4231/4248 fix enabled */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); -#else - /* cs4231/4248 fix disabled */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); -#endif /* CS4231 */ - break; - - case OPTi9XX_HW_82C928: - case OPTi9XX_HW_82C929: - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); - /* - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xa2, 0xae); - */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c); -#ifdef CS4231 - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); -#else - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); -#endif /* CS4231 */ - break; - -#else /* OPTi93X */ - case OPTi9XX_HW_82C931: - case OPTi9XX_HW_82C933: - /* - * The BTC 1817DW has QS1000 wavetable which is connected - * to the serial digital input of the OPTI931. - */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff); - /* - * This bit sets OPTI931 to automaticaly select FM - * or digital input signal. - */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); - case OPTi9XX_HW_82C930: /* FALL THROUGH */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 | - (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), - 0x34); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); - break; -#endif /* OPTi93X */ - - default: - snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware); - return -EINVAL; - } - - /* PnP resource says it decodes only 10 bits of address */ - switch (port & 0x3ff) { - case 0x130: - chip->wss_base = 0x530; - wss_base_bits = 0x00; - break; - case 0x204: - chip->wss_base = 0x604; - wss_base_bits = 0x03; - break; - case 0x280: - chip->wss_base = 0xe80; - wss_base_bits = 0x01; - break; - case 0x340: - chip->wss_base = 0xf40; - wss_base_bits = 0x02; - break; - default: - snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); - goto __skip_base; - } - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); - -__skip_base: - switch (irq) { -//#ifdef OPTi93X - case 5: - irq_bits = 0x05; - break; -//#endif /* OPTi93X */ - case 7: - irq_bits = 0x01; - break; - case 9: - irq_bits = 0x02; - break; - case 10: - irq_bits = 0x03; - break; - case 11: - irq_bits = 0x04; - break; - default: - snd_printk(KERN_WARNING "WSS irq # %d not valid\n", irq); - goto __skip_resources; - } - - switch (dma1) { - case 0: - dma_bits = 0x01; - break; - case 1: - dma_bits = 0x02; - break; - case 3: - dma_bits = 0x03; - break; - default: - snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", dma1); - goto __skip_resources; - } - -#if defined(CS4231) || defined(OPTi93X) - if (dma1 == dma2) { - snd_printk(KERN_ERR "don't want to share dmas\n"); - return -EBUSY; - } - - switch (dma2) { - case 0: - case 1: - break; - default: - snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", dma2); - goto __skip_resources; - } - dma_bits |= 0x04; -#endif /* CS4231 || OPTi93X */ - -#ifndef OPTi93X - outb(irq_bits << 3 | dma_bits, chip->wss_base); -#else /* OPTi93X */ - snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); -#endif /* OPTi93X */ - -__skip_resources: - if (chip->hardware > OPTi9XX_HW_82C928) { - switch (mpu_port) { - case 0: - case -1: - break; - case 0x300: - mpu_port_bits = 0x03; - break; - case 0x310: - mpu_port_bits = 0x02; - break; - case 0x320: - mpu_port_bits = 0x01; - break; - case 0x330: - mpu_port_bits = 0x00; - break; - default: - snd_printk(KERN_WARNING - "MPU-401 port 0x%lx not valid\n", mpu_port); - goto __skip_mpu; - } - - switch (mpu_irq) { - case 5: - mpu_irq_bits = 0x02; - break; - case 7: - mpu_irq_bits = 0x03; - break; - case 9: - mpu_irq_bits = 0x00; - break; - case 10: - mpu_irq_bits = 0x01; - break; - default: - snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n", - mpu_irq); - goto __skip_mpu; - } - - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), - (mpu_port <= 0) ? 0x00 : - 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, - 0xf8); - } -__skip_mpu: - - return 0; -} - -#ifdef OPTi93X - -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_step, -9300, 300, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_4bit_12db_max, -3300, 300, 0); - -static struct snd_kcontrol_new snd_opti93x_controls[] = { -WSS_DOUBLE("Master Playback Switch", 0, - OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Master Playback Volume", 0, - OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1, - db_scale_5bit_3db_step), -WSS_DOUBLE_TLV("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1, - db_scale_5bit), -WSS_DOUBLE_TLV("FM Playback Volume", 0, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Line Playback Volume", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE("Mic Playback Switch", 0, - OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Mic Playback Volume", 0, - OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE_TLV("CD Playback Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -WSS_DOUBLE("Aux Playback Switch", 0, - OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Aux Playback Volume", 0, - OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1, - db_scale_4bit_12db_max), -}; - -static int __devinit snd_opti93x_mixer(struct snd_wss *chip) -{ - struct snd_card *card; - unsigned int idx; - struct snd_ctl_elem_id id1, id2; - int err; - - if (snd_BUG_ON(!chip || !chip->pcm)) - return -EINVAL; - - card = chip->card; - - strcpy(card->mixername, chip->pcm->name); - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUX0 switch to CD */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "CD Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opti93x control\n"); - return err; - } - /* reassign AUX1 switch to FM */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "FM Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) { - snd_printk(KERN_ERR "Cannot rename opti93x control\n"); - return err; - } - /* remove AUX1 volume */ - strcpy(id1.name, "Aux Playback Volume"); id1.index = 1; - snd_ctl_remove_id(card, &id1); - - /* Replace WSS volume controls with OPTi93x volume controls */ - id1.index = 0; - for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) { - strcpy(id1.name, snd_opti93x_controls[idx].name); - snd_ctl_remove_id(card, &id1); - - err = snd_ctl_add(card, - snd_ctl_new1(&snd_opti93x_controls[idx], chip)); - if (err < 0) - return err; - } - return 0; -} - -static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) -{ - struct snd_opti9xx *chip = dev_id; - struct snd_wss *codec = chip->codec; - unsigned char status; - - if (!codec) - return IRQ_HANDLED; - - status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11)); - if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream) - snd_pcm_period_elapsed(codec->playback_substream); - if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) { - snd_wss_overrange(codec); - snd_pcm_period_elapsed(codec->capture_substream); - } - outb(0x00, OPTi93X_PORT(codec, STATUS)); - return IRQ_HANDLED; -} - -#endif /* OPTi93X */ - -static int __devinit snd_opti9xx_read_check(struct snd_opti9xx *chip) -{ - unsigned char value; -#ifdef OPTi93X - unsigned long flags; -#endif - - chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, - "OPTi9xx MC"); - if (chip->res_mc_base == NULL) - return -EBUSY; -#ifndef OPTi93X - value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)); - if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1))) - if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1))) - return 0; -#else /* OPTi93X */ - chip->res_mc_indir = request_region(chip->mc_indir_index, - chip->mc_indir_size, - "OPTi93x MC"); - if (chip->res_mc_indir == NULL) - return -EBUSY; - - spin_lock_irqsave(&chip->lock, flags); - outb(chip->password, chip->mc_base + chip->pwd_reg); - outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base); - spin_unlock_irqrestore(&chip->lock, flags); - - value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)); - snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value); - if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value) - return 0; - - release_and_free_resource(chip->res_mc_indir); - chip->res_mc_indir = NULL; -#endif /* OPTi93X */ - release_and_free_resource(chip->res_mc_base); - chip->res_mc_base = NULL; - - return -ENODEV; -} - -static int __devinit snd_card_opti9xx_detect(struct snd_card *card, - struct snd_opti9xx *chip) -{ - int i, err; - -#ifndef OPTi93X - for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) { -#else - for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) { -#endif - err = snd_opti9xx_init(chip, i); - if (err < 0) - return err; - - err = snd_opti9xx_read_check(chip); - if (err == 0) - return 1; -#ifdef OPTi93X - chip->mc_indir_index = 0; -#endif - } - return -ENODEV; -} - -#ifdef CONFIG_PNP -static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, - struct pnp_card_link *card, - const struct pnp_card_device_id *pid) -{ - struct pnp_dev *pdev; - int err; - struct pnp_dev *devmpu; -#ifndef OPTi93X - struct pnp_dev *devmc; -#endif - - pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (pdev == NULL) - return -EBUSY; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); - return err; - } - -#ifdef OPTi93X - port = pnp_port_start(pdev, 0) - 4; - fm_port = pnp_port_start(pdev, 1) + 8; - chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; - chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; -#else - devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); - if (devmc == NULL) - return -EBUSY; - - err = pnp_activate_dev(devmc); - if (err < 0) { - snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); - return err; - } - - port = pnp_port_start(pdev, 1); - fm_port = pnp_port_start(pdev, 2) + 8; - /* - * The MC(0) is never accessed and card does not - * include it in the PnP resource range. OPTI93x include it. - */ - chip->mc_base = pnp_port_start(devmc, 0) - 1; - chip->mc_base_size = pnp_port_len(devmc, 0) + 1; -#endif /* OPTi93X */ - irq = pnp_irq(pdev, 0); - dma1 = pnp_dma(pdev, 0); -#if defined(CS4231) || defined(OPTi93X) - dma2 = pnp_dma(pdev, 1); -#endif /* CS4231 || OPTi93X */ - - devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - - if (devmpu && mpu_port > 0) { - err = pnp_activate_dev(devmpu); - if (err < 0) { - snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); - mpu_port = -1; - } else { - mpu_port = pnp_port_start(devmpu, 0); - mpu_irq = pnp_irq(devmpu, 0); - } - } - return pid->driver_data; -} -#endif /* CONFIG_PNP */ - -static void snd_card_opti9xx_free(struct snd_card *card) -{ - struct snd_opti9xx *chip = card->private_data; - - if (chip) { -#ifdef OPTi93X - if (chip->irq > 0) { - disable_irq(chip->irq); - free_irq(chip->irq, chip); - } - release_and_free_resource(chip->res_mc_indir); -#endif - release_and_free_resource(chip->res_mc_base); - } -} - -static int __devinit snd_opti9xx_probe(struct snd_card *card) -{ - static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; - int error; - int xdma2; - struct snd_opti9xx *chip = card->private_data; - struct snd_wss *codec; -#ifdef CS4231 - struct snd_timer *timer; -#endif - struct snd_pcm *pcm; - struct snd_rawmidi *rmidi; - struct snd_hwdep *synth; - -#if defined(CS4231) || defined(OPTi93X) - xdma2 = dma2; -#else - xdma2 = -1; -#endif - - if (port == SNDRV_AUTO_PORT) { - port = snd_legacy_find_free_ioport(possible_ports, 4); - if (port < 0) { - snd_printk(KERN_ERR "unable to find a free WSS port\n"); - return -EBUSY; - } - } - error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2, - mpu_port, mpu_irq); - if (error) - return error; - - error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2, -#ifdef OPTi93X - WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, -#else - WSS_HW_DETECT, 0, -#endif - &codec); - if (error < 0) - return error; -#ifdef OPTi93X - chip->codec = codec; -#endif - error = snd_wss_pcm(codec, 0, &pcm); - if (error < 0) - return error; - error = snd_wss_mixer(codec); - if (error < 0) - return error; -#ifdef OPTi93X - error = snd_opti93x_mixer(codec); - if (error < 0) - return error; -#endif -#ifdef CS4231 - error = snd_wss_timer(codec, 0, &timer); - if (error < 0) - return error; -#endif -#ifdef OPTi93X - error = request_irq(irq, snd_opti93x_interrupt, - 0, DEV_NAME" - WSS", chip); - if (error < 0) { - snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); - return error; - } -#endif - chip->irq = irq; - strcpy(card->driver, chip->name); - sprintf(card->shortname, "OPTi %s", card->driver); -#if defined(CS4231) || defined(OPTi93X) - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, pcm->name, - chip->wss_base + 4, irq, dma1, xdma2); -#else - sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); -#endif /* CS4231 || OPTi93X */ - - if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) - rmidi = NULL; - else { - error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port, 0, mpu_irq, &rmidi); - if (error) - snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", - mpu_port); - } - - if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { - struct snd_opl3 *opl3 = NULL; -#ifndef OPTi93X - if (chip->hardware == OPTi9XX_HW_82C928 || - chip->hardware == OPTi9XX_HW_82C929 || - chip->hardware == OPTi9XX_HW_82C924) { - struct snd_opl4 *opl4; - /* assume we have an OPL4 */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), - 0x20, 0x20); - if (snd_opl4_create(card, fm_port, fm_port - 8, - 2, &opl3, &opl4) < 0) { - /* no luck, use OPL3 instead */ - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), - 0x00, 0x20); - } - } -#endif /* !OPTi93X */ - if (!opl3 && snd_opl3_create(card, fm_port, fm_port + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", - fm_port, fm_port + 4 - 1); - } - if (opl3) { - error = snd_opl3_hwdep_new(opl3, 0, 1, &synth); - if (error < 0) - return error; - } - } - - return snd_card_register(card); -} - -static int snd_opti9xx_card_new(struct snd_card **cardp) -{ - struct snd_card *card; - int err; - - err = snd_card_create(index, id, THIS_MODULE, - sizeof(struct snd_opti9xx), &card); - if (err < 0) - return err; - card->private_free = snd_card_opti9xx_free; - *cardp = card; - return 0; -} - -static int __devinit snd_opti9xx_isa_match(struct device *devptr, - unsigned int dev) -{ -#ifdef CONFIG_PNP - if (snd_opti9xx_pnp_is_probed) - return 0; - if (isapnp) - return 0; -#endif - return 1; -} - -static int __devinit snd_opti9xx_isa_probe(struct device *devptr, - unsigned int dev) -{ - struct snd_card *card; - int error; - static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1}; -#ifdef OPTi93X - static int possible_irqs[] = {5, 9, 10, 11, 7, -1}; -#else - static int possible_irqs[] = {9, 10, 11, 7, -1}; -#endif /* OPTi93X */ - static int possible_mpu_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dma1s[] = {3, 1, 0, -1}; -#if defined(CS4231) || defined(OPTi93X) - static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}}; -#endif /* CS4231 || OPTi93X */ - - if (mpu_port == SNDRV_AUTO_PORT) { - if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) { - snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); - return -EBUSY; - } - } - if (irq == SNDRV_AUTO_IRQ) { - if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (mpu_irq == SNDRV_AUTO_IRQ) { - if ((mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) { - snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); - return -EBUSY; - } - } - if (dma1 == SNDRV_AUTO_DMA) { - if ((dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) { - snd_printk(KERN_ERR "unable to find a free DMA1\n"); - return -EBUSY; - } - } -#if defined(CS4231) || defined(OPTi93X) - if (dma2 == SNDRV_AUTO_DMA) { - if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) { - snd_printk(KERN_ERR "unable to find a free DMA2\n"); - return -EBUSY; - } - } -#endif - - error = snd_opti9xx_card_new(&card); - if (error < 0) - return error; - - if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) { - snd_card_free(card); - return error; - } - snd_card_set_dev(card, devptr); - if ((error = snd_opti9xx_probe(card)) < 0) { - snd_card_free(card); - return error; - } - dev_set_drvdata(devptr, card); - return 0; -} - -static int __devexit snd_opti9xx_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -static struct isa_driver snd_opti9xx_driver = { - .match = snd_opti9xx_isa_match, - .probe = snd_opti9xx_isa_probe, - .remove = __devexit_p(snd_opti9xx_isa_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP -static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - struct snd_card *card; - int error, hw; - struct snd_opti9xx *chip; - - if (snd_opti9xx_pnp_is_probed) - return -EBUSY; - if (! isapnp) - return -ENODEV; - error = snd_opti9xx_card_new(&card); - if (error < 0) - return error; - chip = card->private_data; - - hw = snd_card_opti9xx_pnp(chip, pcard, pid); - switch (hw) { - case 0x0924: - hw = OPTi9XX_HW_82C924; - break; - case 0x0925: - hw = OPTi9XX_HW_82C925; - break; - case 0x0931: - hw = OPTi9XX_HW_82C931; - break; - default: - snd_card_free(card); - return -ENODEV; - } - - if ((error = snd_opti9xx_init(chip, hw))) { - snd_card_free(card); - return error; - } - error = snd_opti9xx_read_check(chip); - if (error) { - snd_printk(KERN_ERR "OPTI chip not found\n"); - snd_card_free(card); - return error; - } - snd_card_set_dev(card, &pcard->card->dev); - if ((error = snd_opti9xx_probe(card)) < 0) { - snd_card_free(card); - return error; - } - pnp_set_card_drvdata(pcard, card); - snd_opti9xx_pnp_is_probed = 1; - return 0; -} - -static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); - snd_opti9xx_pnp_is_probed = 0; -} - -static struct pnp_card_driver opti9xx_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "opti9xx", - .id_table = snd_opti9xx_pnpids, - .probe = snd_opti9xx_pnp_probe, - .remove = __devexit_p(snd_opti9xx_pnp_remove), -}; -#endif - -#ifdef OPTi93X -#define CHIP_NAME "82C93x" -#else -#define CHIP_NAME "82C92x" -#endif - -static int __init alsa_card_opti9xx_init(void) -{ -#ifdef CONFIG_PNP - pnp_register_card_driver(&opti9xx_pnpc_driver); - if (snd_opti9xx_pnp_is_probed) - return 0; - pnp_unregister_card_driver(&opti9xx_pnpc_driver); -#endif - return isa_register_driver(&snd_opti9xx_driver, 1); -} - -static void __exit alsa_card_opti9xx_exit(void) -{ - if (!snd_opti9xx_pnp_is_probed) { - isa_unregister_driver(&snd_opti9xx_driver); - return; - } -#ifdef CONFIG_PNP - pnp_unregister_card_driver(&opti9xx_pnpc_driver); -#endif -} - -module_init(alsa_card_opti9xx_init) -module_exit(alsa_card_opti9xx_exit) diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c b/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c deleted file mode 100644 index b17ab19f..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/opti92x-cs4231.c +++ /dev/null @@ -1,2 +0,0 @@ -#define CS4231 -#include "opti92x-ad1848.c" diff --git a/ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c b/ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c deleted file mode 100644 index bad9da52..00000000 --- a/ANDROID_3.4.5/sound/isa/opti9xx/opti93x.c +++ /dev/null @@ -1,3 +0,0 @@ -#define OPTi93X -#include "opti92x-ad1848.c" - diff --git a/ANDROID_3.4.5/sound/isa/sb/Makefile b/ANDROID_3.4.5/sound/isa/sb/Makefile deleted file mode 100644 index 08b9fb97..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-sb-common-objs := sb_common.o sb_mixer.o -snd-sb8-dsp-objs := sb8_main.o sb8_midi.o -snd-sb16-dsp-objs := sb16_main.o -snd-sb16-csp-objs := sb16_csp.o -snd-sb8-objs := sb8.o -snd-sb16-objs := sb16.o -snd-sbawe-objs := sbawe.o emu8000.o -snd-emu8000-synth-objs := emu8000_synth.o emu8000_callback.o emu8000_patch.o emu8000_pcm.o -snd-jazz16-objs := jazz16.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_SB_COMMON) += snd-sb-common.o -obj-$(CONFIG_SND_SB16_DSP) += snd-sb16-dsp.o -obj-$(CONFIG_SND_SB8_DSP) += snd-sb8-dsp.o -obj-$(CONFIG_SND_SB8) += snd-sb8.o -obj-$(CONFIG_SND_SB16) += snd-sb16.o -obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o -obj-$(CONFIG_SND_JAZZ16) += snd-jazz16.o -ifeq ($(CONFIG_SND_SB16_CSP),y) - obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o - obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o -endif -obj-$(CONFIG_SND_SBAWE_SEQ) += snd-emu8000-synth.o diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000.c b/ANDROID_3.4.5/sound/isa/sb/emu8000.c deleted file mode 100644 index 71887874..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000.c +++ /dev/null @@ -1,1163 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> - * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * Routines for control of EMU8000 chip - * - * 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/wait.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/export.h> -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/emu8000.h> -#include <sound/emu8000_reg.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <linux/init.h> -#include <sound/control.h> -#include <sound/initval.h> - -/* - * emu8000 register controls - */ - -/* - * The following routines read and write registers on the emu8000. They - * should always be called via the EMU8000*READ/WRITE macros and never - * directly. The macros handle the port number and command word. - */ -/* Write a word */ -void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - outw((unsigned short)val, port); /* Send data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); -} - -/* Read a word */ -unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg) -{ - unsigned short res; - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - res = inw(port); /* Read data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); - return res; -} - -/* Write a double word */ -void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - outw((unsigned short)val, port); /* Send low word of data */ - outw((unsigned short)(val>>16), port+2); /* Send high word of data */ - spin_unlock_irqrestore(&emu->reg_lock, flags); -} - -/* Read a double word */ -unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg) -{ - unsigned short low; - unsigned int res; - unsigned long flags; - spin_lock_irqsave(&emu->reg_lock, flags); - if (reg != emu->last_reg) { - outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */ - emu->last_reg = reg; - } - low = inw(port); /* Read low word of data */ - res = low + (inw(port+2) << 16); - spin_unlock_irqrestore(&emu->reg_lock, flags); - return res; -} - -/* - * Set up / close a channel to be used for DMA. - */ -/*exported*/ void -snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode) -{ - unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0; - mode &= EMU8000_RAM_MODE_MASK; - if (mode == EMU8000_RAM_CLOSE) { - EMU8000_CCCA_WRITE(emu, ch, 0); - EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F); - return; - } - EMU8000_DCYSUSV_WRITE(emu, ch, 0x80); - EMU8000_VTFT_WRITE(emu, ch, 0); - EMU8000_CVCF_WRITE(emu, ch, 0); - EMU8000_PTRX_WRITE(emu, ch, 0x40000000); - EMU8000_CPF_WRITE(emu, ch, 0x40000000); - EMU8000_PSST_WRITE(emu, ch, 0); - EMU8000_CSL_WRITE(emu, ch, 0); - if (mode == EMU8000_RAM_WRITE) /* DMA write */ - EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit); - else /* DMA read */ - EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit); -} - -/* - */ -static void __devinit -snd_emu8000_read_wait(struct snd_emu8000 *emu) -{ - while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } -} - -/* - */ -static void __devinit -snd_emu8000_write_wait(struct snd_emu8000 *emu) -{ - while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } -} - -/* - * detect a card at the given port - */ -static int __devinit -snd_emu8000_detect(struct snd_emu8000 *emu) -{ - /* Initialise */ - EMU8000_HWCF1_WRITE(emu, 0x0059); - EMU8000_HWCF2_WRITE(emu, 0x0020); - EMU8000_HWCF3_WRITE(emu, 0x0000); - /* Check for a recognisable emu8000 */ - /* - if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c) - return -ENODEV; - */ - if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058) - return -ENODEV; - if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003) - return -ENODEV; - - snd_printdd("EMU8000 [0x%lx]: Synth chip found\n", - emu->port1); - return 0; -} - - -/* - * intiailize audio channels - */ -static void __devinit -init_audio(struct snd_emu8000 *emu) -{ - int ch; - - /* turn off envelope engines */ - for (ch = 0; ch < EMU8000_CHANNELS; ch++) - EMU8000_DCYSUSV_WRITE(emu, ch, 0x80); - - /* reset all other parameters to zero */ - for (ch = 0; ch < EMU8000_CHANNELS; ch++) { - EMU8000_ENVVOL_WRITE(emu, ch, 0); - EMU8000_ENVVAL_WRITE(emu, ch, 0); - EMU8000_DCYSUS_WRITE(emu, ch, 0); - EMU8000_ATKHLDV_WRITE(emu, ch, 0); - EMU8000_LFO1VAL_WRITE(emu, ch, 0); - EMU8000_ATKHLD_WRITE(emu, ch, 0); - EMU8000_LFO2VAL_WRITE(emu, ch, 0); - EMU8000_IP_WRITE(emu, ch, 0); - EMU8000_IFATN_WRITE(emu, ch, 0); - EMU8000_PEFE_WRITE(emu, ch, 0); - EMU8000_FMMOD_WRITE(emu, ch, 0); - EMU8000_TREMFRQ_WRITE(emu, ch, 0); - EMU8000_FM2FRQ2_WRITE(emu, ch, 0); - EMU8000_PTRX_WRITE(emu, ch, 0); - EMU8000_VTFT_WRITE(emu, ch, 0); - EMU8000_PSST_WRITE(emu, ch, 0); - EMU8000_CSL_WRITE(emu, ch, 0); - EMU8000_CCCA_WRITE(emu, ch, 0); - } - - for (ch = 0; ch < EMU8000_CHANNELS; ch++) { - EMU8000_CPF_WRITE(emu, ch, 0); - EMU8000_CVCF_WRITE(emu, ch, 0); - } -} - - -/* - * initialize DMA address - */ -static void __devinit -init_dma(struct snd_emu8000 *emu) -{ - EMU8000_SMALR_WRITE(emu, 0); - EMU8000_SMARR_WRITE(emu, 0); - EMU8000_SMALW_WRITE(emu, 0); - EMU8000_SMARW_WRITE(emu, 0); -} - -/* - * initialization arrays; from ADIP - */ -static unsigned short init1[128] /*__devinitdata*/ = { - 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330, - 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730, - 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30, - 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30, - - 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330, - 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730, - 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30, - 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30, - - 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330, - 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730, - 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30, - 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30, - - 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330, - 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730, - 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30, - 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30, -}; - -static unsigned short init2[128] /*__devinitdata*/ = { - 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330, - 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730, - 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30, - 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30, - - 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330, - 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730, - 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30, - 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30, - - 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330, - 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730, - 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30, - 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30, - - 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330, - 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730, - 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30, - 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30, -}; - -static unsigned short init3[128] /*__devinitdata*/ = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287, - 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386, - 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F, - 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - -static unsigned short init4[128] /*__devinitdata*/ = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287, - 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386, - 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F, - 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - -/* send an initialization array - * Taken from the oss driver, not obvious from the doc how this - * is meant to work - */ -static void __devinit -send_array(struct snd_emu8000 *emu, unsigned short *data, int size) -{ - int i; - unsigned short *p; - - p = data; - for (i = 0; i < size; i++, p++) - EMU8000_INIT1_WRITE(emu, i, *p); - for (i = 0; i < size; i++, p++) - EMU8000_INIT2_WRITE(emu, i, *p); - for (i = 0; i < size; i++, p++) - EMU8000_INIT3_WRITE(emu, i, *p); - for (i = 0; i < size; i++, p++) - EMU8000_INIT4_WRITE(emu, i, *p); -} - - -/* - * Send initialization arrays to start up, this just follows the - * initialisation sequence in the adip. - */ -static void __devinit -init_arrays(struct snd_emu8000 *emu) -{ - send_array(emu, init1, ARRAY_SIZE(init1)/4); - - msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */ - send_array(emu, init2, ARRAY_SIZE(init2)/4); - send_array(emu, init3, ARRAY_SIZE(init3)/4); - - EMU8000_HWCF4_WRITE(emu, 0); - EMU8000_HWCF5_WRITE(emu, 0x83); - EMU8000_HWCF6_WRITE(emu, 0x8000); - - send_array(emu, init4, ARRAY_SIZE(init4)/4); -} - - -#define UNIQUE_ID1 0xa5b9 -#define UNIQUE_ID2 0x9d53 - -/* - * Size the onboard memory. - * This is written so as not to need arbitrary delays after the write. It - * seems that the only way to do this is to use the one channel and keep - * reallocating between read and write. - */ -static void __devinit -size_dram(struct snd_emu8000 *emu) -{ - int i, size, detected_size; - - if (emu->dram_checked) - return; - - size = 0; - detected_size = 0; - - /* write out a magic number */ - snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE); - snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ); - EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET); - EMU8000_SMLD_WRITE(emu, UNIQUE_ID1); - snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */ - - while (size < EMU8000_MAX_DRAM) { - - size += 512 * 1024; /* increment 512kbytes */ - - /* Write a unique data on the test address. - * if the address is out of range, the data is written on - * 0x200000(=EMU8000_DRAM_OFFSET). Then the id word is - * changed by this data. - */ - /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/ - EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1)); - EMU8000_SMLD_WRITE(emu, UNIQUE_ID2); - snd_emu8000_write_wait(emu); - - /* - * read the data on the just written DRAM address - * if not the same then we have reached the end of ram. - */ - /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/ - EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1)); - /*snd_emu8000_read_wait(emu);*/ - EMU8000_SMLD_READ(emu); /* discard stale data */ - if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2) - break; /* no memory at this address */ - - detected_size = size; - - snd_emu8000_read_wait(emu); - - /* - * If it is the same it could be that the address just - * wraps back to the beginning; so check to see if the - * initial value has been overwritten. - */ - EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET); - EMU8000_SMLD_READ(emu); /* discard stale data */ - if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1) - break; /* we must have wrapped around */ - snd_emu8000_read_wait(emu); - } - - /* wait until FULL bit in SMAxW register is false */ - for (i = 0; i < 10000; i++) { - if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0) - break; - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } - snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE); - snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE); - - snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n", - emu->port1, detected_size/1024); - - emu->mem_size = detected_size; - emu->dram_checked = 1; -} - - -/* - * Initiailise the FM section. You have to do this to use sample RAM - * and therefore lose 2 voices. - */ -/*exported*/ void -snd_emu8000_init_fm(struct snd_emu8000 *emu) -{ - unsigned long flags; - - /* Initialize the last two channels for DRAM refresh and producing - the reverb and chorus effects for Yamaha OPL-3 synthesizer */ - - /* 31: FM left channel, 0xffffe0-0xffffe8 */ - EMU8000_DCYSUSV_WRITE(emu, 30, 0x80); - EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */ - EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24)); - EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8)); - EMU8000_CPF_WRITE(emu, 30, 0); - EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3); - - /* 32: FM right channel, 0xfffff0-0xfffff8 */ - EMU8000_DCYSUSV_WRITE(emu, 31, 0x80); - EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */ - EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24)); - EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8)); - EMU8000_CPF_WRITE(emu, 31, 0x8000); - EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3); - - snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0); - - spin_lock_irqsave(&emu->reg_lock, flags); - while (!(inw(EMU8000_PTR(emu)) & 0x1000)) - ; - while ((inw(EMU8000_PTR(emu)) & 0x1000)) - ; - spin_unlock_irqrestore(&emu->reg_lock, flags); - snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828); - /* this is really odd part.. */ - outb(0x3C, EMU8000_PTR(emu)); - outb(0, EMU8000_DATA1(emu)); - - /* skew volume & cutoff */ - EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF); - EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF); -} - - -/* - * The main initialization routine. - */ -static void __devinit -snd_emu8000_init_hw(struct snd_emu8000 *emu) -{ - int i; - - emu->last_reg = 0xffff; /* reset the last register index */ - - /* initialize hardware configuration */ - EMU8000_HWCF1_WRITE(emu, 0x0059); - EMU8000_HWCF2_WRITE(emu, 0x0020); - - /* disable audio; this seems to reduce a clicking noise a bit.. */ - EMU8000_HWCF3_WRITE(emu, 0); - - /* initialize audio channels */ - init_audio(emu); - - /* initialize DMA */ - init_dma(emu); - - /* initialize init arrays */ - init_arrays(emu); - - /* - * Initialize the FM section of the AWE32, this is needed - * for DRAM refresh as well - */ - snd_emu8000_init_fm(emu); - - /* terminate all voices */ - for (i = 0; i < EMU8000_DRAM_VOICES; i++) - EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F); - - /* check DRAM memory size */ - size_dram(emu); - - /* enable audio */ - EMU8000_HWCF3_WRITE(emu, 0x4); - - /* set equzlier, chorus and reverb modes */ - snd_emu8000_update_equalizer(emu); - snd_emu8000_update_chorus_mode(emu); - snd_emu8000_update_reverb_mode(emu); -} - - -/*---------------------------------------------------------------- - * Bass/Treble Equalizer - *----------------------------------------------------------------*/ - -static unsigned short bass_parm[12][3] = { - {0xD26A, 0xD36A, 0x0000}, /* -12 dB */ - {0xD25B, 0xD35B, 0x0000}, /* -8 */ - {0xD24C, 0xD34C, 0x0000}, /* -6 */ - {0xD23D, 0xD33D, 0x0000}, /* -4 */ - {0xD21F, 0xD31F, 0x0000}, /* -2 */ - {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */ - {0xC219, 0xC319, 0x0001}, /* +2 */ - {0xC22A, 0xC32A, 0x0001}, /* +4 */ - {0xC24C, 0xC34C, 0x0001}, /* +6 */ - {0xC26E, 0xC36E, 0x0001}, /* +8 */ - {0xC248, 0xC384, 0x0002}, /* +10 */ - {0xC26A, 0xC36A, 0x0002}, /* +12 dB */ -}; - -static unsigned short treble_parm[12][9] = { - {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */ - {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */ - {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, - {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002} /* +12 dB */ -}; - - -/* - * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB] - */ -/*exported*/ void -snd_emu8000_update_equalizer(struct snd_emu8000 *emu) -{ - unsigned short w; - int bass = emu->bass_level; - int treble = emu->treble_level; - - if (bass < 0 || bass > 11 || treble < 0 || treble > 11) - return; - EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]); - EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]); - EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]); - EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]); - EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]); - EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]); - EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]); - EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]); - EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]); - EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]); - w = bass_parm[bass][2] + treble_parm[treble][8]; - EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262)); - EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362)); -} - - -/*---------------------------------------------------------------- - * Chorus mode control - *----------------------------------------------------------------*/ - -/* - * chorus mode parameters - */ -#define SNDRV_EMU8000_CHORUS_1 0 -#define SNDRV_EMU8000_CHORUS_2 1 -#define SNDRV_EMU8000_CHORUS_3 2 -#define SNDRV_EMU8000_CHORUS_4 3 -#define SNDRV_EMU8000_CHORUS_FEEDBACK 4 -#define SNDRV_EMU8000_CHORUS_FLANGER 5 -#define SNDRV_EMU8000_CHORUS_SHORTDELAY 6 -#define SNDRV_EMU8000_CHORUS_SHORTDELAY2 7 -#define SNDRV_EMU8000_CHORUS_PREDEFINED 8 -/* user can define chorus modes up to 32 */ -#define SNDRV_EMU8000_CHORUS_NUMBERS 32 - -struct soundfont_chorus_fx { - unsigned short feedback; /* feedback level (0xE600-0xE6FF) */ - unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */ - unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */ - unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */ - unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */ -}; - -/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */ -static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS]; -static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = { - {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */ - {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */ - {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */ - {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */ - {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */ - {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */ - {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */ - {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */ -}; - -/*exported*/ int -snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len) -{ - struct soundfont_chorus_fx rec; - if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) { - snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode); - return -EINVAL; - } - if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec))) - return -EFAULT; - chorus_parm[mode] = rec; - chorus_defined[mode] = 1; - return 0; -} - -/*exported*/ void -snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu) -{ - int effect = emu->chorus_mode; - if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS || - (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect])) - return; - EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback); - EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset); - EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth); - EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay); - EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq); - EMU8000_HWCF6_WRITE(emu, 0x8000); - EMU8000_HWCF7_WRITE(emu, 0x0000); -} - -/*---------------------------------------------------------------- - * Reverb mode control - *----------------------------------------------------------------*/ - -/* - * reverb mode parameters - */ -#define SNDRV_EMU8000_REVERB_ROOM1 0 -#define SNDRV_EMU8000_REVERB_ROOM2 1 -#define SNDRV_EMU8000_REVERB_ROOM3 2 -#define SNDRV_EMU8000_REVERB_HALL1 3 -#define SNDRV_EMU8000_REVERB_HALL2 4 -#define SNDRV_EMU8000_REVERB_PLATE 5 -#define SNDRV_EMU8000_REVERB_DELAY 6 -#define SNDRV_EMU8000_REVERB_PANNINGDELAY 7 -#define SNDRV_EMU8000_REVERB_PREDEFINED 8 -/* user can define reverb modes up to 32 */ -#define SNDRV_EMU8000_REVERB_NUMBERS 32 - -struct soundfont_reverb_fx { - unsigned short parms[28]; -}; - -/* reverb mode settings; write the following 28 data of 16 bit length - * on the corresponding ports in the reverb_cmds array - */ -static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS]; -static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = { -{{ /* room 1 */ - 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4, - 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 2 */ - 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 3 */ - 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B, - 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A, -}}, -{{ /* hall 1 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A, - 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529, -}}, -{{ /* hall 2 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254, - 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3, - 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* plate */ - 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234, - 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* delay */ - 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -{{ /* panning delay */ - 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -}; - -enum { DATA1, DATA2 }; -#define AWE_INIT1(c) EMU8000_CMD(2,c), DATA1 -#define AWE_INIT2(c) EMU8000_CMD(2,c), DATA2 -#define AWE_INIT3(c) EMU8000_CMD(3,c), DATA1 -#define AWE_INIT4(c) EMU8000_CMD(3,c), DATA2 - -static struct reverb_cmd_pair { - unsigned short cmd, port; -} reverb_cmds[28] = { - {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)}, - {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)}, - {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)}, - {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)}, - {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)}, - {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)}, - {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)}, -}; - -/*exported*/ int -snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len) -{ - struct soundfont_reverb_fx rec; - - if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) { - snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode); - return -EINVAL; - } - if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec))) - return -EFAULT; - reverb_parm[mode] = rec; - reverb_defined[mode] = 1; - return 0; -} - -/*exported*/ void -snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu) -{ - int effect = emu->reverb_mode; - int i; - - if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS || - (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect])) - return; - for (i = 0; i < 28; i++) { - int port; - if (reverb_cmds[i].port == DATA1) - port = EMU8000_DATA1(emu); - else - port = EMU8000_DATA2(emu); - snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]); - } -} - - -/*---------------------------------------------------------------- - * mixer interface - *----------------------------------------------------------------*/ - -/* - * bass/treble - */ -static int mixer_bass_treble_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 = 11; - return 0; -} - -static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level; - return 0; -} - -static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1; - - val1 = ucontrol->value.integer.value[0] % 12; - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - change = val1 != emu->treble_level; - emu->treble_level = val1; - } else { - change = val1 != emu->bass_level; - emu->bass_level = val1; - } - spin_unlock_irqrestore(&emu->control_lock, flags); - snd_emu8000_update_equalizer(emu); - return change; -} - -static struct snd_kcontrol_new mixer_bass_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Synth Tone Control - Bass", - .info = mixer_bass_treble_info, - .get = mixer_bass_treble_get, - .put = mixer_bass_treble_put, - .private_value = 0, -}; - -static struct snd_kcontrol_new mixer_treble_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Synth Tone Control - Treble", - .info = mixer_bass_treble_info, - .get = mixer_bass_treble_get, - .put = mixer_bass_treble_put, - .private_value = 1, -}; - -/* - * chorus/reverb mode - */ -static int mixer_chorus_reverb_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 = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1); - return 0; -} - -static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode; - return 0; -} - -static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1; - - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS; - change = val1 != emu->chorus_mode; - emu->chorus_mode = val1; - } else { - val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS; - change = val1 != emu->reverb_mode; - emu->reverb_mode = val1; - } - spin_unlock_irqrestore(&emu->control_lock, flags); - if (change) { - if (kcontrol->private_value) - snd_emu8000_update_chorus_mode(emu); - else - snd_emu8000_update_reverb_mode(emu); - } - return change; -} - -static struct snd_kcontrol_new mixer_chorus_mode_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Chorus Mode", - .info = mixer_chorus_reverb_info, - .get = mixer_chorus_reverb_get, - .put = mixer_chorus_reverb_put, - .private_value = 1, -}; - -static struct snd_kcontrol_new mixer_reverb_mode_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Reverb Mode", - .info = mixer_chorus_reverb_info, - .get = mixer_chorus_reverb_get, - .put = mixer_chorus_reverb_put, - .private_value = 0, -}; - -/* - * FM OPL3 chorus/reverb depth - */ -static int mixer_fm_depth_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 = 255; - return 0; -} - -static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth; - return 0; -} - -static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned short val1; - - val1 = ucontrol->value.integer.value[0] % 256; - spin_lock_irqsave(&emu->control_lock, flags); - if (kcontrol->private_value) { - change = val1 != emu->fm_chorus_depth; - emu->fm_chorus_depth = val1; - } else { - change = val1 != emu->fm_reverb_depth; - emu->fm_reverb_depth = val1; - } - spin_unlock_irqrestore(&emu->control_lock, flags); - if (change) - snd_emu8000_init_fm(emu); - return change; -} - -static struct snd_kcontrol_new mixer_fm_chorus_depth_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "FM Chorus Depth", - .info = mixer_fm_depth_info, - .get = mixer_fm_depth_get, - .put = mixer_fm_depth_put, - .private_value = 1, -}; - -static struct snd_kcontrol_new mixer_fm_reverb_depth_control = -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "FM Reverb Depth", - .info = mixer_fm_depth_info, - .get = mixer_fm_depth_get, - .put = mixer_fm_depth_put, - .private_value = 0, -}; - - -static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = { - &mixer_bass_control, - &mixer_treble_control, - &mixer_chorus_mode_control, - &mixer_reverb_mode_control, - &mixer_fm_chorus_depth_control, - &mixer_fm_reverb_depth_control, -}; - -/* - * create and attach mixer elements for WaveTable treble/bass controls - */ -static int __devinit -snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) -{ - int i, err = 0; - - if (snd_BUG_ON(!emu || !card)) - return -EINVAL; - - spin_lock_init(&emu->control_lock); - - memset(emu->controls, 0, sizeof(emu->controls)); - for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { - if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) - goto __error; - } - return 0; - -__error: - for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { - down_write(&card->controls_rwsem); - if (emu->controls[i]) - snd_ctl_remove(card, emu->controls[i]); - up_write(&card->controls_rwsem); - } - return err; -} - - -/* - * free resources - */ -static int snd_emu8000_free(struct snd_emu8000 *hw) -{ - release_and_free_resource(hw->res_port1); - release_and_free_resource(hw->res_port2); - release_and_free_resource(hw->res_port3); - kfree(hw); - return 0; -} - -/* - */ -static int snd_emu8000_dev_free(struct snd_device *device) -{ - struct snd_emu8000 *hw = device->device_data; - return snd_emu8000_free(hw); -} - -/* - * initialize and register emu8000 synth device. - */ -int __devinit -snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, - struct snd_seq_device **awe_ret) -{ - struct snd_seq_device *awe; - struct snd_emu8000 *hw; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_emu8000_dev_free, - }; - - if (awe_ret) - *awe_ret = NULL; - - if (seq_ports <= 0) - return 0; - - hw = kzalloc(sizeof(*hw), GFP_KERNEL); - if (hw == NULL) - return -ENOMEM; - spin_lock_init(&hw->reg_lock); - hw->index = index; - hw->port1 = port; - hw->port2 = port + 0x400; - hw->port3 = port + 0x800; - if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) || - !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) || - !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) { - snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3); - snd_emu8000_free(hw); - return -EBUSY; - } - hw->mem_size = 0; - hw->card = card; - hw->seq_ports = seq_ports; - hw->bass_level = 5; - hw->treble_level = 9; - hw->chorus_mode = 2; - hw->reverb_mode = 4; - hw->fm_chorus_depth = 0; - hw->fm_reverb_depth = 0; - - if (snd_emu8000_detect(hw) < 0) { - snd_emu8000_free(hw); - return -ENODEV; - } - - snd_emu8000_init_hw(hw); - if ((err = snd_emu8000_create_mixer(card, hw)) < 0) { - snd_emu8000_free(hw); - return err; - } - - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) { - snd_emu8000_free(hw); - return err; - } -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) - if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000, - sizeof(struct snd_emu8000*), &awe) >= 0) { - strcpy(awe->name, "EMU-8000"); - *(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw; - } -#else - awe = NULL; -#endif - if (awe_ret) - *awe_ret = awe; - - return 0; -} - - -/* - * exported stuff - */ - -EXPORT_SYMBOL(snd_emu8000_poke); -EXPORT_SYMBOL(snd_emu8000_peek); -EXPORT_SYMBOL(snd_emu8000_poke_dw); -EXPORT_SYMBOL(snd_emu8000_peek_dw); -EXPORT_SYMBOL(snd_emu8000_dma_chan); -EXPORT_SYMBOL(snd_emu8000_init_fm); -EXPORT_SYMBOL(snd_emu8000_load_chorus_fx); -EXPORT_SYMBOL(snd_emu8000_load_reverb_fx); -EXPORT_SYMBOL(snd_emu8000_update_chorus_mode); -EXPORT_SYMBOL(snd_emu8000_update_reverb_mode); -EXPORT_SYMBOL(snd_emu8000_update_equalizer); diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c deleted file mode 100644 index 344b4355..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_callback.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * synth callback routines for the emu8000 (AWE32/64) - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (C) 1999-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 "emu8000_local.h" -#include <linux/export.h> -#include <sound/asoundef.h> - -/* - * prototypes - */ -static struct snd_emux_voice *get_voice(struct snd_emux *emu, - 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 reset_voice(struct snd_emux *emu, int ch); -static void terminate_voice(struct snd_emux_voice *vp); -static void sysex(struct snd_emux *emu, char *buf, int len, int parsed, - struct snd_midi_channel_set *chset); -#ifdef CONFIG_SND_SEQUENCER_OSS -static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2); -#endif -static int load_fx(struct snd_emux *emu, int type, int mode, - const void __user *buf, long len); - -static void set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp); -static void snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int ch); - -/* - * 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 emu8000_ops = { - .owner = THIS_MODULE, - .get_voice = get_voice, - .prepare = start_voice, - .trigger = trigger_voice, - .release = release_voice, - .update = update_voice, - .terminate = terminate_voice, - .reset = reset_voice, - .sample_new = snd_emu8000_sample_new, - .sample_free = snd_emu8000_sample_free, - .sample_reset = snd_emu8000_sample_reset, - .load_fx = load_fx, - .sysex = sysex, -#ifdef CONFIG_SND_SEQUENCER_OSS - .oss_ioctl = oss_ioctl, -#endif -}; - -void -snd_emu8000_ops_setup(struct snd_emu8000 *hw) -{ - hw->emu->ops = emu8000_ops; -} - - - -/* - * Terminate a voice - */ -static void -release_voice(struct snd_emux_voice *vp) -{ - int dcysusv; - struct snd_emu8000 *hw; - - hw = vp->hw; - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease; - EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv); - dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease; - EMU8000_DCYSUSV_WRITE(hw, vp->ch, dcysusv); -} - - -/* - */ -static void -terminate_voice(struct snd_emux_voice *vp) -{ - struct snd_emu8000 *hw; - - hw = vp->hw; - EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F); -} - - -/* - */ -static void -update_voice(struct snd_emux_voice *vp, int update) -{ - struct snd_emu8000 *hw; - - hw = vp->hw; - if (update & SNDRV_EMUX_UPDATE_VOLUME) - set_volume(hw, vp); - if (update & SNDRV_EMUX_UPDATE_PITCH) - set_pitch(hw, vp); - if ((update & SNDRV_EMUX_UPDATE_PAN) && - vp->port->ctrls[EMUX_MD_REALTIME_PAN]) - set_pan(hw, vp); - if (update & SNDRV_EMUX_UPDATE_FMMOD) - set_fmmod(hw, vp); - if (update & SNDRV_EMUX_UPDATE_TREMFREQ) - set_tremfreq(hw, vp); - if (update & SNDRV_EMUX_UPDATE_FM2FRQ2) - set_fm2frq2(hw, vp); - if (update & SNDRV_EMUX_UPDATE_Q) - set_filterQ(hw, vp); -} - - -/* - * Find a channel (voice) within the EMU that is not in use or at least - * less in use than other channels. Always returns a valid pointer - * no matter what. If there is a real shortage of voices then one - * will be cut. Such is life. - * - * The channel index (vp->ch) must be initialized in this routine. - * In Emu8k, it is identical with the array index. - */ -static struct snd_emux_voice * -get_voice(struct snd_emux *emu, struct snd_emux_port *port) -{ - int i; - struct snd_emux_voice *vp; - struct snd_emu8000 *hw; - - /* what we are looking for, in order of preference */ - enum { - OFF=0, RELEASED, PLAYING, END - }; - - /* Keeps track of what we are finding */ - struct best { - unsigned int time; - int voice; - } best[END]; - struct best *bp; - - hw = emu->hw; - - for (i = 0; i < 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. - */ - for (i = 0; i < emu->max_voices; i++) { - int state, val; - - vp = &emu->voices[i]; - state = vp->state; - - if (state == SNDRV_EMUX_ST_OFF) - bp = best + OFF; - else if (state == SNDRV_EMUX_ST_RELEASED || - state == SNDRV_EMUX_ST_PENDING) { - bp = best + RELEASED; - val = (EMU8000_CVCF_READ(hw, vp->ch) >> 16) & 0xffff; - if (! val) - bp = best + OFF; - } - else if (state & SNDRV_EMUX_ST_ON) - bp = best + PLAYING; - else - continue; - - /* check if sample is finished playing (non-looping only) */ - if (state != SNDRV_EMUX_ST_OFF && - (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) { - val = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff; - if (val >= vp->reg.loopstart) - bp = best + OFF; - } - - if (vp->time < bp->time) { - bp->time = vp->time; - bp->voice = i; - } - } - - for (i = 0; i < END; i++) { - if (best[i].voice >= 0) { - vp = &emu->voices[best[i].voice]; - vp->ch = best[i].voice; - return vp; - } - } - - /* not found */ - return NULL; -} - -/* - */ -static int -start_voice(struct snd_emux_voice *vp) -{ - unsigned int temp; - int ch; - int addr; - struct snd_midi_channel *chan; - struct snd_emu8000 *hw; - - hw = vp->hw; - ch = vp->ch; - chan = vp->chan; - - /* channel to be silent and idle */ - EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080); - EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF); - EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF); - EMU8000_PTRX_WRITE(hw, ch, 0); - EMU8000_CPF_WRITE(hw, ch, 0); - - /* set pitch offset */ - set_pitch(hw, vp); - - /* set envelope parameters */ - EMU8000_ENVVAL_WRITE(hw, ch, vp->reg.parm.moddelay); - EMU8000_ATKHLD_WRITE(hw, ch, vp->reg.parm.modatkhld); - EMU8000_DCYSUS_WRITE(hw, ch, vp->reg.parm.moddcysus); - EMU8000_ENVVOL_WRITE(hw, ch, vp->reg.parm.voldelay); - EMU8000_ATKHLDV_WRITE(hw, ch, vp->reg.parm.volatkhld); - /* decay/sustain parameter for volume envelope is used - for triggerg the voice */ - - /* cutoff and volume */ - set_volume(hw, vp); - - /* modulation envelope heights */ - EMU8000_PEFE_WRITE(hw, ch, vp->reg.parm.pefe); - - /* lfo1/2 delay */ - EMU8000_LFO1VAL_WRITE(hw, ch, vp->reg.parm.lfo1delay); - EMU8000_LFO2VAL_WRITE(hw, ch, vp->reg.parm.lfo2delay); - - /* lfo1 pitch & cutoff shift */ - set_fmmod(hw, vp); - /* lfo1 volume & freq */ - set_tremfreq(hw, vp); - /* lfo2 pitch & freq */ - set_fm2frq2(hw, vp); - /* pan & loop start */ - set_pan(hw, vp); - - /* chorus & loop end (chorus 8bit, MSB) */ - addr = vp->reg.loopend - 1; - temp = vp->reg.parm.chorus; - temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - temp = (temp <<24) | (unsigned int)addr; - EMU8000_CSL_WRITE(hw, ch, temp); - - /* Q & current address (Q 4bit value, MSB) */ - addr = vp->reg.start - 1; - temp = vp->reg.parm.filterQ; - temp = (temp<<28) | (unsigned int)addr; - EMU8000_CCCA_WRITE(hw, ch, temp); - - /* clear unknown registers */ - EMU8000_00A0_WRITE(hw, ch, 0); - EMU8000_0080_WRITE(hw, ch, 0); - - /* reset volume */ - temp = vp->vtarget << 16; - EMU8000_VTFT_WRITE(hw, ch, temp | vp->ftarget); - EMU8000_CVCF_WRITE(hw, ch, temp | 0xff00); - - return 0; -} - -/* - * Start envelope - */ -static void -trigger_voice(struct snd_emux_voice *vp) -{ - int ch = vp->ch; - unsigned int temp; - struct snd_emu8000 *hw; - - hw = vp->hw; - - /* set reverb and pitch target */ - temp = vp->reg.parm.reverb; - temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10; - LIMITMAX(temp, 255); - temp = (temp << 8) | (vp->ptarget << 16) | vp->aaux; - EMU8000_PTRX_WRITE(hw, ch, temp); - EMU8000_CPF_WRITE(hw, ch, vp->ptarget << 16); - EMU8000_DCYSUSV_WRITE(hw, ch, vp->reg.parm.voldcysus); -} - -/* - * reset voice parameters - */ -static void -reset_voice(struct snd_emux *emu, int ch) -{ - struct snd_emu8000 *hw; - - hw = emu->hw; - EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F); - snd_emu8000_tweak_voice(hw, ch); -} - -/* - * Set the pitch of a possibly playing note. - */ -static void -set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - EMU8000_IP_WRITE(hw, vp->ch, vp->apitch); -} - -/* - * Set the volume of a possibly already playing note - */ -static void -set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - int ifatn; - - ifatn = (unsigned char)vp->acutoff; - ifatn = (ifatn << 8); - ifatn |= (unsigned char)vp->avol; - EMU8000_IFATN_WRITE(hw, vp->ch, ifatn); -} - -/* - * Set pan and loop start address. - */ -static void -set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - unsigned int temp; - - temp = ((unsigned int)vp->apan<<24) | ((unsigned int)vp->reg.loopstart - 1); - EMU8000_PSST_WRITE(hw, vp->ch, temp); -} - -#define MOD_SENSE 18 - -static void -set_fmmod(struct snd_emu8000 *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; - EMU8000_FMMOD_WRITE(hw, vp->ch, fmmod); -} - -/* set tremolo (lfo1) volume & frequency */ -static void -set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - EMU8000_TREMFRQ_WRITE(hw, vp->ch, vp->reg.parm.tremfrq); -} - -/* set lfo2 pitch & frequency */ -static void -set_fm2frq2(struct snd_emu8000 *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; - EMU8000_FM2FRQ2_WRITE(hw, vp->ch, fm2frq2); -} - -/* set filterQ */ -static void -set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp) -{ - unsigned int addr; - addr = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff; - addr |= (vp->reg.parm.filterQ << 28); - EMU8000_CCCA_WRITE(hw, vp->ch, addr); -} - -/* - * set the envelope & LFO parameters to the default values - */ -static void -snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int i) -{ - /* set all mod/vol envelope shape to minimum */ - EMU8000_ENVVOL_WRITE(emu, i, 0x8000); - EMU8000_ENVVAL_WRITE(emu, i, 0x8000); - EMU8000_DCYSUS_WRITE(emu, i, 0x7F7F); - EMU8000_ATKHLDV_WRITE(emu, i, 0x7F7F); - EMU8000_ATKHLD_WRITE(emu, i, 0x7F7F); - EMU8000_PEFE_WRITE(emu, i, 0); /* mod envelope height to zero */ - EMU8000_LFO1VAL_WRITE(emu, i, 0x8000); /* no delay for LFO1 */ - EMU8000_LFO2VAL_WRITE(emu, i, 0x8000); - EMU8000_IP_WRITE(emu, i, 0xE000); /* no pitch shift */ - EMU8000_IFATN_WRITE(emu, i, 0xFF00); /* volume to minimum */ - EMU8000_FMMOD_WRITE(emu, i, 0); - EMU8000_TREMFRQ_WRITE(emu, i, 0); - EMU8000_FM2FRQ2_WRITE(emu, i, 0); -} - -/* - * sysex callback - */ -static void -sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_channel_set *chset) -{ - struct snd_emu8000 *hw; - - hw = emu->hw; - - switch (parsed) { - case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE: - hw->chorus_mode = chset->gs_chorus_mode; - snd_emu8000_update_chorus_mode(hw); - break; - - case SNDRV_MIDI_SYSEX_GS_REVERB_MODE: - hw->reverb_mode = chset->gs_reverb_mode; - snd_emu8000_update_reverb_mode(hw); - break; - } -} - - -#ifdef CONFIG_SND_SEQUENCER_OSS -/* - * OSS ioctl callback - */ -static int -oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2) -{ - struct snd_emu8000 *hw; - - hw = emu->hw; - - switch (cmd) { - case _EMUX_OSS_REVERB_MODE: - hw->reverb_mode = p1; - snd_emu8000_update_reverb_mode(hw); - break; - - case _EMUX_OSS_CHORUS_MODE: - hw->chorus_mode = p1; - snd_emu8000_update_chorus_mode(hw); - break; - - case _EMUX_OSS_INITIALIZE_CHIP: - /* snd_emu8000_init(hw); */ /*ignored*/ - break; - - case _EMUX_OSS_EQUALIZER: - hw->bass_level = p1; - hw->treble_level = p2; - snd_emu8000_update_equalizer(hw); - break; - } - return 0; -} -#endif - - -/* - * additional patch keys - */ - -#define SNDRV_EMU8000_LOAD_CHORUS_FX 0x10 /* optarg=mode */ -#define SNDRV_EMU8000_LOAD_REVERB_FX 0x11 /* optarg=mode */ - - -/* - * callback routine - */ - -static int -load_fx(struct snd_emux *emu, int type, int mode, const void __user *buf, long len) -{ - struct snd_emu8000 *hw; - hw = emu->hw; - - /* skip header */ - buf += 16; - len -= 16; - - switch (type) { - case SNDRV_EMU8000_LOAD_CHORUS_FX: - return snd_emu8000_load_chorus_fx(hw, mode, buf, len); - case SNDRV_EMU8000_LOAD_REVERB_FX: - return snd_emu8000_load_reverb_fx(hw, mode, buf, len); - } - return -EINVAL; -} - diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_local.h b/ANDROID_3.4.5/sound/isa/sb/emu8000_local.h deleted file mode 100644 index 7e87c349..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_local.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __EMU8000_LOCAL_H -#define __EMU8000_LOCAL_H -/* - * Local defininitons for the emu8000 (AWE32/64) - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (C) 1999-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/wait.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <sound/core.h> -#include <sound/emu8000.h> -#include <sound/emu8000_reg.h> - -/* emu8000_patch.c */ -int snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *data, long count); -int snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr); -void snd_emu8000_sample_reset(struct snd_emux *rec); - -/* emu8000_callback.c */ -void snd_emu8000_ops_setup(struct snd_emu8000 *emu); - -/* emu8000_pcm.c */ -int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index); - -#endif /* __EMU8000_LOCAL_H */ diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c deleted file mode 100644 index c99c6078..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_patch.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Patch routines for the emu8000 (AWE32/64) - * - * Copyright (C) 1999 Steve Ratcliffe - * Copyright (C) 1999-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 "emu8000_local.h" -#include <asm/uaccess.h> -#include <linux/moduleparam.h> - -static int emu8000_reset_addr; -module_param(emu8000_reset_addr, int, 0444); -MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)"); - - -/* - * Open up channels. - */ -static int -snd_emu8000_open_dma(struct snd_emu8000 *emu, int write) -{ - int i; - - /* reserve all 30 voices for loading */ - for (i = 0; i < EMU8000_DRAM_VOICES; i++) { - snd_emux_lock_voice(emu->emu, i); - snd_emu8000_dma_chan(emu, i, write); - } - - /* assign voice 31 and 32 to ROM */ - EMU8000_VTFT_WRITE(emu, 30, 0); - EMU8000_PSST_WRITE(emu, 30, 0x1d8); - EMU8000_CSL_WRITE(emu, 30, 0x1e0); - EMU8000_CCCA_WRITE(emu, 30, 0x1d8); - EMU8000_VTFT_WRITE(emu, 31, 0); - EMU8000_PSST_WRITE(emu, 31, 0x1d8); - EMU8000_CSL_WRITE(emu, 31, 0x1e0); - EMU8000_CCCA_WRITE(emu, 31, 0x1d8); - - return 0; -} - -/* - * Close all dram channels. - */ -static void -snd_emu8000_close_dma(struct snd_emu8000 *emu) -{ - int i; - - for (i = 0; i < EMU8000_DRAM_VOICES; i++) { - snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE); - snd_emux_unlock_voice(emu->emu, i); - } -} - -/* - */ - -#define BLANK_LOOP_START 4 -#define BLANK_LOOP_END 8 -#define BLANK_LOOP_SIZE 12 -#define BLANK_HEAD_SIZE 48 - -/* - * Read a word from userland, taking care of conversions from - * 8bit samples etc. - */ -static unsigned short -read_word(const void __user *buf, int offset, int mode) -{ - unsigned short c; - if (mode & SNDRV_SFNT_SAMPLE_8BITS) { - unsigned char cc; - get_user(cc, (unsigned char __user *)buf + offset); - c = cc << 8; /* convert 8bit -> 16bit */ - } else { -#ifdef SNDRV_LITTLE_ENDIAN - get_user(c, (unsigned short __user *)buf + offset); -#else - unsigned short cc; - get_user(cc, (unsigned short __user *)buf + offset); - c = swab16(cc); -#endif - } - if (mode & SNDRV_SFNT_SAMPLE_UNSIGNED) - c ^= 0x8000; /* unsigned -> signed */ - return c; -} - -/* - */ -static void -snd_emu8000_write_wait(struct snd_emu8000 *emu) -{ - while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } -} - -/* - * write sample word data - * - * You should not have to keep resetting the address each time - * as the chip is supposed to step on the next address automatically. - * It mostly does, but during writes of some samples at random it - * completely loses words (every one in 16 roughly but with no - * obvious pattern). - * - * This is therefore much slower than need be, but is at least - * working. - */ -static inline void -write_word(struct snd_emu8000 *emu, int *offset, unsigned short data) -{ - if (emu8000_reset_addr) { - if (emu8000_reset_addr > 1) - snd_emu8000_write_wait(emu); - EMU8000_SMALW_WRITE(emu, *offset); - } - EMU8000_SMLD_WRITE(emu, data); - *offset += 1; -} - -/* - * Write the sample to EMU800 memory. This routine is invoked out of - * the generic soundfont routines as a callback. - */ -int -snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr, - const void __user *data, long count) -{ - int i; - int rc; - int offset; - int truesize; - int dram_offset, dram_start; - struct snd_emu8000 *emu; - - emu = rec->hw; - if (snd_BUG_ON(!sp)) - return -EINVAL; - - if (sp->v.size == 0) - return 0; - - /* 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; - if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) - truesize += sp->v.loopend - sp->v.loopstart; - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) - truesize += BLANK_LOOP_SIZE; - - sp->block = snd_util_mem_alloc(hdr, truesize * 2); - if (sp->block == NULL) { - /*snd_printd("EMU8000: out of memory\n");*/ - /* not ENOMEM (for compatibility) */ - return -ENOSPC; - } - - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) { - if (!access_ok(VERIFY_READ, data, sp->v.size)) - return -EFAULT; - } else { - if (!access_ok(VERIFY_READ, data, sp->v.size * 2)) - return -EFAULT; - } - - /* 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; - - /* dram position (in word) -- mem_offset is byte */ - dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1); - dram_start = dram_offset; - - /* set the total size (store onto obsolete checksum value) */ - sp->v.truesize = truesize * 2; /* in bytes */ - - snd_emux_terminate_all(emu->emu); - if ((rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE)) != 0) - return rc; - - /* Set the address to start writing at */ - snd_emu8000_write_wait(emu); - EMU8000_SMALW_WRITE(emu, dram_offset); - - /*snd_emu8000_init_fm(emu);*/ - -#if 0 - /* first block - write 48 samples for silence */ - if (! sp->block->offset) { - for (i = 0; i < BLANK_HEAD_SIZE; i++) { - write_word(emu, &dram_offset, 0); - } - } -#endif - - offset = 0; - for (i = 0; i < sp->v.size; i++) { - unsigned short s; - - s = read_word(data, offset, sp->v.mode_flags); - offset++; - write_word(emu, &dram_offset, s); - - /* we may take too long time in this loop. - * so give controls back to kernel if needed. - */ - cond_resched(); - - if (i == sp->v.loopend && - (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))) - { - int looplen = sp->v.loopend - sp->v.loopstart; - int k; - - /* copy reverse loop */ - for (k = 1; k <= looplen; k++) { - s = read_word(data, offset - k, sp->v.mode_flags); - write_word(emu, &dram_offset, s); - } - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) { - sp->v.loopend += looplen; - } else { - sp->v.loopstart += looplen; - sp->v.loopend += looplen; - } - sp->v.end += looplen; - } - } - - /* if no blank loop is attached in the sample, add it */ - if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) { - for (i = 0; i < BLANK_LOOP_SIZE; i++) { - write_word(emu, &dram_offset, 0); - } - 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; - } - } - - /* add dram offset */ - sp->v.start += dram_start; - sp->v.end += dram_start; - sp->v.loopstart += dram_start; - sp->v.loopend += dram_start; - - snd_emu8000_close_dma(emu); - snd_emu8000_init_fm(emu); - - return 0; -} - -/* - * free a sample block - */ -int -snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp, - struct snd_util_memhdr *hdr) -{ - if (sp->block) { - snd_util_mem_free(hdr, sp->block); - sp->block = NULL; - } - return 0; -} - - -/* - * sample_reset callback - terminate voices - */ -void -snd_emu8000_sample_reset(struct snd_emux *rec) -{ - snd_emux_terminate_all(rec); -} diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c deleted file mode 100644 index 2f85c66f..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_pcm.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * pcm emulation on emu8000 wavetable - * - * Copyright (C) 2002 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 "emu8000_local.h" -#include <linux/init.h> -#include <linux/slab.h> -#include <sound/initval.h> -#include <sound/pcm.h> - -/* - * define the following if you want to use this pcm with non-interleaved mode - */ -/* #define USE_NONINTERLEAVE */ - -/* NOTE: for using the non-interleaved mode with alsa-lib, you have to set - * mmap_emulation flag to 1 in your .asoundrc, such like - * - * pcm.emu8k { - * type plug - * slave.pcm { - * type hw - * card 0 - * device 1 - * mmap_emulation 1 - * } - * } - * - * besides, for the time being, the non-interleaved mode doesn't work well on - * alsa-lib... - */ - - -struct snd_emu8k_pcm { - struct snd_emu8000 *emu; - struct snd_pcm_substream *substream; - - unsigned int allocated_bytes; - struct snd_util_memblk *block; - unsigned int offset; - unsigned int buf_size; - unsigned int period_size; - unsigned int loop_start[2]; - unsigned int pitch; - int panning[2]; - int last_ptr; - int period_pos; - int voices; - unsigned int dram_opened: 1; - unsigned int running: 1; - unsigned int timer_running: 1; - struct timer_list timer; - spinlock_t timer_lock; -}; - -#define LOOP_BLANK_SIZE 8 - - -/* - * open up channels for the simultaneous data transfer and playback - */ -static int -emu8k_open_dram_for_pcm(struct snd_emu8000 *emu, int channels) -{ - int i; - - /* reserve up to 2 voices for playback */ - snd_emux_lock_voice(emu->emu, 0); - if (channels > 1) - snd_emux_lock_voice(emu->emu, 1); - - /* reserve 28 voices for loading */ - for (i = channels + 1; i < EMU8000_DRAM_VOICES; i++) { - unsigned int mode = EMU8000_RAM_WRITE; - snd_emux_lock_voice(emu->emu, i); -#ifndef USE_NONINTERLEAVE - if (channels > 1 && (i & 1) != 0) - mode |= EMU8000_RAM_RIGHT; -#endif - snd_emu8000_dma_chan(emu, i, mode); - } - - /* assign voice 31 and 32 to ROM */ - EMU8000_VTFT_WRITE(emu, 30, 0); - EMU8000_PSST_WRITE(emu, 30, 0x1d8); - EMU8000_CSL_WRITE(emu, 30, 0x1e0); - EMU8000_CCCA_WRITE(emu, 30, 0x1d8); - EMU8000_VTFT_WRITE(emu, 31, 0); - EMU8000_PSST_WRITE(emu, 31, 0x1d8); - EMU8000_CSL_WRITE(emu, 31, 0x1e0); - EMU8000_CCCA_WRITE(emu, 31, 0x1d8); - - return 0; -} - -/* - */ -static void -snd_emu8000_write_wait(struct snd_emu8000 *emu, int can_schedule) -{ - while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { - if (can_schedule) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - } - } -} - -/* - * close all channels - */ -static void -emu8k_close_dram(struct snd_emu8000 *emu) -{ - int i; - - for (i = 0; i < 2; i++) - snd_emux_unlock_voice(emu->emu, i); - for (; i < EMU8000_DRAM_VOICES; i++) { - snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE); - snd_emux_unlock_voice(emu->emu, i); - } -} - -/* - * convert Hz to AWE32 rate offset (see emux/soundfont.c) - */ - -#define OFFSET_SAMPLERATE 1011119 /* base = 44100 */ -#define SAMPLERATE_RATIO 4096 - -static int calc_rate_offset(int hz) -{ - return snd_sf_linear_to_log(hz, OFFSET_SAMPLERATE, SAMPLERATE_RATIO); -} - - -/* - */ - -static struct snd_pcm_hardware emu8k_pcm_hw = { -#ifdef USE_NONINTERLEAVE - .info = SNDRV_PCM_INFO_NONINTERLEAVED, -#else - .info = SNDRV_PCM_INFO_INTERLEAVED, -#endif - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, - .rate_min = 4000, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = (128*1024), - .period_bytes_min = 1024, - .period_bytes_max = (128*1024), - .periods_min = 2, - .periods_max = 1024, - .fifo_size = 0, - -}; - -/* - * get the current position at the given channel from CCCA register - */ -static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch) -{ - int val = EMU8000_CCCA_READ(rec->emu, ch) & 0xfffffff; - val -= rec->loop_start[ch] - 1; - return val; -} - - -/* - * timer interrupt handler - * check the current position and update the period if necessary. - */ -static void emu8k_pcm_timer_func(unsigned long data) -{ - struct snd_emu8k_pcm *rec = (struct snd_emu8k_pcm *)data; - int ptr, delta; - - spin_lock(&rec->timer_lock); - /* update the current pointer */ - ptr = emu8k_get_curpos(rec, 0); - if (ptr < rec->last_ptr) - delta = ptr + rec->buf_size - rec->last_ptr; - else - delta = ptr - rec->last_ptr; - rec->period_pos += delta; - rec->last_ptr = ptr; - - /* reprogram timer */ - rec->timer.expires = jiffies + 1; - add_timer(&rec->timer); - - /* update period */ - if (rec->period_pos >= (int)rec->period_size) { - rec->period_pos %= rec->period_size; - spin_unlock(&rec->timer_lock); - snd_pcm_period_elapsed(rec->substream); - return; - } - spin_unlock(&rec->timer_lock); -} - - -/* - * open pcm - * creating an instance here - */ -static int emu8k_pcm_open(struct snd_pcm_substream *subs) -{ - struct snd_emu8000 *emu = snd_pcm_substream_chip(subs); - struct snd_emu8k_pcm *rec; - struct snd_pcm_runtime *runtime = subs->runtime; - - rec = kzalloc(sizeof(*rec), GFP_KERNEL); - if (! rec) - return -ENOMEM; - - rec->emu = emu; - rec->substream = subs; - runtime->private_data = rec; - - spin_lock_init(&rec->timer_lock); - init_timer(&rec->timer); - rec->timer.function = emu8k_pcm_timer_func; - rec->timer.data = (unsigned long)rec; - - runtime->hw = emu8k_pcm_hw; - runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3; - runtime->hw.period_bytes_max = runtime->hw.buffer_bytes_max / 2; - - /* use timer to update periods.. (specified in msec) */ - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, - (1000000 + HZ - 1) / HZ, UINT_MAX); - - return 0; -} - -static int emu8k_pcm_close(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - kfree(rec); - subs->runtime->private_data = NULL; - return 0; -} - -/* - * calculate pitch target - */ -static int calc_pitch_target(int pitch) -{ - int ptarget = 1 << (pitch >> 12); - if (pitch & 0x800) ptarget += (ptarget * 0x102e) / 0x2710; - if (pitch & 0x400) ptarget += (ptarget * 0x764) / 0x2710; - if (pitch & 0x200) ptarget += (ptarget * 0x389) / 0x2710; - ptarget += (ptarget >> 1); - if (ptarget > 0xffff) ptarget = 0xffff; - return ptarget; -} - -/* - * set up the voice - */ -static void setup_voice(struct snd_emu8k_pcm *rec, int ch) -{ - struct snd_emu8000 *hw = rec->emu; - unsigned int temp; - - /* channel to be silent and idle */ - EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080); - EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF); - EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF); - EMU8000_PTRX_WRITE(hw, ch, 0); - EMU8000_CPF_WRITE(hw, ch, 0); - - /* pitch offset */ - EMU8000_IP_WRITE(hw, ch, rec->pitch); - /* set envelope parameters */ - EMU8000_ENVVAL_WRITE(hw, ch, 0x8000); - EMU8000_ATKHLD_WRITE(hw, ch, 0x7f7f); - EMU8000_DCYSUS_WRITE(hw, ch, 0x7f7f); - EMU8000_ENVVOL_WRITE(hw, ch, 0x8000); - EMU8000_ATKHLDV_WRITE(hw, ch, 0x7f7f); - /* decay/sustain parameter for volume envelope is used - for triggerg the voice */ - /* modulation envelope heights */ - EMU8000_PEFE_WRITE(hw, ch, 0x0); - /* lfo1/2 delay */ - EMU8000_LFO1VAL_WRITE(hw, ch, 0x8000); - EMU8000_LFO2VAL_WRITE(hw, ch, 0x8000); - /* lfo1 pitch & cutoff shift */ - EMU8000_FMMOD_WRITE(hw, ch, 0); - /* lfo1 volume & freq */ - EMU8000_TREMFRQ_WRITE(hw, ch, 0); - /* lfo2 pitch & freq */ - EMU8000_FM2FRQ2_WRITE(hw, ch, 0); - /* pan & loop start */ - temp = rec->panning[ch]; - temp = (temp <<24) | ((unsigned int)rec->loop_start[ch] - 1); - EMU8000_PSST_WRITE(hw, ch, temp); - /* chorus & loop end (chorus 8bit, MSB) */ - temp = 0; // chorus - temp = (temp << 24) | ((unsigned int)rec->loop_start[ch] + rec->buf_size - 1); - EMU8000_CSL_WRITE(hw, ch, temp); - /* Q & current address (Q 4bit value, MSB) */ - temp = 0; // filterQ - temp = (temp << 28) | ((unsigned int)rec->loop_start[ch] - 1); - EMU8000_CCCA_WRITE(hw, ch, temp); - /* clear unknown registers */ - EMU8000_00A0_WRITE(hw, ch, 0); - EMU8000_0080_WRITE(hw, ch, 0); -} - -/* - * trigger the voice - */ -static void start_voice(struct snd_emu8k_pcm *rec, int ch) -{ - unsigned long flags; - struct snd_emu8000 *hw = rec->emu; - unsigned int temp, aux; - int pt = calc_pitch_target(rec->pitch); - - /* cutoff and volume */ - EMU8000_IFATN_WRITE(hw, ch, 0xff00); - EMU8000_VTFT_WRITE(hw, ch, 0xffff); - EMU8000_CVCF_WRITE(hw, ch, 0xffff); - /* trigger envelope */ - EMU8000_DCYSUSV_WRITE(hw, ch, 0x7f7f); - /* set reverb and pitch target */ - temp = 0; // reverb - if (rec->panning[ch] == 0) - aux = 0xff; - else - aux = (-rec->panning[ch]) & 0xff; - temp = (temp << 8) | (pt << 16) | aux; - EMU8000_PTRX_WRITE(hw, ch, temp); - EMU8000_CPF_WRITE(hw, ch, pt << 16); - - /* start timer */ - spin_lock_irqsave(&rec->timer_lock, flags); - if (! rec->timer_running) { - rec->timer.expires = jiffies + 1; - add_timer(&rec->timer); - rec->timer_running = 1; - } - spin_unlock_irqrestore(&rec->timer_lock, flags); -} - -/* - * stop the voice immediately - */ -static void stop_voice(struct snd_emu8k_pcm *rec, int ch) -{ - unsigned long flags; - struct snd_emu8000 *hw = rec->emu; - - EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F); - - /* stop timer */ - spin_lock_irqsave(&rec->timer_lock, flags); - if (rec->timer_running) { - del_timer(&rec->timer); - rec->timer_running = 0; - } - spin_unlock_irqrestore(&rec->timer_lock, flags); -} - -static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - int ch; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - for (ch = 0; ch < rec->voices; ch++) - start_voice(rec, ch); - rec->running = 1; - break; - case SNDRV_PCM_TRIGGER_STOP: - rec->running = 0; - for (ch = 0; ch < rec->voices; ch++) - stop_voice(rec, ch); - break; - default: - return -EINVAL; - } - return 0; -} - - -/* - * copy / silence ops - */ - -/* - * this macro should be inserted in the copy/silence loops - * to reduce the latency. without this, the system will hang up - * during the whole loop. - */ -#define CHECK_SCHEDULER() \ -do { \ - cond_resched();\ - if (signal_pending(current))\ - return -EAGAIN;\ -} while (0) - - -#ifdef USE_NONINTERLEAVE -/* copy one channel block */ -static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count) -{ - EMU8000_SMALW_WRITE(emu, offset); - while (count > 0) { - unsigned short sval; - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMLD_WRITE(emu, sval); - buf++; - count--; - } - return 0; -} - -static int emu8k_pcm_copy(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - void *src, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - if (voice == -1) { - unsigned short *buf = src; - int i, err; - count /= rec->voices; - for (i = 0; i < rec->voices; i++) { - err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count); - if (err < 0) - return err; - buf += count; - } - return 0; - } else { - return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count); - } -} - -/* make a channel block silence */ -static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count) -{ - EMU8000_SMALW_WRITE(emu, offset); - while (count > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - count--; - } - return 0; -} - -static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - if (voice == -1 && rec->voices == 1) - voice = 0; - if (voice == -1) { - int err; - err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2); - if (err < 0) - return err; - return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2); - } else { - return emu8k_silence_block(emu, pos + rec->loop_start[voice], count); - } -} - -#else /* interleave */ - -/* - * copy the interleaved data can be done easily by using - * DMA "left" and "right" channels on emu8k engine. - */ -static int emu8k_pcm_copy(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - unsigned short __user *buf = src; - - snd_emu8000_write_wait(emu, 1); - EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); - if (rec->voices > 1) - EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); - - while (count-- > 0) { - unsigned short sval; - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMLD_WRITE(emu, sval); - buf++; - if (rec->voices > 1) { - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMRD_WRITE(emu, sval); - buf++; - } - } - return 0; -} - -static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos); - if (rec->voices > 1) - EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos); - while (count-- > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - if (rec->voices > 1) { - CHECK_SCHEDULER(); - EMU8000_SMRD_WRITE(emu, 0); - } - } - return 0; -} -#endif - - -/* - * allocate a memory block - */ -static int emu8k_pcm_hw_params(struct snd_pcm_substream *subs, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - - if (rec->block) { - /* reallocation - release the old block */ - snd_util_mem_free(rec->emu->memhdr, rec->block); - rec->block = NULL; - } - - rec->allocated_bytes = params_buffer_bytes(hw_params) + LOOP_BLANK_SIZE * 4; - rec->block = snd_util_mem_alloc(rec->emu->memhdr, rec->allocated_bytes); - if (! rec->block) - return -ENOMEM; - rec->offset = EMU8000_DRAM_OFFSET + (rec->block->offset >> 1); /* in word */ - /* at least dma_bytes must be set for non-interleaved mode */ - subs->dma_buffer.bytes = params_buffer_bytes(hw_params); - - return 0; -} - -/* - * free the memory block - */ -static int emu8k_pcm_hw_free(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - - if (rec->block) { - int ch; - for (ch = 0; ch < rec->voices; ch++) - stop_voice(rec, ch); // to be sure - if (rec->dram_opened) - emu8k_close_dram(rec->emu); - snd_util_mem_free(rec->emu->memhdr, rec->block); - rec->block = NULL; - } - return 0; -} - -/* - */ -static int emu8k_pcm_prepare(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - - rec->pitch = 0xe000 + calc_rate_offset(subs->runtime->rate); - rec->last_ptr = 0; - rec->period_pos = 0; - - rec->buf_size = subs->runtime->buffer_size; - rec->period_size = subs->runtime->period_size; - rec->voices = subs->runtime->channels; - rec->loop_start[0] = rec->offset + LOOP_BLANK_SIZE; - if (rec->voices > 1) - rec->loop_start[1] = rec->loop_start[0] + rec->buf_size + LOOP_BLANK_SIZE; - if (rec->voices > 1) { - rec->panning[0] = 0xff; - rec->panning[1] = 0x00; - } else - rec->panning[0] = 0x80; - - if (! rec->dram_opened) { - int err, i, ch; - - snd_emux_terminate_all(rec->emu->emu); - if ((err = emu8k_open_dram_for_pcm(rec->emu, rec->voices)) != 0) - return err; - rec->dram_opened = 1; - - /* clear loop blanks */ - snd_emu8000_write_wait(rec->emu, 0); - EMU8000_SMALW_WRITE(rec->emu, rec->offset); - for (i = 0; i < LOOP_BLANK_SIZE; i++) - EMU8000_SMLD_WRITE(rec->emu, 0); - for (ch = 0; ch < rec->voices; ch++) { - EMU8000_SMALW_WRITE(rec->emu, rec->loop_start[ch] + rec->buf_size); - for (i = 0; i < LOOP_BLANK_SIZE; i++) - EMU8000_SMLD_WRITE(rec->emu, 0); - } - } - - setup_voice(rec, 0); - if (rec->voices > 1) - setup_voice(rec, 1); - return 0; -} - -static snd_pcm_uframes_t emu8k_pcm_pointer(struct snd_pcm_substream *subs) -{ - struct snd_emu8k_pcm *rec = subs->runtime->private_data; - if (rec->running) - return emu8k_get_curpos(rec, 0); - return 0; -} - - -static struct snd_pcm_ops emu8k_pcm_ops = { - .open = emu8k_pcm_open, - .close = emu8k_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = emu8k_pcm_hw_params, - .hw_free = emu8k_pcm_hw_free, - .prepare = emu8k_pcm_prepare, - .trigger = emu8k_pcm_trigger, - .pointer = emu8k_pcm_pointer, - .copy = emu8k_pcm_copy, - .silence = emu8k_pcm_silence, -}; - - -static void snd_emu8000_pcm_free(struct snd_pcm *pcm) -{ - struct snd_emu8000 *emu = pcm->private_data; - emu->pcm = NULL; -} - -int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index) -{ - struct snd_pcm *pcm; - int err; - - if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0) - return err; - pcm->private_data = emu; - pcm->private_free = snd_emu8000_pcm_free; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &emu8k_pcm_ops); - emu->pcm = pcm; - - snd_device_register(card, pcm); - - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c b/ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c deleted file mode 100644 index 4e3fcfb1..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/emu8000_synth.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk> - * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * Emu8000 synth plug-in routine - * - * 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 "emu8000_local.h" -#include <linux/init.h> -#include <linux/module.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe"); -MODULE_DESCRIPTION("Emu8000 synth plug-in routine"); -MODULE_LICENSE("GPL"); - -/*----------------------------------------------------------------*/ - -/* - * create a new hardware dependent device for Emu8000 - */ -static int snd_emu8000_new_device(struct snd_seq_device *dev) -{ - struct snd_emu8000 *hw; - struct snd_emux *emu; - - hw = *(struct snd_emu8000**)SNDRV_SEQ_DEVICE_ARGPTR(dev); - if (hw == NULL) - return -EINVAL; - - if (hw->emu) - return -EBUSY; /* already exists..? */ - - if (snd_emux_new(&emu) < 0) - return -ENOMEM; - - hw->emu = emu; - snd_emu8000_ops_setup(hw); - - emu->hw = hw; - emu->max_voices = EMU8000_DRAM_VOICES; - emu->num_ports = hw->seq_ports; - - if (hw->memhdr) { - snd_printk(KERN_ERR "memhdr is already initialized!?\n"); - snd_util_memhdr_free(hw->memhdr); - } - hw->memhdr = snd_util_memhdr_new(hw->mem_size); - if (hw->memhdr == NULL) { - snd_emux_free(emu); - hw->emu = NULL; - return -ENOMEM; - } - - emu->memhdr = hw->memhdr; - emu->midi_ports = hw->seq_ports < 2 ? hw->seq_ports : 2; /* number of virmidi ports */ - emu->midi_devidx = 1; - emu->linear_panning = 1; - emu->hwdep_idx = 2; /* FIXED */ - - if (snd_emux_register(emu, dev->card, hw->index, "Emu8000") < 0) { - snd_emux_free(emu); - snd_util_memhdr_free(hw->memhdr); - hw->emu = NULL; - hw->memhdr = NULL; - return -ENOMEM; - } - - if (hw->mem_size > 0) - snd_emu8000_pcm_new(dev->card, hw, 1); - - dev->driver_data = hw; - - return 0; -} - - -/* - * free all resources - */ -static int snd_emu8000_delete_device(struct snd_seq_device *dev) -{ - struct snd_emu8000 *hw; - - if (dev->driver_data == NULL) - return 0; /* no synth was allocated actually */ - - hw = dev->driver_data; - if (hw->pcm) - snd_device_free(dev->card, hw->pcm); - if (hw->emu) - snd_emux_free(hw->emu); - if (hw->memhdr) - snd_util_memhdr_free(hw->memhdr); - hw->emu = NULL; - hw->memhdr = NULL; - return 0; -} - -/* - * INIT part - */ - -static int __init alsa_emu8000_init(void) -{ - - static struct snd_seq_dev_ops ops = { - snd_emu8000_new_device, - snd_emu8000_delete_device, - }; - return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU8000, &ops, - sizeof(struct snd_emu8000*)); -} - -static void __exit alsa_emu8000_exit(void) -{ - snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU8000); -} - -module_init(alsa_emu8000_init) -module_exit(alsa_emu8000_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/jazz16.c b/ANDROID_3.4.5/sound/isa/sb/jazz16.c deleted file mode 100644 index 410758c6..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/jazz16.c +++ /dev/null @@ -1,404 +0,0 @@ - -/* - * jazz16.c - driver for Media Vision Jazz16 based soundcards. - * Copyright (C) 2009 Krzysztof Helt <krzysztof.h1@wp.pl> - * Based on patches posted by Rask Ingemann Lambertsen and Rene Herman. - * Based on OSS Sound Blaster driver. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <asm/dma.h> -#include <linux/isa.h> -#include <sound/core.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#include <sound/sb.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -#define PFX "jazz16: " - -MODULE_DESCRIPTION("Media Vision Jazz16"); -MODULE_SUPPORTED_DEVICE("{{Media Vision ??? }," - "{RTL,RTL3000}}"); - -MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>"); -MODULE_LICENSE("GPL"); - -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; /* Enable this card */ -static unsigned long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static unsigned long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Media Vision Jazz16 based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Media Vision Jazz16 based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Media Vision Jazz16 based soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for jazz16 driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for jazz16 driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for jazz16 driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for jazz16 driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "DMA8 # for jazz16 driver."); -module_param_array(dma16, int, NULL, 0444); -MODULE_PARM_DESC(dma16, "DMA16 # for jazz16 driver."); - -#define SB_JAZZ16_WAKEUP 0xaf -#define SB_JAZZ16_SET_PORTS 0x50 -#define SB_DSP_GET_JAZZ_BRD_REV 0xfa -#define SB_JAZZ16_SET_DMAINTR 0xfb -#define SB_DSP_GET_JAZZ_MODEL 0xfe - -struct snd_card_jazz16 { - struct snd_sb *chip; -}; - -static irqreturn_t jazz16_interrupt(int irq, void *chip) -{ - return snd_sb8dsp_interrupt(chip); -} - -static int __devinit jazz16_configure_ports(unsigned long port, - unsigned long mpu_port, int idx) -{ - unsigned char val; - - if (!request_region(0x201, 1, "jazz16 config")) { - snd_printk(KERN_ERR "config port region is already in use.\n"); - return -EBUSY; - } - outb(SB_JAZZ16_WAKEUP - idx, 0x201); - udelay(100); - outb(SB_JAZZ16_SET_PORTS + idx, 0x201); - udelay(100); - val = port & 0x70; - val |= (mpu_port & 0x30) >> 4; - outb(val, 0x201); - - release_region(0x201, 1); - return 0; -} - -static int __devinit jazz16_detect_board(unsigned long port, - unsigned long mpu_port) -{ - int err; - int val; - struct snd_sb chip; - - if (!request_region(port, 0x10, "jazz16")) { - snd_printk(KERN_ERR "I/O port region is already in use.\n"); - return -EBUSY; - } - /* just to call snd_sbdsp_command/reset/get_byte() */ - chip.port = port; - - err = snd_sbdsp_reset(&chip); - if (err < 0) - for (val = 0; val < 4; val++) { - err = jazz16_configure_ports(port, mpu_port, val); - if (err < 0) - break; - - err = snd_sbdsp_reset(&chip); - if (!err) - break; - } - if (err < 0) { - err = -ENODEV; - goto err_unmap; - } - if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_BRD_REV)) { - err = -EBUSY; - goto err_unmap; - } - val = snd_sbdsp_get_byte(&chip); - if (val >= 0x30) - snd_sbdsp_get_byte(&chip); - - if ((val & 0xf0) != 0x10) { - err = -ENODEV; - goto err_unmap; - } - if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_MODEL)) { - err = -EBUSY; - goto err_unmap; - } - snd_sbdsp_get_byte(&chip); - err = snd_sbdsp_get_byte(&chip); - snd_printd("Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n", - val, err); - - err = 0; - -err_unmap: - release_region(port, 0x10); - return err; -} - -static int __devinit jazz16_configure_board(struct snd_sb *chip, int mpu_irq) -{ - static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4, - 0, 2, 5, 0, 0, 0, 0, 6 }; - static unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 }; - - if (jazz_dma_bits[chip->dma8] == 0 || - jazz_dma_bits[chip->dma16] == 0 || - jazz_irq_bits[chip->irq] == 0) - return -EINVAL; - - if (!snd_sbdsp_command(chip, SB_JAZZ16_SET_DMAINTR)) - return -EBUSY; - - if (!snd_sbdsp_command(chip, - jazz_dma_bits[chip->dma8] | - (jazz_dma_bits[chip->dma16] << 4))) - return -EBUSY; - - if (!snd_sbdsp_command(chip, - jazz_irq_bits[chip->irq] | - (jazz_irq_bits[mpu_irq] << 4))) - return -EBUSY; - - return 0; -} - -static int __devinit snd_jazz16_match(struct device *devptr, unsigned int dev) -{ - if (!enable[dev]) - return 0; - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "please specify port\n"); - return 0; - } else if (port[dev] == 0x200 || (port[dev] & ~0x270)) { - snd_printk(KERN_ERR "incorrect port specified\n"); - return 0; - } - if (dma8[dev] != SNDRV_AUTO_DMA && - dma8[dev] != 1 && dma8[dev] != 3) { - snd_printk(KERN_ERR "dma8 must be 1 or 3\n"); - return 0; - } - if (dma16[dev] != SNDRV_AUTO_DMA && - dma16[dev] != 5 && dma16[dev] != 7) { - snd_printk(KERN_ERR "dma16 must be 5 or 7\n"); - return 0; - } - if (mpu_port[dev] != SNDRV_AUTO_PORT && - (mpu_port[dev] & ~0x030) != 0x300) { - snd_printk(KERN_ERR "incorrect mpu_port specified\n"); - return 0; - } - if (mpu_irq[dev] != SNDRV_AUTO_DMA && - mpu_irq[dev] != 2 && mpu_irq[dev] != 3 && - mpu_irq[dev] != 5 && mpu_irq[dev] != 7) { - snd_printk(KERN_ERR "mpu_irq must be 2, 3, 5 or 7\n"); - return 0; - } - return 1; -} - -static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev) -{ - struct snd_card *card; - struct snd_card_jazz16 *jazz16; - struct snd_sb *chip; - struct snd_opl3 *opl3; - static int possible_irqs[] = {2, 3, 5, 7, 9, 10, 15, -1}; - static int possible_dmas8[] = {1, 3, -1}; - static int possible_dmas16[] = {5, 7, -1}; - int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_jazz16), &card); - if (err < 0) - return err; - - jazz16 = card->private_data; - - xirq = irq[dev]; - if (xirq == SNDRV_AUTO_IRQ) { - xirq = snd_legacy_find_free_irq(possible_irqs); - if (xirq < 0) { - snd_printk(KERN_ERR "unable to find a free IRQ\n"); - err = -EBUSY; - goto err_free; - } - } - xdma8 = dma8[dev]; - if (xdma8 == SNDRV_AUTO_DMA) { - xdma8 = snd_legacy_find_free_dma(possible_dmas8); - if (xdma8 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA8\n"); - err = -EBUSY; - goto err_free; - } - } - xdma16 = dma16[dev]; - if (xdma16 == SNDRV_AUTO_DMA) { - xdma16 = snd_legacy_find_free_dma(possible_dmas16); - if (xdma16 < 0) { - snd_printk(KERN_ERR "unable to find a free DMA16\n"); - err = -EBUSY; - goto err_free; - } - } - - xmpu_port = mpu_port[dev]; - if (xmpu_port == SNDRV_AUTO_PORT) - xmpu_port = 0; - err = jazz16_detect_board(port[dev], xmpu_port); - if (err < 0) { - printk(KERN_ERR "Media Vision Jazz16 board not detected\n"); - goto err_free; - } - err = snd_sbdsp_create(card, port[dev], irq[dev], - jazz16_interrupt, - dma8[dev], dma16[dev], - SB_HW_JAZZ16, - &chip); - if (err < 0) - goto err_free; - - xmpu_irq = mpu_irq[dev]; - if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT) - xmpu_irq = 0; - err = jazz16_configure_board(chip, xmpu_irq); - if (err < 0) { - printk(KERN_ERR "Media Vision Jazz16 configuration failed\n"); - goto err_free; - } - - jazz16->chip = chip; - - strcpy(card->driver, "jazz16"); - strcpy(card->shortname, "Media Vision Jazz16"); - sprintf(card->longname, - "Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d", - port[dev], xirq, xdma8, xdma16); - - err = snd_sb8dsp_pcm(chip, 0, NULL); - if (err < 0) - goto err_free; - err = snd_sbmixer_new(chip); - if (err < 0) - goto err_free; - - err = snd_opl3_create(card, chip->port, chip->port + 2, - OPL3_HW_AUTO, 1, &opl3); - if (err < 0) - snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n", - chip->port, chip->port + 2); - else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - goto err_free; - } - if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - - if (snd_mpu401_uart_new(card, 0, - MPU401_HW_MPU401, - mpu_port[dev], 0, - mpu_irq[dev], - NULL) < 0) - snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n", - mpu_port[dev]); - } - - snd_card_set_dev(card, devptr); - - err = snd_card_register(card); - if (err < 0) - goto err_free; - - dev_set_drvdata(devptr, card); - return 0; - -err_free: - snd_card_free(card); - return err; -} - -static int __devexit snd_jazz16_remove(struct device *devptr, unsigned int dev) -{ - struct snd_card *card = dev_get_drvdata(devptr); - - dev_set_drvdata(devptr, NULL); - snd_card_free(card); - return 0; -} - -#ifdef CONFIG_PM -static int snd_jazz16_suspend(struct device *pdev, unsigned int n, - pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct snd_card_jazz16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_jazz16_resume(struct device *pdev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct snd_card_jazz16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static struct isa_driver snd_jazz16_driver = { - .match = snd_jazz16_match, - .probe = snd_jazz16_probe, - .remove = __devexit_p(snd_jazz16_remove), -#ifdef CONFIG_PM - .suspend = snd_jazz16_suspend, - .resume = snd_jazz16_resume, -#endif - .driver = { - .name = "jazz16" - }, -}; - -static int __init alsa_card_jazz16_init(void) -{ - return isa_register_driver(&snd_jazz16_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_jazz16_exit(void) -{ - isa_unregister_driver(&snd_jazz16_driver); -} - -module_init(alsa_card_jazz16_init) -module_exit(alsa_card_jazz16_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb16.c b/ANDROID_3.4.5/sound/isa/sb/sb16.c deleted file mode 100644 index 39b8eca1..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb16.c +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Driver for SoundBlaster 16/AWE32/AWE64 soundcards - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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 <asm/dma.h> -#include <linux/init.h> -#include <linux/pnp.h> -#include <linux/err.h> -#include <linux/isa.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/sb.h> -#include <sound/sb16_csp.h> -#include <sound/mpu401.h> -#include <sound/opl3.h> -#include <sound/emu8000.h> -#include <sound/seq_device.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -#ifdef SNDRV_SBAWE -#define PFX "sbawe: " -#else -#define PFX "sb16: " -#endif - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_LICENSE("GPL"); -#ifndef SNDRV_SBAWE -MODULE_DESCRIPTION("Sound Blaster 16"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 16}," - "{Creative Labs,SB Vibra16S}," - "{Creative Labs,SB Vibra16C}," - "{Creative Labs,SB Vibra16CL}," - "{Creative Labs,SB Vibra16X}}"); -#else -MODULE_DESCRIPTION("Sound Blaster AWE"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32}," - "{Creative Labs,SB AWE 64}," - "{Creative Labs,SB AWE 64 Gold}}"); -#endif - -#if 0 -#define SNDRV_DEBUG_IRQ -#endif - -#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))) -#define SNDRV_SBAWE_EMU8000 -#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_ISAPNP; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x330,0x300 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -#ifdef SNDRV_SBAWE_EMU8000 -static long awe_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -#endif -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ -static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */ -static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#ifdef CONFIG_SND_SB16_CSP -static int csp[SNDRV_CARDS]; -#endif -#ifdef SNDRV_SBAWE_EMU8000 -static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; -#endif - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for SoundBlaster 16 soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for SoundBlaster 16 soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable SoundBlaster 16 soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); -#endif -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for SB16 driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for SB16 driver."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port # for SB16 PnP driver."); -#ifdef SNDRV_SBAWE_EMU8000 -module_param_array(awe_port, long, NULL, 0444); -MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver."); -#endif -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for SB16 driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for SB16 driver."); -module_param_array(dma16, int, NULL, 0444); -MODULE_PARM_DESC(dma16, "16-bit DMA # for SB16 driver."); -module_param_array(mic_agc, int, NULL, 0444); -MODULE_PARM_DESC(mic_agc, "Mic Auto-Gain-Control switch."); -#ifdef CONFIG_SND_SB16_CSP -module_param_array(csp, int, NULL, 0444); -MODULE_PARM_DESC(csp, "ASP/CSP chip support."); -#endif -#ifdef SNDRV_SBAWE_EMU8000 -module_param_array(seq_ports, int, NULL, 0444); -MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); -#endif - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -#endif - -struct snd_card_sb16 { - struct resource *fm_res; /* used to block FM i/o region for legacy cards */ - struct snd_sb *chip; -#ifdef CONFIG_PNP - int dev_no; - struct pnp_dev *dev; -#ifdef SNDRV_SBAWE_EMU8000 - struct pnp_dev *devwt; -#endif -#endif -}; - -#ifdef CONFIG_PNP - -static struct pnp_card_device_id snd_sb16_pnpids[] = { -#ifndef SNDRV_SBAWE - /* Sound Blaster 16 PnP */ - { .id = "CTL0024", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0025", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0026", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0027", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0028", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL0029", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL002a", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - /* Note: This card has also a CTL0051:StereoEnhance device!!! */ - { .id = "CTL002b", .devs = { { "CTL0031" } } }, - /* Sound Blaster 16 PnP */ - { .id = "CTL002c", .devs = { { "CTL0031" } } }, - /* Sound Blaster Vibra16S */ - { .id = "CTL0051", .devs = { { "CTL0001" } } }, - /* Sound Blaster Vibra16C */ - { .id = "CTL0070", .devs = { { "CTL0001" } } }, - /* Sound Blaster Vibra16CL - added by ctm@ardi.com */ - { .id = "CTL0080", .devs = { { "CTL0041" } } }, - /* Sound Blaster 16 'value' PnP. It says model ct4130 on the pcb, */ - /* but ct4131 on a sticker on the board.. */ - { .id = "CTL0086", .devs = { { "CTL0041" } } }, - /* Sound Blaster Vibra16X */ - { .id = "CTL00f0", .devs = { { "CTL0043" } } }, - /* Sound Blaster 16 (Virtual PC 2004) */ - { .id = "tBA03b0", .devs = { {.id="PNPb003" } } }, -#else /* SNDRV_SBAWE defined */ - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0035", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0039", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0042", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0043", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - /* Note: This card has also a CTL0051:StereoEnhance device!!! */ - { .id = "CTL0044", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - /* Note: This card has also a CTL0051:StereoEnhance device!!! */ - { .id = "CTL0045", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0046", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0047", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0048", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL0054", .devs = { { "CTL0031" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL009a", .devs = { { "CTL0041" }, { "CTL0021" } } }, - /* Sound Blaster AWE 32 PnP */ - { .id = "CTL009c", .devs = { { "CTL0041" }, { "CTL0021" } } }, - /* Sound Blaster 32 PnP */ - { .id = "CTL009f", .devs = { { "CTL0041" }, { "CTL0021" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL009d", .devs = { { "CTL0042" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP Gold */ - { .id = "CTL009e", .devs = { { "CTL0044" }, { "CTL0023" } } }, - /* Sound Blaster AWE 64 PnP Gold */ - { .id = "CTL00b2", .devs = { { "CTL0044" }, { "CTL0023" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c1", .devs = { { "CTL0042" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c3", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c5", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00c7", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00e4", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster AWE 64 PnP */ - { .id = "CTL00e9", .devs = { { "CTL0045" }, { "CTL0022" } } }, - /* Sound Blaster 16 PnP (AWE) */ - { .id = "CTL00ed", .devs = { { "CTL0041" }, { "CTL0070" } } }, - /* Generic entries */ - { .id = "CTLXXXX" , .devs = { { "CTL0031" }, { "CTL0021" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0041" }, { "CTL0021" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0042" }, { "CTL0022" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0044" }, { "CTL0023" } } }, - { .id = "CTLXXXX" , .devs = { { "CTL0045" }, { "CTL0022" } } }, -#endif /* SNDRV_SBAWE */ - { .id = "", } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_sb16_pnpids); - -#endif /* CONFIG_PNP */ - -#ifdef SNDRV_SBAWE_EMU8000 -#define DRIVER_NAME "snd-card-sbawe" -#else -#define DRIVER_NAME "snd-card-sb16" -#endif - -#ifdef CONFIG_PNP - -static int __devinit snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard, - struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->dev == NULL) - return -ENODEV; - -#ifdef SNDRV_SBAWE_EMU8000 - acard->devwt = pnp_request_card_device(card, id->devs[1].id, acard->dev); -#endif - /* Audio initialization */ - pdev = acard->dev; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); - return err; - } - port[dev] = pnp_port_start(pdev, 0); - mpu_port[dev] = pnp_port_start(pdev, 1); - fm_port[dev] = pnp_port_start(pdev, 2); - dma8[dev] = pnp_dma(pdev, 0); - dma16[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("pnp SB16: port=0x%lx, mpu port=0x%lx, fm port=0x%lx\n", - port[dev], mpu_port[dev], fm_port[dev]); - snd_printdd("pnp SB16: dma1=%i, dma2=%i, irq=%i\n", - dma8[dev], dma16[dev], irq[dev]); -#ifdef SNDRV_SBAWE_EMU8000 - /* WaveTable initialization */ - pdev = acard->devwt; - if (pdev != NULL) { - err = pnp_activate_dev(pdev); - if (err < 0) { - goto __wt_error; - } - awe_port[dev] = pnp_port_start(pdev, 0); - snd_printdd("pnp SB16: wavetable port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0)); - } else { -__wt_error: - if (pdev) { - pnp_release_card_device(pdev); - snd_printk(KERN_ERR PFX "WaveTable pnp configure failure\n"); - } - acard->devwt = NULL; - awe_port[dev] = -1; - } -#endif - return 0; -} - -#endif /* CONFIG_PNP */ - -static void snd_sb16_free(struct snd_card *card) -{ - struct snd_card_sb16 *acard = card->private_data; - - if (acard == NULL) - return; - release_and_free_resource(acard->fm_res); -} - -#ifdef CONFIG_PNP -#define is_isapnp_selected(dev) isapnp[dev] -#else -#define is_isapnp_selected(dev) 0 -#endif - -static int snd_sb16_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_card_sb16), &card); - if (err < 0) - return err; - card->private_free = snd_sb16_free; - *cardp = card; - return 0; -} - -static int __devinit snd_sb16_probe(struct snd_card *card, int dev) -{ - int xirq, xdma8, xdma16; - struct snd_sb *chip; - struct snd_card_sb16 *acard = card->private_data; - struct snd_opl3 *opl3; - struct snd_hwdep *synth = NULL; -#ifdef CONFIG_SND_SB16_CSP - struct snd_hwdep *xcsp = NULL; -#endif - unsigned long flags; - int err; - - xirq = irq[dev]; - xdma8 = dma8[dev]; - xdma16 = dma16[dev]; - - if ((err = snd_sbdsp_create(card, - port[dev], - xirq, - snd_sb16dsp_interrupt, - xdma8, - xdma16, - SB_HW_AUTO, - &chip)) < 0) - return err; - - acard->chip = chip; - if (chip->hardware != SB_HW_16) { - snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]); - return -ENODEV; - } - chip->mpu_port = mpu_port[dev]; - if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) - return err; - - if ((err = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) - return err; - - strcpy(card->driver, -#ifdef SNDRV_SBAWE_EMU8000 - awe_port[dev] > 0 ? "SB AWE" : -#endif - "SB16"); - strcpy(card->shortname, chip->name); - sprintf(card->longname, "%s at 0x%lx, irq %i, dma ", - chip->name, - chip->port, - xirq); - if (xdma8 >= 0) - sprintf(card->longname + strlen(card->longname), "%d", xdma8); - if (xdma16 >= 0) - sprintf(card->longname + strlen(card->longname), "%s%d", - xdma8 >= 0 ? "&" : "", xdma16); - - if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, - chip->mpu_port, - MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi)) < 0) - return err; - chip->rmidi_callback = snd_mpu401_uart_interrupt; - } - -#ifdef SNDRV_SBAWE_EMU8000 - if (awe_port[dev] == SNDRV_AUTO_PORT) - awe_port[dev] = 0; /* disable */ -#endif - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3, - acard->fm_res != NULL || fm_port[dev] == port[dev], - &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", - fm_port[dev], fm_port[dev] + 2); - } else { -#ifdef SNDRV_SBAWE_EMU8000 - int seqdev = awe_port[dev] > 0 ? 2 : 1; -#else - int seqdev = 1; -#endif - if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) - return err; - } - } - - if ((err = snd_sbmixer_new(chip)) < 0) - return err; - -#ifdef CONFIG_SND_SB16_CSP - /* CSP chip on SB16ASP/AWE32 */ - if ((chip->hardware == SB_HW_16) && csp[dev]) { - snd_sb_csp_new(chip, synth != NULL ? 1 : 0, &xcsp); - if (xcsp) { - chip->csp = xcsp->private_data; - chip->hardware = SB_HW_16CSP; - } else { - snd_printk(KERN_INFO PFX "warning - CSP chip not detected on soundcard #%i\n", dev + 1); - } - } -#endif -#ifdef SNDRV_SBAWE_EMU8000 - if (awe_port[dev] > 0) { - if ((err = snd_emu8000_new(card, 1, awe_port[dev], - seq_ports[dev], NULL)) < 0) { - snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]); - - return err; - } - } -#endif - - /* setup Mic AGC */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, SB_DSP4_MIC_AGC, - (snd_sbmixer_read(chip, SB_DSP4_MIC_AGC) & 0x01) | - (mic_agc[dev] ? 0x00 : 0x01)); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - if ((err = snd_card_register(card)) < 0) - return err; - - return 0; -} - -#ifdef CONFIG_PM -static int snd_sb16_suspend(struct snd_card *card, pm_message_t state) -{ - struct snd_card_sb16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_sb16_resume(struct snd_card *card) -{ - struct snd_card_sb16 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev) -{ - struct snd_card_sb16 *acard; - struct snd_card *card; - int err; - - err = snd_sb16_card_new(dev, &card); - if (err < 0) - return err; - - acard = card->private_data; - /* non-PnP FM port address is hardwired with base port address */ - fm_port[dev] = port[dev]; - /* block the 0x388 port to avoid PnP conflicts */ - acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); -#ifdef SNDRV_SBAWE_EMU8000 - /* non-PnP AWE port address is hardwired with base port address */ - awe_port[dev] = port[dev] + 0x400; -#endif - - snd_card_set_dev(card, pdev); - if ((err = snd_sb16_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - dev_set_drvdata(pdev, card); - return 0; -} - - -static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev) -{ - return enable[dev] && !is_isapnp_selected(dev); -} - -static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev) -{ - int err; - static int possible_irqs[] = {5, 9, 10, 7, -1}; - static int possible_dmas8[] = {1, 3, 0, -1}; - static int possible_dmas16[] = {5, 6, 7, -1}; - - if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - return -EBUSY; - } - } - if (dma8[dev] == SNDRV_AUTO_DMA) { - if ((dma8[dev] = snd_legacy_find_free_dma(possible_dmas8)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n"); - return -EBUSY; - } - } - if (dma16[dev] == SNDRV_AUTO_DMA) { - if ((dma16[dev] = snd_legacy_find_free_dma(possible_dmas16)) < 0) { - snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n"); - return -EBUSY; - } - } - - if (port[dev] != SNDRV_AUTO_PORT) - return snd_sb16_isa_probe1(dev, pdev); - else { - static int possible_ports[] = {0x220, 0x240, 0x260, 0x280}; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - port[dev] = possible_ports[i]; - err = snd_sb16_isa_probe1(dev, pdev); - if (! err) - return 0; - } - return err; - } -} - -static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_sb16_isa_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - return snd_sb16_suspend(dev_get_drvdata(dev), state); -} - -static int snd_sb16_isa_resume(struct device *dev, unsigned int n) -{ - return snd_sb16_resume(dev_get_drvdata(dev)); -} -#endif - -#ifdef SNDRV_SBAWE -#define DEV_NAME "sbawe" -#else -#define DEV_NAME "sb16" -#endif - -static struct isa_driver snd_sb16_isa_driver = { - .match = snd_sb16_isa_match, - .probe = snd_sb16_isa_probe, - .remove = __devexit_p(snd_sb16_isa_remove), -#ifdef CONFIG_PM - .suspend = snd_sb16_isa_suspend, - .resume = snd_sb16_isa_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (!enable[dev] || !isapnp[dev]) - continue; - res = snd_sb16_card_new(dev, &card); - if (res < 0) - return res; - snd_card_set_dev(card, &pcard->card->dev); - if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || - (res = snd_sb16_probe(card, dev)) < 0) { - snd_card_free(card); - return res; - } - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; - } - - return -ENODEV; -} - -static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -#ifdef CONFIG_PM -static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) -{ - return snd_sb16_suspend(pnp_get_card_drvdata(pcard), state); -} -static int snd_sb16_pnp_resume(struct pnp_card_link *pcard) -{ - return snd_sb16_resume(pnp_get_card_drvdata(pcard)); -} -#endif - -static struct pnp_card_driver sb16_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, -#ifdef SNDRV_SBAWE - .name = "sbawe", -#else - .name = "sb16", -#endif - .id_table = snd_sb16_pnpids, - .probe = snd_sb16_pnp_detect, - .remove = __devexit_p(snd_sb16_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_sb16_pnp_suspend, - .resume = snd_sb16_pnp_resume, -#endif -}; - -#endif /* CONFIG_PNP */ - -static int __init alsa_card_sb16_init(void) -{ - int err; - - err = isa_register_driver(&snd_sb16_isa_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&sb16_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_sb16_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&sb16_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_sb16_isa_driver); -} - -module_init(alsa_card_sb16_init) -module_exit(alsa_card_sb16_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb16_csp.c b/ANDROID_3.4.5/sound/isa/sb/sb16_csp.c deleted file mode 100644 index c1aa21ed..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb16_csp.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright (c) 1999 by Uros Bizjak <uros@kss-loka.si> - * Takashi Iwai <tiwai@suse.de> - * - * SB16ASP/AWE32 CSP control - * - * CSP microcode loader: - * alsa-tools/sb16_csp/ - * - * 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/slab.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/info.h> -#include <sound/sb16_csp.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>"); -MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("sb16/mulaw_main.csp"); -MODULE_FIRMWARE("sb16/alaw_main.csp"); -MODULE_FIRMWARE("sb16/ima_adpcm_init.csp"); -MODULE_FIRMWARE("sb16/ima_adpcm_playback.csp"); -MODULE_FIRMWARE("sb16/ima_adpcm_capture.csp"); - -#ifdef SNDRV_LITTLE_ENDIAN -#define CSP_HDR_VALUE(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) -#else -#define CSP_HDR_VALUE(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24)) -#endif - -#define RIFF_HEADER CSP_HDR_VALUE('R', 'I', 'F', 'F') -#define CSP__HEADER CSP_HDR_VALUE('C', 'S', 'P', ' ') -#define LIST_HEADER CSP_HDR_VALUE('L', 'I', 'S', 'T') -#define FUNC_HEADER CSP_HDR_VALUE('f', 'u', 'n', 'c') -#define CODE_HEADER CSP_HDR_VALUE('c', 'o', 'd', 'e') -#define INIT_HEADER CSP_HDR_VALUE('i', 'n', 'i', 't') -#define MAIN_HEADER CSP_HDR_VALUE('m', 'a', 'i', 'n') - -/* - * RIFF data format - */ -struct riff_header { - __u32 name; - __u32 len; -}; - -struct desc_header { - struct riff_header info; - __u16 func_nr; - __u16 VOC_type; - __u16 flags_play_rec; - __u16 flags_16bit_8bit; - __u16 flags_stereo_mono; - __u16 flags_rates; -}; - -/* - * prototypes - */ -static void snd_sb_csp_free(struct snd_hwdep *hw); -static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file); -static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg); -static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file); - -static int csp_detect(struct snd_sb *chip, int *version); -static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val); -static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val); -static int read_register(struct snd_sb *chip, unsigned char reg); -static int set_mode_register(struct snd_sb *chip, unsigned char mode); -static int get_version(struct snd_sb *chip); - -static int snd_sb_csp_riff_load(struct snd_sb_csp * p, - struct snd_sb_csp_microcode __user * code); -static int snd_sb_csp_unload(struct snd_sb_csp * p); -static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags); -static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode); -static int snd_sb_csp_check_version(struct snd_sb_csp * p); - -static int snd_sb_csp_use(struct snd_sb_csp * p); -static int snd_sb_csp_unuse(struct snd_sb_csp * p); -static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels); -static int snd_sb_csp_stop(struct snd_sb_csp * p); -static int snd_sb_csp_pause(struct snd_sb_csp * p); -static int snd_sb_csp_restart(struct snd_sb_csp * p); - -static int snd_sb_qsound_build(struct snd_sb_csp * p); -static void snd_sb_qsound_destroy(struct snd_sb_csp * p); -static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p); - -static int init_proc_entry(struct snd_sb_csp * p, int device); -static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer); - -/* - * Detect CSP chip and create a new instance - */ -int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) -{ - struct snd_sb_csp *p; - int uninitialized_var(version); - int err; - struct snd_hwdep *hw; - - if (rhwdep) - *rhwdep = NULL; - - if (csp_detect(chip, &version)) - return -ENODEV; - - if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0) - return err; - - if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { - snd_device_free(chip->card, hw); - return -ENOMEM; - } - p->chip = chip; - p->version = version; - - /* CSP operators */ - p->ops.csp_use = snd_sb_csp_use; - p->ops.csp_unuse = snd_sb_csp_unuse; - p->ops.csp_autoload = snd_sb_csp_autoload; - p->ops.csp_start = snd_sb_csp_start; - p->ops.csp_stop = snd_sb_csp_stop; - p->ops.csp_qsound_transfer = snd_sb_csp_qsound_transfer; - - mutex_init(&p->access_mutex); - sprintf(hw->name, "CSP v%d.%d", (version >> 4), (version & 0x0f)); - hw->iface = SNDRV_HWDEP_IFACE_SB16CSP; - hw->private_data = p; - hw->private_free = snd_sb_csp_free; - - /* operators - only write/ioctl */ - hw->ops.open = snd_sb_csp_open; - hw->ops.ioctl = snd_sb_csp_ioctl; - hw->ops.release = snd_sb_csp_release; - - /* create a proc entry */ - init_proc_entry(p, device); - if (rhwdep) - *rhwdep = hw; - return 0; -} - -/* - * free_private for hwdep instance - */ -static void snd_sb_csp_free(struct snd_hwdep *hwdep) -{ - int i; - struct snd_sb_csp *p = hwdep->private_data; - if (p) { - if (p->running & SNDRV_SB_CSP_ST_RUNNING) - snd_sb_csp_stop(p); - for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i) - release_firmware(p->csp_programs[i]); - kfree(p); - } -} - -/* ------------------------------ */ - -/* - * open the device exclusively - */ -static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file) -{ - struct snd_sb_csp *p = hw->private_data; - return (snd_sb_csp_use(p)); -} - -/* - * ioctl for hwdep device: - */ -static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_sb_csp *p = hw->private_data; - struct snd_sb_csp_info info; - struct snd_sb_csp_start start_info; - int err; - - if (snd_BUG_ON(!p)) - return -EINVAL; - - if (snd_sb_csp_check_version(p)) - return -ENODEV; - - switch (cmd) { - /* get information */ - case SNDRV_SB_CSP_IOCTL_INFO: - *info.codec_name = *p->codec_name; - info.func_nr = p->func_nr; - info.acc_format = p->acc_format; - info.acc_channels = p->acc_channels; - info.acc_width = p->acc_width; - info.acc_rates = p->acc_rates; - info.csp_mode = p->mode; - info.run_channels = p->run_channels; - info.run_width = p->run_width; - info.version = p->version; - info.state = p->running; - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - err = -EFAULT; - else - err = 0; - break; - - /* load CSP microcode */ - case SNDRV_SB_CSP_IOCTL_LOAD_CODE: - err = (p->running & SNDRV_SB_CSP_ST_RUNNING ? - -EBUSY : snd_sb_csp_riff_load(p, (struct snd_sb_csp_microcode __user *) arg)); - break; - case SNDRV_SB_CSP_IOCTL_UNLOAD_CODE: - err = (p->running & SNDRV_SB_CSP_ST_RUNNING ? - -EBUSY : snd_sb_csp_unload(p)); - break; - - /* change CSP running state */ - case SNDRV_SB_CSP_IOCTL_START: - if (copy_from_user(&start_info, (void __user *) arg, sizeof(start_info))) - err = -EFAULT; - else - err = snd_sb_csp_start(p, start_info.sample_width, start_info.channels); - break; - case SNDRV_SB_CSP_IOCTL_STOP: - err = snd_sb_csp_stop(p); - break; - case SNDRV_SB_CSP_IOCTL_PAUSE: - err = snd_sb_csp_pause(p); - break; - case SNDRV_SB_CSP_IOCTL_RESTART: - err = snd_sb_csp_restart(p); - break; - default: - err = -ENOTTY; - break; - } - - return err; -} - -/* - * close the device - */ -static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file) -{ - struct snd_sb_csp *p = hw->private_data; - return (snd_sb_csp_unuse(p)); -} - -/* ------------------------------ */ - -/* - * acquire device - */ -static int snd_sb_csp_use(struct snd_sb_csp * p) -{ - mutex_lock(&p->access_mutex); - if (p->used) { - mutex_unlock(&p->access_mutex); - return -EAGAIN; - } - p->used++; - mutex_unlock(&p->access_mutex); - - return 0; - -} - -/* - * release device - */ -static int snd_sb_csp_unuse(struct snd_sb_csp * p) -{ - mutex_lock(&p->access_mutex); - p->used--; - mutex_unlock(&p->access_mutex); - - return 0; -} - -/* - * load microcode via ioctl: - * code is user-space pointer - */ -static int snd_sb_csp_riff_load(struct snd_sb_csp * p, - struct snd_sb_csp_microcode __user * mcode) -{ - struct snd_sb_csp_mc_header info; - - unsigned char __user *data_ptr; - unsigned char __user *data_end; - unsigned short func_nr = 0; - - struct riff_header file_h, item_h, code_h; - __u32 item_type; - struct desc_header funcdesc_h; - - unsigned long flags; - int err; - - if (copy_from_user(&info, mcode, sizeof(info))) - return -EFAULT; - data_ptr = mcode->data; - - if (copy_from_user(&file_h, data_ptr, sizeof(file_h))) - return -EFAULT; - if ((file_h.name != RIFF_HEADER) || - (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) { - snd_printd("%s: Invalid RIFF header\n", __func__); - return -EINVAL; - } - data_ptr += sizeof(file_h); - data_end = data_ptr + le32_to_cpu(file_h.len); - - if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) - return -EFAULT; - if (item_type != CSP__HEADER) { - snd_printd("%s: Invalid RIFF file type\n", __func__); - return -EINVAL; - } - data_ptr += sizeof (item_type); - - for (; data_ptr < data_end; data_ptr += le32_to_cpu(item_h.len)) { - if (copy_from_user(&item_h, data_ptr, sizeof(item_h))) - return -EFAULT; - data_ptr += sizeof(item_h); - if (item_h.name != LIST_HEADER) - continue; - - if (copy_from_user(&item_type, data_ptr, sizeof(item_type))) - return -EFAULT; - switch (item_type) { - case FUNC_HEADER: - if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h))) - return -EFAULT; - func_nr = le16_to_cpu(funcdesc_h.func_nr); - break; - case CODE_HEADER: - if (func_nr != info.func_req) - break; /* not required function, try next */ - data_ptr += sizeof(item_type); - - /* destroy QSound mixer element */ - if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { - snd_sb_qsound_destroy(p); - } - /* Clear all flags */ - p->running = 0; - p->mode = 0; - - /* load microcode blocks */ - for (;;) { - if (data_ptr >= data_end) - return -EINVAL; - if (copy_from_user(&code_h, data_ptr, sizeof(code_h))) - return -EFAULT; - - /* init microcode blocks */ - if (code_h.name != INIT_HEADER) - break; - data_ptr += sizeof(code_h); - err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len), - SNDRV_SB_CSP_LOAD_INITBLOCK); - if (err) - return err; - data_ptr += le32_to_cpu(code_h.len); - } - /* main microcode block */ - if (copy_from_user(&code_h, data_ptr, sizeof(code_h))) - return -EFAULT; - - if (code_h.name != MAIN_HEADER) { - snd_printd("%s: Missing 'main' microcode\n", __func__); - return -EINVAL; - } - data_ptr += sizeof(code_h); - err = snd_sb_csp_load_user(p, data_ptr, - le32_to_cpu(code_h.len), 0); - if (err) - return err; - - /* fill in codec header */ - strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name)); - p->func_nr = func_nr; - p->mode = le16_to_cpu(funcdesc_h.flags_play_rec); - switch (le16_to_cpu(funcdesc_h.VOC_type)) { - case 0x0001: /* QSound decoder */ - if (le16_to_cpu(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) { - if (snd_sb_qsound_build(p) == 0) - /* set QSound flag and clear all other mode flags */ - p->mode = SNDRV_SB_CSP_MODE_QSOUND; - } - p->acc_format = 0; - break; - case 0x0006: /* A Law codec */ - p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; - break; - case 0x0007: /* Mu Law codec */ - p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; - break; - case 0x0011: /* what Creative thinks is IMA ADPCM codec */ - case 0x0200: /* Creative ADPCM codec */ - p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; - break; - case 201: /* Text 2 Speech decoder */ - /* TODO: Text2Speech handling routines */ - p->acc_format = 0; - break; - case 0x0202: /* Fast Speech 8 codec */ - case 0x0203: /* Fast Speech 10 codec */ - p->acc_format = SNDRV_PCM_FMTBIT_SPECIAL; - break; - default: /* other codecs are unsupported */ - p->acc_format = p->acc_width = p->acc_rates = 0; - p->mode = 0; - snd_printd("%s: Unsupported CSP codec type: 0x%04x\n", - __func__, - le16_to_cpu(funcdesc_h.VOC_type)); - return -EINVAL; - } - p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono); - p->acc_width = le16_to_cpu(funcdesc_h.flags_16bit_8bit); - p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates); - - /* Decouple CSP from IRQ and DMAREQ lines */ - spin_lock_irqsave(&p->chip->reg_lock, flags); - set_mode_register(p->chip, 0xfc); - set_mode_register(p->chip, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - - /* finished loading successfully */ - p->running = SNDRV_SB_CSP_ST_LOADED; /* set LOADED flag */ - return 0; - } - } - snd_printd("%s: Function #%d not found\n", __func__, info.func_req); - return -EINVAL; -} - -/* - * unload CSP microcode - */ -static int snd_sb_csp_unload(struct snd_sb_csp * p) -{ - if (p->running & SNDRV_SB_CSP_ST_RUNNING) - return -EBUSY; - if (!(p->running & SNDRV_SB_CSP_ST_LOADED)) - return -ENXIO; - - /* clear supported formats */ - p->acc_format = 0; - p->acc_channels = p->acc_width = p->acc_rates = 0; - /* destroy QSound mixer element */ - if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { - snd_sb_qsound_destroy(p); - } - /* clear all flags */ - p->running = 0; - p->mode = 0; - return 0; -} - -/* - * send command sequence to DSP - */ -static inline int command_seq(struct snd_sb *chip, const unsigned char *seq, int size) -{ - int i; - for (i = 0; i < size; i++) { - if (!snd_sbdsp_command(chip, seq[i])) - return -EIO; - } - return 0; -} - -/* - * set CSP codec parameter - */ -static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val) -{ - unsigned char dsp_cmd[3]; - - dsp_cmd[0] = 0x05; /* CSP set codec parameter */ - dsp_cmd[1] = val; /* Parameter value */ - dsp_cmd[2] = par; /* Parameter */ - command_seq(chip, dsp_cmd, 3); - snd_sbdsp_command(chip, 0x03); /* DSP read? */ - if (snd_sbdsp_get_byte(chip) != par) - return -EIO; - return 0; -} - -/* - * set CSP register - */ -static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val) -{ - unsigned char dsp_cmd[3]; - - dsp_cmd[0] = 0x0e; /* CSP set register */ - dsp_cmd[1] = reg; /* CSP Register */ - dsp_cmd[2] = val; /* value */ - return command_seq(chip, dsp_cmd, 3); -} - -/* - * read CSP register - * return < 0 -> error - */ -static int read_register(struct snd_sb *chip, unsigned char reg) -{ - unsigned char dsp_cmd[2]; - - dsp_cmd[0] = 0x0f; /* CSP read register */ - dsp_cmd[1] = reg; /* CSP Register */ - command_seq(chip, dsp_cmd, 2); - return snd_sbdsp_get_byte(chip); /* Read DSP value */ -} - -/* - * set CSP mode register - */ -static int set_mode_register(struct snd_sb *chip, unsigned char mode) -{ - unsigned char dsp_cmd[2]; - - dsp_cmd[0] = 0x04; /* CSP set mode register */ - dsp_cmd[1] = mode; /* mode */ - return command_seq(chip, dsp_cmd, 2); -} - -/* - * Detect CSP - * return 0 if CSP exists. - */ -static int csp_detect(struct snd_sb *chip, int *version) -{ - unsigned char csp_test1, csp_test2; - unsigned long flags; - int result = -ENODEV; - - spin_lock_irqsave(&chip->reg_lock, flags); - - set_codec_parameter(chip, 0x00, 0x00); - set_mode_register(chip, 0xfc); /* 0xfc = ?? */ - - csp_test1 = read_register(chip, 0x83); - set_register(chip, 0x83, ~csp_test1); - csp_test2 = read_register(chip, 0x83); - if (csp_test2 != (csp_test1 ^ 0xff)) - goto __fail; - - set_register(chip, 0x83, csp_test1); - csp_test2 = read_register(chip, 0x83); - if (csp_test2 != csp_test1) - goto __fail; - - set_mode_register(chip, 0x00); /* 0x00 = ? */ - - *version = get_version(chip); - snd_sbdsp_reset(chip); /* reset DSP after getversion! */ - if (*version >= 0x10 && *version <= 0x1f) - result = 0; /* valid version id */ - - __fail: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return result; -} - -/* - * get CSP version number - */ -static int get_version(struct snd_sb *chip) -{ - unsigned char dsp_cmd[2]; - - dsp_cmd[0] = 0x08; /* SB_DSP_!something! */ - dsp_cmd[1] = 0x03; /* get chip version id? */ - command_seq(chip, dsp_cmd, 2); - - return (snd_sbdsp_get_byte(chip)); -} - -/* - * check if the CSP version is valid - */ -static int snd_sb_csp_check_version(struct snd_sb_csp * p) -{ - if (p->version < 0x10 || p->version > 0x1f) { - snd_printd("%s: Invalid CSP version: 0x%x\n", __func__, p->version); - return 1; - } - return 0; -} - -/* - * download microcode to CSP (microcode should have one "main" block). - */ -static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int size, int load_flags) -{ - int status, i; - int err; - int result = -EIO; - unsigned long flags; - - spin_lock_irqsave(&p->chip->reg_lock, flags); - snd_sbdsp_command(p->chip, 0x01); /* CSP download command */ - if (snd_sbdsp_get_byte(p->chip)) { - snd_printd("%s: Download command failed\n", __func__); - goto __fail; - } - /* Send CSP low byte (size - 1) */ - snd_sbdsp_command(p->chip, (unsigned char)(size - 1)); - /* Send high byte */ - snd_sbdsp_command(p->chip, (unsigned char)((size - 1) >> 8)); - /* send microcode sequence */ - /* load from kernel space */ - while (size--) { - if (!snd_sbdsp_command(p->chip, *buf++)) - goto __fail; - } - if (snd_sbdsp_get_byte(p->chip)) - goto __fail; - - if (load_flags & SNDRV_SB_CSP_LOAD_INITBLOCK) { - i = 0; - /* some codecs (FastSpeech) take some time to initialize */ - while (1) { - snd_sbdsp_command(p->chip, 0x03); - status = snd_sbdsp_get_byte(p->chip); - if (status == 0x55 || ++i >= 10) - break; - udelay (10); - } - if (status != 0x55) { - snd_printd("%s: Microcode initialization failed\n", __func__); - goto __fail; - } - } else { - /* - * Read mixer register SB_DSP4_DMASETUP after loading 'main' code. - * Start CSP chip if no 16bit DMA channel is set - some kind - * of autorun or perhaps a bugfix? - */ - spin_lock(&p->chip->mixer_lock); - status = snd_sbmixer_read(p->chip, SB_DSP4_DMASETUP); - spin_unlock(&p->chip->mixer_lock); - if (!(status & (SB_DMASETUP_DMA7 | SB_DMASETUP_DMA6 | SB_DMASETUP_DMA5))) { - err = (set_codec_parameter(p->chip, 0xaa, 0x00) || - set_codec_parameter(p->chip, 0xff, 0x00)); - snd_sbdsp_reset(p->chip); /* really! */ - if (err) - goto __fail; - set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - set_mode_register(p->chip, 0x70); /* 70 = RUN */ - } - } - result = 0; - - __fail: - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - return result; -} - -static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags) -{ - int err; - unsigned char *kbuf; - - kbuf = memdup_user(buf, size); - if (IS_ERR(kbuf)) - return PTR_ERR(kbuf); - - err = snd_sb_csp_load(p, kbuf, size, load_flags); - - kfree(kbuf); - return err; -} - -static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags) -{ - static const char *const names[] = { - "sb16/mulaw_main.csp", - "sb16/alaw_main.csp", - "sb16/ima_adpcm_init.csp", - "sb16/ima_adpcm_playback.csp", - "sb16/ima_adpcm_capture.csp", - }; - const struct firmware *program; - - BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT); - program = p->csp_programs[index]; - if (!program) { - int err = request_firmware(&program, names[index], - p->chip->card->dev); - if (err < 0) - return err; - p->csp_programs[index] = program; - } - return snd_sb_csp_load(p, program->data, program->size, flags); -} - -/* - * autoload hardware codec if necessary - * return 0 if CSP is loaded and ready to run (p->running != 0) - */ -static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode) -{ - unsigned long flags; - int err = 0; - - /* if CSP is running or manually loaded then exit */ - if (p->running & (SNDRV_SB_CSP_ST_RUNNING | SNDRV_SB_CSP_ST_LOADED)) - return -EBUSY; - - /* autoload microcode only if requested hardware codec is not already loaded */ - if (((1 << pcm_sfmt) & p->acc_format) && (play_rec_mode & p->mode)) { - p->running = SNDRV_SB_CSP_ST_AUTO; - } else { - switch (pcm_sfmt) { - case SNDRV_PCM_FORMAT_MU_LAW: - err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0); - p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; - p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; - break; - case SNDRV_PCM_FORMAT_A_LAW: - err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0); - p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; - p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; - break; - case SNDRV_PCM_FORMAT_IMA_ADPCM: - err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT, - SNDRV_SB_CSP_LOAD_INITBLOCK); - if (err) - break; - if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) { - err = snd_sb_csp_firmware_load - (p, CSP_PROGRAM_ADPCM_PLAYBACK, 0); - p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE; - } else { - err = snd_sb_csp_firmware_load - (p, CSP_PROGRAM_ADPCM_CAPTURE, 0); - p->mode = SNDRV_SB_CSP_MODE_DSP_READ; - } - p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; - break; - default: - /* Decouple CSP from IRQ and DMAREQ lines */ - if (p->running & SNDRV_SB_CSP_ST_AUTO) { - spin_lock_irqsave(&p->chip->reg_lock, flags); - set_mode_register(p->chip, 0xfc); - set_mode_register(p->chip, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - p->running = 0; /* clear autoloaded flag */ - } - return -EINVAL; - } - if (err) { - p->acc_format = 0; - p->acc_channels = p->acc_width = p->acc_rates = 0; - - p->running = 0; /* clear autoloaded flag */ - p->mode = 0; - return (err); - } else { - p->running = SNDRV_SB_CSP_ST_AUTO; /* set autoloaded flag */ - p->acc_width = SNDRV_SB_CSP_SAMPLE_16BIT; /* only 16 bit data */ - p->acc_channels = SNDRV_SB_CSP_MONO | SNDRV_SB_CSP_STEREO; - p->acc_rates = SNDRV_SB_CSP_RATE_ALL; /* HW codecs accept all rates */ - } - - } - return (p->running & SNDRV_SB_CSP_ST_AUTO) ? 0 : -ENXIO; -} - -/* - * start CSP - */ -static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels) -{ - unsigned char s_type; /* sample type */ - unsigned char mixL, mixR; - int result = -EIO; - unsigned long flags; - - if (!(p->running & (SNDRV_SB_CSP_ST_LOADED | SNDRV_SB_CSP_ST_AUTO))) { - snd_printd("%s: Microcode not loaded\n", __func__); - return -ENXIO; - } - if (p->running & SNDRV_SB_CSP_ST_RUNNING) { - snd_printd("%s: CSP already running\n", __func__); - return -EBUSY; - } - if (!(sample_width & p->acc_width)) { - snd_printd("%s: Unsupported PCM sample width\n", __func__); - return -EINVAL; - } - if (!(channels & p->acc_channels)) { - snd_printd("%s: Invalid number of channels\n", __func__); - return -EINVAL; - } - - /* Mute PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); - mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); - - spin_lock(&p->chip->reg_lock); - set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - set_mode_register(p->chip, 0x70); /* 70 = RUN */ - - s_type = 0x00; - if (channels == SNDRV_SB_CSP_MONO) - s_type = 0x11; /* 000n 000n (n = 1 if mono) */ - if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT) - s_type |= 0x22; /* 00dX 00dX (d = 1 if 8 bit samples) */ - - if (set_codec_parameter(p->chip, 0x81, s_type)) { - snd_printd("%s: Set sample type command failed\n", __func__); - goto __fail; - } - if (set_codec_parameter(p->chip, 0x80, 0x00)) { - snd_printd("%s: Codec start command failed\n", __func__); - goto __fail; - } - p->run_width = sample_width; - p->run_channels = channels; - - p->running |= SNDRV_SB_CSP_ST_RUNNING; - - if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* enable QSound decoder */ - set_codec_parameter(p->chip, 0x00, 0xff); - set_codec_parameter(p->chip, 0x01, 0xff); - p->running |= SNDRV_SB_CSP_ST_QSOUND; - /* set QSound startup value */ - snd_sb_csp_qsound_transfer(p); - } - result = 0; - - __fail: - spin_unlock(&p->chip->reg_lock); - - /* restore PCM volume */ - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); - - return result; -} - -/* - * stop CSP - */ -static int snd_sb_csp_stop(struct snd_sb_csp * p) -{ - int result; - unsigned char mixL, mixR; - unsigned long flags; - - if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) - return 0; - - /* Mute PCM volume */ - spin_lock_irqsave(&p->chip->mixer_lock, flags); - mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV); - mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); - - spin_lock(&p->chip->reg_lock); - if (p->running & SNDRV_SB_CSP_ST_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* disable QSound decoder */ - set_codec_parameter(p->chip, 0x00, 0x00); - set_codec_parameter(p->chip, 0x01, 0x00); - - p->running &= ~SNDRV_SB_CSP_ST_QSOUND; - } - result = set_mode_register(p->chip, 0xc0); /* c0 = STOP */ - spin_unlock(&p->chip->reg_lock); - - /* restore PCM volume */ - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); - snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); - spin_unlock_irqrestore(&p->chip->mixer_lock, flags); - - if (!(result)) - p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING); - return result; -} - -/* - * pause CSP codec and hold DMA transfer - */ -static int snd_sb_csp_pause(struct snd_sb_csp * p) -{ - int result; - unsigned long flags; - - if (!(p->running & SNDRV_SB_CSP_ST_RUNNING)) - return -EBUSY; - - spin_lock_irqsave(&p->chip->reg_lock, flags); - result = set_codec_parameter(p->chip, 0x80, 0xff); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - if (!(result)) - p->running |= SNDRV_SB_CSP_ST_PAUSED; - - return result; -} - -/* - * restart CSP codec and resume DMA transfer - */ -static int snd_sb_csp_restart(struct snd_sb_csp * p) -{ - int result; - unsigned long flags; - - if (!(p->running & SNDRV_SB_CSP_ST_PAUSED)) - return -EBUSY; - - spin_lock_irqsave(&p->chip->reg_lock, flags); - result = set_codec_parameter(p->chip, 0x80, 0x00); - spin_unlock_irqrestore(&p->chip->reg_lock, flags); - if (!(result)) - p->running &= ~SNDRV_SB_CSP_ST_PAUSED; - - return result; -} - -/* ------------------------------ */ - -/* - * QSound mixer control for PCM - */ - -#define snd_sb_qsound_switch_info snd_ctl_boolean_mono_info - -static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0; - return 0; -} - -static int snd_sb_qsound_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval; - - nval = ucontrol->value.integer.value[0] & 0x01; - spin_lock_irqsave(&p->q_lock, flags); - change = p->q_enabled != nval; - p->q_enabled = nval; - spin_unlock_irqrestore(&p->q_lock, flags); - return change; -} - -static int snd_sb_qsound_space_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 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; - return 0; -} - -static int snd_sb_qsound_space_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&p->q_lock, flags); - ucontrol->value.integer.value[0] = p->qpos_left; - ucontrol->value.integer.value[1] = p->qpos_right; - spin_unlock_irqrestore(&p->q_lock, flags); - return 0; -} - -static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval1, nval2; - - nval1 = ucontrol->value.integer.value[0]; - if (nval1 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT) - nval1 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; - nval2 = ucontrol->value.integer.value[1]; - if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT) - nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT; - spin_lock_irqsave(&p->q_lock, flags); - change = p->qpos_left != nval1 || p->qpos_right != nval2; - p->qpos_left = nval1; - p->qpos_right = nval2; - p->qpos_changed = change; - spin_unlock_irqrestore(&p->q_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_sb_qsound_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Switch", - .info = snd_sb_qsound_switch_info, - .get = snd_sb_qsound_switch_get, - .put = snd_sb_qsound_switch_put -}; - -static struct snd_kcontrol_new snd_sb_qsound_space = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "3D Control - Space", - .info = snd_sb_qsound_space_info, - .get = snd_sb_qsound_space_get, - .put = snd_sb_qsound_space_put -}; - -static int snd_sb_qsound_build(struct snd_sb_csp * p) -{ - struct snd_card *card; - int err; - - if (snd_BUG_ON(!p)) - return -EINVAL; - - card = p->chip->card; - p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2; - p->qpos_changed = 0; - - spin_lock_init(&p->q_lock); - - if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0) - goto __error; - if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0) - goto __error; - - return 0; - - __error: - snd_sb_qsound_destroy(p); - return err; -} - -static void snd_sb_qsound_destroy(struct snd_sb_csp * p) -{ - struct snd_card *card; - unsigned long flags; - - if (snd_BUG_ON(!p)) - return; - - card = p->chip->card; - - down_write(&card->controls_rwsem); - if (p->qsound_switch) - snd_ctl_remove(card, p->qsound_switch); - if (p->qsound_space) - snd_ctl_remove(card, p->qsound_space); - up_write(&card->controls_rwsem); - - /* cancel pending transfer of QSound parameters */ - spin_lock_irqsave (&p->q_lock, flags); - p->qpos_changed = 0; - spin_unlock_irqrestore (&p->q_lock, flags); -} - -/* - * Transfer qsound parameters to CSP, - * function should be called from interrupt routine - */ -static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p) -{ - int err = -ENXIO; - - spin_lock(&p->q_lock); - if (p->running & SNDRV_SB_CSP_ST_QSOUND) { - set_codec_parameter(p->chip, 0xe0, 0x01); - /* left channel */ - set_codec_parameter(p->chip, 0x00, p->qpos_left); - set_codec_parameter(p->chip, 0x02, 0x00); - /* right channel */ - set_codec_parameter(p->chip, 0x00, p->qpos_right); - set_codec_parameter(p->chip, 0x03, 0x00); - err = 0; - } - p->qpos_changed = 0; - spin_unlock(&p->q_lock); - return err; -} - -/* ------------------------------ */ - -/* - * proc interface - */ -static int init_proc_entry(struct snd_sb_csp * p, int device) -{ - char name[16]; - struct snd_info_entry *entry; - sprintf(name, "cspD%d", device); - if (! snd_card_proc_new(p->chip->card, name, &entry)) - snd_info_set_text_ops(entry, p, info_read); - return 0; -} - -static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) -{ - struct snd_sb_csp *p = entry->private_data; - - snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f)); - snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'), - ((p->running & SNDRV_SB_CSP_ST_PAUSED) ? 'P' : '-'), - ((p->running & SNDRV_SB_CSP_ST_RUNNING) ? 'R' : '-'), - ((p->running & SNDRV_SB_CSP_ST_LOADED) ? 'L' : '-')); - if (p->running & SNDRV_SB_CSP_ST_LOADED) { - snd_iprintf(buffer, "Codec: %s [func #%d]\n", p->codec_name, p->func_nr); - snd_iprintf(buffer, "Sample rates: "); - if (p->acc_rates == SNDRV_SB_CSP_RATE_ALL) { - snd_iprintf(buffer, "All\n"); - } else { - snd_iprintf(buffer, "%s%s%s%s\n", - ((p->acc_rates & SNDRV_SB_CSP_RATE_8000) ? "8000Hz " : ""), - ((p->acc_rates & SNDRV_SB_CSP_RATE_11025) ? "11025Hz " : ""), - ((p->acc_rates & SNDRV_SB_CSP_RATE_22050) ? "22050Hz " : ""), - ((p->acc_rates & SNDRV_SB_CSP_RATE_44100) ? "44100Hz" : "")); - } - if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) { - snd_iprintf(buffer, "QSound decoder %sabled\n", - p->q_enabled ? "en" : "dis"); - } else { - snd_iprintf(buffer, "PCM format ID: 0x%x (%s/%s) [%s/%s] [%s/%s]\n", - p->acc_format, - ((p->acc_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? "16bit" : "-"), - ((p->acc_width & SNDRV_SB_CSP_SAMPLE_8BIT) ? "8bit" : "-"), - ((p->acc_channels & SNDRV_SB_CSP_MONO) ? "mono" : "-"), - ((p->acc_channels & SNDRV_SB_CSP_STEREO) ? "stereo" : "-"), - ((p->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) ? "playback" : "-"), - ((p->mode & SNDRV_SB_CSP_MODE_DSP_READ) ? "capture" : "-")); - } - } - if (p->running & SNDRV_SB_CSP_ST_AUTO) { - snd_iprintf(buffer, "Autoloaded Mu-Law, A-Law or Ima-ADPCM hardware codec\n"); - } - if (p->running & SNDRV_SB_CSP_ST_RUNNING) { - snd_iprintf(buffer, "Processing %dbit %s PCM samples\n", - ((p->run_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? 16 : 8), - ((p->run_channels & SNDRV_SB_CSP_MONO) ? "mono" : "stereo")); - } - if (p->running & SNDRV_SB_CSP_ST_QSOUND) { - snd_iprintf(buffer, "Qsound position: left = 0x%x, right = 0x%x\n", - p->qpos_left, p->qpos_right); - } -} - -/* */ - -EXPORT_SYMBOL(snd_sb_csp_new); - -/* - * INIT part - */ - -static int __init alsa_sb_csp_init(void) -{ - return 0; -} - -static void __exit alsa_sb_csp_exit(void) -{ -} - -module_init(alsa_sb_csp_init) -module_exit(alsa_sb_csp_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb16_main.c b/ANDROID_3.4.5/sound/isa/sb/sb16_main.c deleted file mode 100644 index 0bbcd471..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb16_main.c +++ /dev/null @@ -1,925 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of 16-bit SoundBlaster cards and clones - * Note: This is very ugly hardware which uses one 8-bit DMA channel and - * second 16-bit DMA channel. Unfortunately 8-bit DMA channel can't - * transfer 16-bit samples and 16-bit DMA channels can't transfer - * 8-bit samples. This make full duplex more complicated than - * can be... People, don't buy these soundcards for full 16-bit - * duplex!!! - * Note: 16-bit wide is assigned to first direction which made request. - * With full duplex - playback is preferred with abstract layer. - * - * Note: Some chip revisions have hardware bug. Changing capture - * channel from full-duplex 8bit DMA to 16bit DMA will block - * 16bit DMA transfers from DSP chip (capture) until 8bit transfer - * to DSP chip (playback) starts. This bug can be avoided with - * "16bit DMA Allocation" setting set to Playback or Capture. - * - * - * 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 <asm/io.h> -#include <asm/dma.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/sb.h> -#include <sound/sb16_csp.h> -#include <sound/mpu401.h> -#include <sound/control.h> -#include <sound/info.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones"); -MODULE_LICENSE("GPL"); - -#ifdef CONFIG_SND_SB16_CSP -static void snd_sb16_csp_playback_prepare(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) && - ((1U << runtime->format) == csp->acc_format)) { - /* Supported runtime PCM format for playback */ - if (csp->ops.csp_use(csp) == 0) { - /* If CSP was successfully acquired */ - goto __start_CSP; - } - } else if ((csp->mode & SNDRV_SB_CSP_MODE_QSOUND) && (csp->q_enabled)) { - /* QSound decoder is loaded and enabled */ - if ((1 << runtime->format) & (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE)) { - /* Only for simple PCM formats */ - if (csp->ops.csp_use(csp) == 0) { - /* If CSP was successfully acquired */ - goto __start_CSP; - } - } - } - } else if (csp->ops.csp_use(csp) == 0) { - /* Acquire CSP and try to autoload hardware codec */ - if (csp->ops.csp_autoload(csp, runtime->format, SNDRV_SB_CSP_MODE_DSP_WRITE)) { - /* Unsupported format, release CSP */ - csp->ops.csp_unuse(csp); - } else { - __start_CSP: - /* Try to start CSP */ - if (csp->ops.csp_start(csp, (chip->mode & SB_MODE_PLAYBACK_16) ? - SNDRV_SB_CSP_SAMPLE_16BIT : SNDRV_SB_CSP_SAMPLE_8BIT, - (runtime->channels > 1) ? - SNDRV_SB_CSP_STEREO : SNDRV_SB_CSP_MONO)) { - /* Failed, release CSP */ - csp->ops.csp_unuse(csp); - } else { - /* Success, CSP acquired and running */ - chip->open = SNDRV_SB_CSP_MODE_DSP_WRITE; - } - } - } - } -} - -static void snd_sb16_csp_capture_prepare(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if ((csp->mode & SNDRV_SB_CSP_MODE_DSP_READ) && - ((1U << runtime->format) == csp->acc_format)) { - /* Supported runtime PCM format for capture */ - if (csp->ops.csp_use(csp) == 0) { - /* If CSP was successfully acquired */ - goto __start_CSP; - } - } - } else if (csp->ops.csp_use(csp) == 0) { - /* Acquire CSP and try to autoload hardware codec */ - if (csp->ops.csp_autoload(csp, runtime->format, SNDRV_SB_CSP_MODE_DSP_READ)) { - /* Unsupported format, release CSP */ - csp->ops.csp_unuse(csp); - } else { - __start_CSP: - /* Try to start CSP */ - if (csp->ops.csp_start(csp, (chip->mode & SB_MODE_CAPTURE_16) ? - SNDRV_SB_CSP_SAMPLE_16BIT : SNDRV_SB_CSP_SAMPLE_8BIT, - (runtime->channels > 1) ? - SNDRV_SB_CSP_STEREO : SNDRV_SB_CSP_MONO)) { - /* Failed, release CSP */ - csp->ops.csp_unuse(csp); - } else { - /* Success, CSP acquired and running */ - chip->open = SNDRV_SB_CSP_MODE_DSP_READ; - } - } - } - } -} - -static void snd_sb16_csp_update(struct snd_sb *chip) -{ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->qpos_changed) { - spin_lock(&chip->reg_lock); - csp->ops.csp_qsound_transfer (csp); - spin_unlock(&chip->reg_lock); - } - } -} - -static void snd_sb16_csp_playback_open(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - /* CSP decoders (QSound excluded) support only 16bit transfers */ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if (csp->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) { - runtime->hw.formats |= csp->acc_format; - } - } else { - /* autoloaded codecs */ - runtime->hw.formats |= SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM; - } - } -} - -static void snd_sb16_csp_playback_close(struct snd_sb *chip) -{ - if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_WRITE)) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->ops.csp_stop(csp) == 0) { - csp->ops.csp_unuse(csp); - chip->open = 0; - } - } -} - -static void snd_sb16_csp_capture_open(struct snd_sb *chip, struct snd_pcm_runtime *runtime) -{ - /* CSP coders support only 16bit transfers */ - if (chip->hardware == SB_HW_16CSP) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->running & SNDRV_SB_CSP_ST_LOADED) { - /* manually loaded codec */ - if (csp->mode & SNDRV_SB_CSP_MODE_DSP_READ) { - runtime->hw.formats |= csp->acc_format; - } - } else { - /* autoloaded codecs */ - runtime->hw.formats |= SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM; - } - } -} - -static void snd_sb16_csp_capture_close(struct snd_sb *chip) -{ - if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_READ)) { - struct snd_sb_csp *csp = chip->csp; - - if (csp->ops.csp_stop(csp) == 0) { - csp->ops.csp_unuse(csp); - chip->open = 0; - } - } -} -#else -#define snd_sb16_csp_playback_prepare(chip, runtime) /*nop*/ -#define snd_sb16_csp_capture_prepare(chip, runtime) /*nop*/ -#define snd_sb16_csp_update(chip) /*nop*/ -#define snd_sb16_csp_playback_open(chip, runtime) /*nop*/ -#define snd_sb16_csp_playback_close(chip) /*nop*/ -#define snd_sb16_csp_capture_open(chip, runtime) /*nop*/ -#define snd_sb16_csp_capture_close(chip) /*nop*/ -#endif - - -static void snd_sb16_setup_rate(struct snd_sb *chip, - unsigned short rate, - int channel) -{ - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->mode & (channel == SNDRV_PCM_STREAM_PLAYBACK ? SB_MODE_PLAYBACK_16 : SB_MODE_CAPTURE_16)) - snd_sb_ack_16bit(chip); - else - snd_sb_ack_8bit(chip); - if (!(chip->mode & SB_RATE_LOCK)) { - chip->locked_rate = rate; - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_IN); - snd_sbdsp_command(chip, rate >> 8); - snd_sbdsp_command(chip, rate & 0xff); - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_OUT); - snd_sbdsp_command(chip, rate >> 8); - snd_sbdsp_command(chip, rate & 0xff); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static int snd_sb16_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_sb16_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_sb16_playback_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned char format; - unsigned int size, count, dma; - - snd_sb16_csp_playback_prepare(chip, runtime); - if (snd_pcm_format_unsigned(runtime->format) > 0) { - format = runtime->channels > 1 ? SB_DSP4_MODE_UNS_STEREO : SB_DSP4_MODE_UNS_MONO; - } else { - format = runtime->channels > 1 ? SB_DSP4_MODE_SIGN_STEREO : SB_DSP4_MODE_SIGN_MONO; - } - - snd_sb16_setup_rate(chip, runtime->rate, SNDRV_PCM_STREAM_PLAYBACK); - size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream); - dma = (chip->mode & SB_MODE_PLAYBACK_8) ? chip->dma8 : chip->dma16; - snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - - count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->mode & SB_MODE_PLAYBACK_16) { - count >>= 1; - count--; - snd_sbdsp_command(chip, SB_DSP4_OUT16_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); - } else { - count--; - snd_sbdsp_command(chip, SB_DSP4_OUT8_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb16_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - chip->mode |= SB_RATE_LOCK_PLAYBACK; - snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); - /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ - if (chip->mode & SB_RATE_LOCK_CAPTURE) - snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - chip->mode &= ~SB_RATE_LOCK_PLAYBACK; - break; - default: - result = -EINVAL; - } - spin_unlock(&chip->reg_lock); - return result; -} - -static int snd_sb16_capture_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned char format; - unsigned int size, count, dma; - - snd_sb16_csp_capture_prepare(chip, runtime); - if (snd_pcm_format_unsigned(runtime->format) > 0) { - format = runtime->channels > 1 ? SB_DSP4_MODE_UNS_STEREO : SB_DSP4_MODE_UNS_MONO; - } else { - format = runtime->channels > 1 ? SB_DSP4_MODE_SIGN_STEREO : SB_DSP4_MODE_SIGN_MONO; - } - snd_sb16_setup_rate(chip, runtime->rate, SNDRV_PCM_STREAM_CAPTURE); - size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream); - dma = (chip->mode & SB_MODE_CAPTURE_8) ? chip->dma8 : chip->dma16; - snd_dma_program(dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - - count = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->mode & SB_MODE_CAPTURE_16) { - count >>= 1; - count--; - snd_sbdsp_command(chip, SB_DSP4_IN16_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); - } else { - count--; - snd_sbdsp_command(chip, SB_DSP4_IN8_AI); - snd_sbdsp_command(chip, format); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb16_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - int result = 0; - - spin_lock(&chip->reg_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - chip->mode |= SB_RATE_LOCK_CAPTURE; - snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF); - /* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */ - if (chip->mode & SB_RATE_LOCK_PLAYBACK) - snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON); - chip->mode &= ~SB_RATE_LOCK_CAPTURE; - break; - default: - result = -EINVAL; - } - spin_unlock(&chip->reg_lock); - return result; -} - -irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id) -{ - struct snd_sb *chip = dev_id; - unsigned char status; - int ok; - - spin_lock(&chip->mixer_lock); - status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS); - spin_unlock(&chip->mixer_lock); - if ((status & SB_IRQTYPE_MPUIN) && chip->rmidi_callback) - chip->rmidi_callback(irq, chip->rmidi->private_data); - if (status & SB_IRQTYPE_8BIT) { - ok = 0; - if (chip->mode & SB_MODE_PLAYBACK_8) { - snd_pcm_period_elapsed(chip->playback_substream); - snd_sb16_csp_update(chip); - ok++; - } - if (chip->mode & SB_MODE_CAPTURE_8) { - snd_pcm_period_elapsed(chip->capture_substream); - ok++; - } - spin_lock(&chip->reg_lock); - if (!ok) - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - snd_sb_ack_8bit(chip); - spin_unlock(&chip->reg_lock); - } - if (status & SB_IRQTYPE_16BIT) { - ok = 0; - if (chip->mode & SB_MODE_PLAYBACK_16) { - snd_pcm_period_elapsed(chip->playback_substream); - snd_sb16_csp_update(chip); - ok++; - } - if (chip->mode & SB_MODE_CAPTURE_16) { - snd_pcm_period_elapsed(chip->capture_substream); - ok++; - } - spin_lock(&chip->reg_lock); - if (!ok) - snd_sbdsp_command(chip, SB_DSP_DMA16_OFF); - snd_sb_ack_16bit(chip); - spin_unlock(&chip->reg_lock); - } - return IRQ_HANDLED; -} - -/* - - */ - -static snd_pcm_uframes_t snd_sb16_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int dma; - size_t ptr; - - dma = (chip->mode & SB_MODE_PLAYBACK_8) ? chip->dma8 : chip->dma16; - ptr = snd_dma_pointer(dma, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_sb16_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int dma; - size_t ptr; - - dma = (chip->mode & SB_MODE_CAPTURE_8) ? chip->dma8 : chip->dma16; - ptr = snd_dma_pointer(dma, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static struct snd_pcm_hardware snd_sb16_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = 0, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100, - .rate_min = 4000, - .rate_max = 44100, - .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, -}; - -static struct snd_pcm_hardware snd_sb16_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = 0, - .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_44100, - .rate_min = 4000, - .rate_max = 44100, - .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, -}; - -/* - * open/close - */ - -static int snd_sb16_playback_open(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->mode & SB_MODE_PLAYBACK) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - runtime->hw = snd_sb16_playback; - - /* skip if 16 bit DMA was reserved for capture */ - if (chip->force_mode16 & SB_MODE_CAPTURE_16) - goto __skip_16bit; - - if (chip->dma16 >= 0 && !(chip->mode & SB_MODE_CAPTURE_16)) { - chip->mode |= SB_MODE_PLAYBACK_16; - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - /* Vibra16X hack */ - if (chip->dma16 <= 3) { - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - } else { - snd_sb16_csp_playback_open(chip, runtime); - } - goto __open_ok; - } - - __skip_16bit: - if (chip->dma8 >= 0 && !(chip->mode & SB_MODE_CAPTURE_8)) { - chip->mode |= SB_MODE_PLAYBACK_8; - /* DSP v 4.xx can transfer 16bit data through 8bit DMA channel, SBHWPG 2-7 */ - if (chip->dma16 < 0) { - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - chip->mode |= SB_MODE_PLAYBACK_16; - } else { - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8; - } - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - goto __open_ok; - } - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - - __open_ok: - if (chip->hardware == SB_HW_ALS100) - runtime->hw.rate_max = 48000; - if (chip->hardware == SB_HW_CS5530) { - runtime->hw.buffer_bytes_max = 32 * 1024; - runtime->hw.periods_min = 2; - runtime->hw.rate_min = 44100; - } - if (chip->mode & SB_RATE_LOCK) - runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; - chip->playback_substream = substream; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -static int snd_sb16_playback_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - snd_sb16_csp_playback_close(chip); - spin_lock_irqsave(&chip->open_lock, flags); - chip->playback_substream = NULL; - chip->mode &= ~SB_MODE_PLAYBACK; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -static int snd_sb16_capture_open(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->mode & SB_MODE_CAPTURE) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - runtime->hw = snd_sb16_capture; - - /* skip if 16 bit DMA was reserved for playback */ - if (chip->force_mode16 & SB_MODE_PLAYBACK_16) - goto __skip_16bit; - - if (chip->dma16 >= 0 && !(chip->mode & SB_MODE_PLAYBACK_16)) { - chip->mode |= SB_MODE_CAPTURE_16; - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - /* Vibra16X hack */ - if (chip->dma16 <= 3) { - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - } else { - snd_sb16_csp_capture_open(chip, runtime); - } - goto __open_ok; - } - - __skip_16bit: - if (chip->dma8 >= 0 && !(chip->mode & SB_MODE_PLAYBACK_8)) { - chip->mode |= SB_MODE_CAPTURE_8; - /* DSP v 4.xx can transfer 16bit data through 8bit DMA channel, SBHWPG 2-7 */ - if (chip->dma16 < 0) { - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE; - chip->mode |= SB_MODE_CAPTURE_16; - } else { - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8; - } - runtime->hw.buffer_bytes_max = - runtime->hw.period_bytes_max = 64 * 1024; - goto __open_ok; - } - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - - __open_ok: - if (chip->hardware == SB_HW_ALS100) - runtime->hw.rate_max = 48000; - if (chip->hardware == SB_HW_CS5530) { - runtime->hw.buffer_bytes_max = 32 * 1024; - runtime->hw.periods_min = 2; - runtime->hw.rate_min = 44100; - } - if (chip->mode & SB_RATE_LOCK) - runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; - chip->capture_substream = substream; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -static int snd_sb16_capture_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - snd_sb16_csp_capture_close(chip); - spin_lock_irqsave(&chip->open_lock, flags); - chip->capture_substream = NULL; - chip->mode &= ~SB_MODE_CAPTURE; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -/* - * DMA control interface - */ - -static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what) -{ - if (chip->dma8 < 0 || chip->dma16 < 0) { - if (snd_BUG_ON(what)) - return -EINVAL; - return 0; - } - if (what == 0) { - chip->force_mode16 = 0; - } else if (what == 1) { - chip->force_mode16 = SB_MODE_PLAYBACK_16; - } else if (what == 2) { - chip->force_mode16 = SB_MODE_CAPTURE_16; - } else { - return -EINVAL; - } - return 0; -} - -static int snd_sb16_get_dma_mode(struct snd_sb *chip) -{ - if (chip->dma8 < 0 || chip->dma16 < 0) - return 0; - switch (chip->force_mode16) { - case SB_MODE_PLAYBACK_16: - return 1; - case SB_MODE_CAPTURE_16: - return 2; - default: - return 0; - } -} - -static int snd_sb16_dma_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static char *texts[3] = { - "Auto", "Playback", "Capture" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_sb16_dma_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.enumerated.item[0] = snd_sb16_get_dma_mode(chip); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char nval, oval; - int change; - - if ((nval = ucontrol->value.enumerated.item[0]) > 2) - return -EINVAL; - spin_lock_irqsave(&chip->reg_lock, flags); - oval = snd_sb16_get_dma_mode(chip); - change = nval != oval; - snd_sb16_set_dma_mode(chip, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -static struct snd_kcontrol_new snd_sb16_dma_control = { - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .name = "16-bit DMA Allocation", - .info = snd_sb16_dma_control_info, - .get = snd_sb16_dma_control_get, - .put = snd_sb16_dma_control_put -}; - -/* - * Initialization part - */ - -int snd_sb16dsp_configure(struct snd_sb * chip) -{ - unsigned long flags; - unsigned char irqreg = 0, dmareg = 0, mpureg; - unsigned char realirq, realdma, realmpureg; - /* note: mpu register should be present only on SB16 Vibra soundcards */ - - // printk(KERN_DEBUG "codec->irq=%i, codec->dma8=%i, codec->dma16=%i\n", chip->irq, chip->dma8, chip->dma16); - spin_lock_irqsave(&chip->mixer_lock, flags); - mpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP) & ~0x06; - spin_unlock_irqrestore(&chip->mixer_lock, flags); - switch (chip->irq) { - case 2: - case 9: - irqreg |= SB_IRQSETUP_IRQ9; - break; - case 5: - irqreg |= SB_IRQSETUP_IRQ5; - break; - case 7: - irqreg |= SB_IRQSETUP_IRQ7; - break; - case 10: - irqreg |= SB_IRQSETUP_IRQ10; - break; - default: - return -EINVAL; - } - if (chip->dma8 >= 0) { - switch (chip->dma8) { - case 0: - dmareg |= SB_DMASETUP_DMA0; - break; - case 1: - dmareg |= SB_DMASETUP_DMA1; - break; - case 3: - dmareg |= SB_DMASETUP_DMA3; - break; - default: - return -EINVAL; - } - } - if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) { - switch (chip->dma16) { - case 5: - dmareg |= SB_DMASETUP_DMA5; - break; - case 6: - dmareg |= SB_DMASETUP_DMA6; - break; - case 7: - dmareg |= SB_DMASETUP_DMA7; - break; - default: - return -EINVAL; - } - } - switch (chip->mpu_port) { - case 0x300: - mpureg |= 0x04; - break; - case 0x330: - mpureg |= 0x00; - break; - default: - mpureg |= 0x02; /* disable MPU */ - } - spin_lock_irqsave(&chip->mixer_lock, flags); - - snd_sbmixer_write(chip, SB_DSP4_IRQSETUP, irqreg); - realirq = snd_sbmixer_read(chip, SB_DSP4_IRQSETUP); - - snd_sbmixer_write(chip, SB_DSP4_DMASETUP, dmareg); - realdma = snd_sbmixer_read(chip, SB_DSP4_DMASETUP); - - snd_sbmixer_write(chip, SB_DSP4_MPUSETUP, mpureg); - realmpureg = snd_sbmixer_read(chip, SB_DSP4_MPUSETUP); - - spin_unlock_irqrestore(&chip->mixer_lock, flags); - if ((~realirq) & irqreg || (~realdma) & dmareg) { - snd_printk(KERN_ERR "SB16 [0x%lx]: unable to set DMA & IRQ (PnP device?)\n", chip->port); - snd_printk(KERN_ERR "SB16 [0x%lx]: wanted: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, realirq, realdma, realmpureg); - snd_printk(KERN_ERR "SB16 [0x%lx]: got: irqreg=0x%x, dmareg=0x%x, mpureg = 0x%x\n", chip->port, irqreg, dmareg, mpureg); - return -ENODEV; - } - return 0; -} - -static struct snd_pcm_ops snd_sb16_playback_ops = { - .open = snd_sb16_playback_open, - .close = snd_sb16_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb16_hw_params, - .hw_free = snd_sb16_hw_free, - .prepare = snd_sb16_playback_prepare, - .trigger = snd_sb16_playback_trigger, - .pointer = snd_sb16_playback_pointer, -}; - -static struct snd_pcm_ops snd_sb16_capture_ops = { - .open = snd_sb16_capture_open, - .close = snd_sb16_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb16_hw_params, - .hw_free = snd_sb16_hw_free, - .prepare = snd_sb16_capture_prepare, - .trigger = snd_sb16_capture_trigger, - .pointer = snd_sb16_capture_pointer, -}; - -int snd_sb16dsp_pcm(struct snd_sb * chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_card *card = chip->card; - struct snd_pcm *pcm; - int err; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm)) < 0) - return err; - sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); - pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops); - - if (chip->dma16 >= 0 && chip->dma8 != chip->dma16) - snd_ctl_add(card, snd_ctl_new1(&snd_sb16_dma_control, chip)); - else - pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, 128*1024); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -const struct snd_pcm_ops *snd_sb16dsp_get_pcm_ops(int direction) -{ - return direction == SNDRV_PCM_STREAM_PLAYBACK ? - &snd_sb16_playback_ops : &snd_sb16_capture_ops; -} - -EXPORT_SYMBOL(snd_sb16dsp_pcm); -EXPORT_SYMBOL(snd_sb16dsp_get_pcm_ops); -EXPORT_SYMBOL(snd_sb16dsp_configure); -EXPORT_SYMBOL(snd_sb16dsp_interrupt); - -/* - * INIT part - */ - -static int __init alsa_sb16_init(void) -{ - return 0; -} - -static void __exit alsa_sb16_exit(void) -{ -} - -module_init(alsa_sb16_init) -module_exit(alsa_sb16_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb8.c b/ANDROID_3.4.5/sound/isa/sb/sb8.c deleted file mode 100644 index ab5cebea..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb8.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Driver for SoundBlaster 1.0/2.0/Pro soundcards and compatible - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/sb.h> -#include <sound/opl3.h> -#include <sound/initval.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */ -static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3 */ - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for Sound Blaster soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for SB8 driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for SB8 driver."); -module_param_array(dma8, int, NULL, 0444); -MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver."); - -struct snd_sb8 { - struct resource *fm_res; /* used to block FM i/o region for legacy cards */ - struct snd_sb *chip; -}; - -static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id) -{ - struct snd_sb *chip = dev_id; - - if (chip->open & SB_OPEN_PCM) { - return snd_sb8dsp_interrupt(chip); - } else { - return snd_sb8dsp_midi_interrupt(chip); - } -} - -static void snd_sb8_free(struct snd_card *card) -{ - struct snd_sb8 *acard = card->private_data; - - if (acard == NULL) - return; - release_and_free_resource(acard->fm_res); -} - -static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev) -{ - if (!enable[dev]) - return 0; - if (irq[dev] == SNDRV_AUTO_IRQ) { - dev_err(pdev, "please specify irq\n"); - return 0; - } - if (dma8[dev] == SNDRV_AUTO_DMA) { - dev_err(pdev, "please specify dma8\n"); - return 0; - } - return 1; -} - -static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) -{ - struct snd_sb *chip; - struct snd_card *card; - struct snd_sb8 *acard; - struct snd_opl3 *opl3; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct snd_sb8), &card); - if (err < 0) - return err; - acard = card->private_data; - card->private_free = snd_sb8_free; - - /* block the 0x388 port to avoid PnP conflicts */ - acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); - - if (port[dev] != SNDRV_AUTO_PORT) { - if ((err = snd_sbdsp_create(card, port[dev], irq[dev], - snd_sb8_interrupt, - dma8[dev], - -1, - SB_HW_AUTO, - &chip)) < 0) - goto _err; - } else { - /* auto-probe legacy ports */ - static unsigned long possible_ports[] = { - 0x220, 0x240, 0x260, - }; - int i; - for (i = 0; i < ARRAY_SIZE(possible_ports); i++) { - err = snd_sbdsp_create(card, possible_ports[i], - irq[dev], - snd_sb8_interrupt, - dma8[dev], - -1, - SB_HW_AUTO, - &chip); - if (err >= 0) { - port[dev] = possible_ports[i]; - break; - } - } - if (i >= ARRAY_SIZE(possible_ports)) { - err = -EINVAL; - goto _err; - } - } - acard->chip = chip; - - if (chip->hardware >= SB_HW_16) { - if (chip->hardware == SB_HW_ALS100) - snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n", - port[dev]); - else - snd_printk(KERN_WARNING "SB 16 chip detected at 0x%lx, try snd-sb16 module\n", - port[dev]); - err = -ENODEV; - goto _err; - } - - if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) - goto _err; - - if ((err = snd_sbmixer_new(chip)) < 0) - goto _err; - - if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) { - if ((err = snd_opl3_create(card, chip->port + 8, 0, - OPL3_HW_AUTO, 1, - &opl3)) < 0) { - snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8); - } - } else { - if ((err = snd_opl3_create(card, chip->port, chip->port + 2, - OPL3_HW_AUTO, 1, - &opl3)) < 0) { - snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n", - chip->port, chip->port + 2); - } - } - if (err >= 0) { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) - goto _err; - } - - if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0) - goto _err; - - strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8"); - strcpy(card->shortname, chip->name); - sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", - chip->name, - chip->port, - irq[dev], dma8[dev]); - - snd_card_set_dev(card, pdev); - - if ((err = snd_card_register(card)) < 0) - goto _err; - - dev_set_drvdata(pdev, card); - return 0; - - _err: - snd_card_free(card); - return err; -} - -static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(pdev)); - dev_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef CONFIG_PM -static int snd_sb8_suspend(struct device *dev, unsigned int n, - pm_message_t state) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_sb8 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm); - snd_sbmixer_suspend(chip); - return 0; -} - -static int snd_sb8_resume(struct device *dev, unsigned int n) -{ - struct snd_card *card = dev_get_drvdata(dev); - struct snd_sb8 *acard = card->private_data; - struct snd_sb *chip = acard->chip; - - snd_sbdsp_reset(chip); - snd_sbmixer_resume(chip); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -#endif - -#define DEV_NAME "sb8" - -static struct isa_driver snd_sb8_driver = { - .match = snd_sb8_match, - .probe = snd_sb8_probe, - .remove = __devexit_p(snd_sb8_remove), -#ifdef CONFIG_PM - .suspend = snd_sb8_suspend, - .resume = snd_sb8_resume, -#endif - .driver = { - .name = DEV_NAME - }, -}; - -static int __init alsa_card_sb8_init(void) -{ - return isa_register_driver(&snd_sb8_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_sb8_exit(void) -{ - isa_unregister_driver(&snd_sb8_driver); -} - -module_init(alsa_card_sb8_init) -module_exit(alsa_card_sb8_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb8_main.c b/ANDROID_3.4.5/sound/isa/sb/sb8_main.c deleted file mode 100644 index 24d4121a..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb8_main.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Uros Bizjak <uros@kss-loka.si> - * - * Routines for control of 8-bit SoundBlaster cards and clones - * Please note: I don't have access to old SB8 soundcards. - * - * - * 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 - * - * -- - * - * Thu Apr 29 20:36:17 BST 1999 George David Morrison <gdm@gedamo.demon.co.uk> - * DSP can't respond to commands whilst in "high speed" mode. Caused - * glitching during playback. Fixed. - * - * Wed Jul 12 22:02:55 CEST 2000 Uros Bizjak <uros@kss-loka.si> - * Cleaned up and rewrote lowlevel routines. - */ - -#include <asm/io.h> -#include <asm/dma.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/sb.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>"); -MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones"); -MODULE_LICENSE("GPL"); - -#define SB8_CLOCK 1000000 -#define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v)) -#define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v)) - -static struct snd_ratnum clock = { - .num = SB8_CLOCK, - .den_min = 1, - .den_max = 256, - .den_step = 1, -}; - -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = { - .nrats = 1, - .rats = &clock, -}; - -static struct snd_ratnum stereo_clocks[] = { - { - .num = SB8_CLOCK, - .den_min = SB8_DEN(22050), - .den_max = SB8_DEN(22050), - .den_step = 1, - }, - { - .num = SB8_CLOCK, - .den_min = SB8_DEN(11025), - .den_max = SB8_DEN(11025), - .den_step = 1, - } -}; - -static int snd_sb8_hw_constraint_rate_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - if (c->min > 1) { - unsigned int num = 0, den = 0; - int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE), - 2, stereo_clocks, &num, &den); - if (err >= 0 && den) { - params->rate_num = num; - params->rate_den = den; - } - return err; - } - return 0; -} - -static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) { - struct snd_interval t = { .min = 1, .max = 1 }; - return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t); - } - return 0; -} - -static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int mixreg, rate, size, count; - unsigned char format; - unsigned char stereo = runtime->channels > 1; - int dma; - - rate = runtime->rate; - switch (chip->hardware) { - case SB_HW_JAZZ16: - if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) { - if (chip->mode & SB_MODE_CAPTURE_16) - return -EBUSY; - else - chip->mode |= SB_MODE_PLAYBACK_16; - } - chip->playback_format = SB_DSP_LO_OUTPUT_AUTO; - break; - case SB_HW_PRO: - if (runtime->channels > 1) { - if (snd_BUG_ON(rate != SB8_RATE(11025) && - rate != SB8_RATE(22050))) - return -EINVAL; - chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; - break; - } - /* fallthru */ - case SB_HW_201: - if (rate > 23000) { - chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; - break; - } - /* fallthru */ - case SB_HW_20: - chip->playback_format = SB_DSP_LO_OUTPUT_AUTO; - break; - case SB_HW_10: - chip->playback_format = SB_DSP_OUTPUT; - break; - default: - return -EINVAL; - } - if (chip->mode & SB_MODE_PLAYBACK_16) { - format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT; - dma = chip->dma16; - } else { - format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT; - chip->mode |= SB_MODE_PLAYBACK_8; - dma = chip->dma8; - } - size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream); - count = chip->p_period_size = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON); - if (chip->hardware == SB_HW_JAZZ16) - snd_sbdsp_command(chip, format); - else if (stereo) { - /* set playback stereo mode */ - spin_lock(&chip->mixer_lock); - mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW); - snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02); - spin_unlock(&chip->mixer_lock); - - /* Soundblaster hardware programming reference guide, 3-23 */ - snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT); - runtime->dma_area[0] = 0x80; - snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE); - /* force interrupt */ - snd_sbdsp_command(chip, SB_DSP_OUTPUT); - snd_sbdsp_command(chip, 0); - snd_sbdsp_command(chip, 0); - } - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); - if (stereo) { - snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); - spin_lock(&chip->mixer_lock); - /* save output filter status and turn it off */ - mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT); - snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20); - spin_unlock(&chip->mixer_lock); - /* just use force_mode16 for temporary storate... */ - chip->force_mode16 = mixreg; - } else { - snd_sbdsp_command(chip, 256 - runtime->rate_den); - } - if (chip->playback_format != SB_DSP_OUTPUT) { - if (chip->mode & SB_MODE_PLAYBACK_16) - count /= 2; - count--; - snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_dma_program(dma, runtime->dma_addr, - size, DMA_MODE_WRITE | DMA_AUTOINIT); - return 0; -} - -static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int count; - - spin_lock_irqsave(&chip->reg_lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_sbdsp_command(chip, chip->playback_format); - if (chip->playback_format == SB_DSP_OUTPUT) { - count = chip->p_period_size - 1; - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - break; - case SNDRV_PCM_TRIGGER_STOP: - if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) { - struct snd_pcm_runtime *runtime = substream->runtime; - snd_sbdsp_reset(chip); - if (runtime->channels > 1) { - spin_lock(&chip->mixer_lock); - /* restore output filter and set hardware to mono mode */ - snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02); - spin_unlock(&chip->mixer_lock); - } - } else { - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_sb8_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_sb8_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - return 0; -} - -static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int mixreg, rate, size, count; - unsigned char format; - unsigned char stereo = runtime->channels > 1; - int dma; - - rate = runtime->rate; - switch (chip->hardware) { - case SB_HW_JAZZ16: - if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) { - if (chip->mode & SB_MODE_PLAYBACK_16) - return -EBUSY; - else - chip->mode |= SB_MODE_CAPTURE_16; - } - chip->capture_format = SB_DSP_LO_INPUT_AUTO; - break; - case SB_HW_PRO: - if (runtime->channels > 1) { - if (snd_BUG_ON(rate != SB8_RATE(11025) && - rate != SB8_RATE(22050))) - return -EINVAL; - chip->capture_format = SB_DSP_HI_INPUT_AUTO; - break; - } - chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO; - break; - case SB_HW_201: - if (rate > 13000) { - chip->capture_format = SB_DSP_HI_INPUT_AUTO; - break; - } - /* fallthru */ - case SB_HW_20: - chip->capture_format = SB_DSP_LO_INPUT_AUTO; - break; - case SB_HW_10: - chip->capture_format = SB_DSP_INPUT; - break; - default: - return -EINVAL; - } - if (chip->mode & SB_MODE_CAPTURE_16) { - format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT; - dma = chip->dma16; - } else { - format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT; - chip->mode |= SB_MODE_CAPTURE_8; - dma = chip->dma8; - } - size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream); - count = chip->c_period_size = snd_pcm_lib_period_bytes(substream); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); - if (chip->hardware == SB_HW_JAZZ16) - snd_sbdsp_command(chip, format); - else if (stereo) - snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT); - snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE); - if (stereo) { - snd_sbdsp_command(chip, 256 - runtime->rate_den / 2); - spin_lock(&chip->mixer_lock); - /* save input filter status and turn it off */ - mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT); - snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20); - spin_unlock(&chip->mixer_lock); - /* just use force_mode16 for temporary storate... */ - chip->force_mode16 = mixreg; - } else { - snd_sbdsp_command(chip, 256 - runtime->rate_den); - } - if (chip->capture_format != SB_DSP_INPUT) { - if (chip->mode & SB_MODE_PLAYBACK_16) - count /= 2; - count--; - snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE); - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_dma_program(dma, runtime->dma_addr, - size, DMA_MODE_READ | DMA_AUTOINIT); - return 0; -} - -static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - unsigned int count; - - spin_lock_irqsave(&chip->reg_lock, flags); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - snd_sbdsp_command(chip, chip->capture_format); - if (chip->capture_format == SB_DSP_INPUT) { - count = chip->c_period_size - 1; - snd_sbdsp_command(chip, count & 0xff); - snd_sbdsp_command(chip, count >> 8); - } - break; - case SNDRV_PCM_TRIGGER_STOP: - if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) { - struct snd_pcm_runtime *runtime = substream->runtime; - snd_sbdsp_reset(chip); - if (runtime->channels > 1) { - /* restore input filter status */ - spin_lock(&chip->mixer_lock); - snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16); - spin_unlock(&chip->mixer_lock); - /* set hardware to mono mode */ - snd_sbdsp_command(chip, SB_DSP_MONO_8BIT); - } - } else { - snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); - } - snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - - snd_sb_ack_8bit(chip); - switch (chip->mode) { - case SB_MODE_PLAYBACK_16: /* ok.. playback is active */ - if (chip->hardware != SB_HW_JAZZ16) - break; - /* fallthru */ - case SB_MODE_PLAYBACK_8: - substream = chip->playback_substream; - runtime = substream->runtime; - if (chip->playback_format == SB_DSP_OUTPUT) - snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START); - snd_pcm_period_elapsed(substream); - break; - case SB_MODE_CAPTURE_16: - if (chip->hardware != SB_HW_JAZZ16) - break; - /* fallthru */ - case SB_MODE_CAPTURE_8: - substream = chip->capture_substream; - runtime = substream->runtime; - if (chip->capture_format == SB_DSP_INPUT) - snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START); - snd_pcm_period_elapsed(substream); - break; - } - return IRQ_HANDLED; -} - -static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - size_t ptr; - int dma; - - if (chip->mode & SB_MODE_PLAYBACK_8) - dma = chip->dma8; - else if (chip->mode & SB_MODE_PLAYBACK_16) - dma = chip->dma16; - else - return 0; - ptr = snd_dma_pointer(dma, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - size_t ptr; - int dma; - - if (chip->mode & SB_MODE_CAPTURE_8) - dma = chip->dma8; - else if (chip->mode & SB_MODE_CAPTURE_16) - dma = chip->dma16; - else - return 0; - ptr = snd_dma_pointer(dma, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static struct snd_pcm_hardware snd_sb8_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050), - .rate_min = 4000, - .rate_max = 23000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -static struct snd_pcm_hardware snd_sb8_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_U8, - .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_11025), - .rate_min = 4000, - .rate_max = 13000, - .channels_min = 1, - .channels_max = 1, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, - .fifo_size = 0, -}; - -/* - * - */ - -static int snd_sb8_open(struct snd_pcm_substream *substream) -{ - struct snd_sb *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_PCM; - spin_unlock_irqrestore(&chip->open_lock, flags); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - chip->playback_substream = substream; - runtime->hw = snd_sb8_playback; - } else { - chip->capture_substream = substream; - runtime->hw = snd_sb8_capture; - } - switch (chip->hardware) { - case SB_HW_JAZZ16: - if (chip->dma16 == 5 || chip->dma16 == 7) - runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE; - runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000; - runtime->hw.rate_min = 4000; - runtime->hw.rate_max = 50000; - runtime->hw.channels_max = 2; - break; - case SB_HW_PRO: - runtime->hw.rate_max = 44100; - runtime->hw.channels_max = 2; - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - snd_sb8_hw_constraint_rate_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, -1); - snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - snd_sb8_hw_constraint_channels_rate, NULL, - SNDRV_PCM_HW_PARAM_RATE, -1); - break; - case SB_HW_201: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - runtime->hw.rate_max = 44100; - } else { - runtime->hw.rate_max = 15000; - } - default: - break; - } - snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_clock); - if (chip->dma8 > 3 || chip->dma16 >= 0) { - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2); - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2); - runtime->hw.buffer_bytes_max = 128 * 1024 * 1024; - runtime->hw.period_bytes_max = 128 * 1024 * 1024; - } - return 0; -} - -static int snd_sb8_close(struct snd_pcm_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - chip->capture_substream = NULL; - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~SB_OPEN_PCM; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - chip->mode &= ~SB_MODE_PLAYBACK; - else - chip->mode &= ~SB_MODE_CAPTURE; - spin_unlock_irqrestore(&chip->open_lock, flags); - return 0; -} - -/* - * Initialization part - */ - -static struct snd_pcm_ops snd_sb8_playback_ops = { - .open = snd_sb8_open, - .close = snd_sb8_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb8_hw_params, - .hw_free = snd_sb8_hw_free, - .prepare = snd_sb8_playback_prepare, - .trigger = snd_sb8_playback_trigger, - .pointer = snd_sb8_playback_pointer, -}; - -static struct snd_pcm_ops snd_sb8_capture_ops = { - .open = snd_sb8_open, - .close = snd_sb8_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_sb8_hw_params, - .hw_free = snd_sb8_hw_free, - .prepare = snd_sb8_capture_prepare, - .trigger = snd_sb8_capture_trigger, - .pointer = snd_sb8_capture_pointer, -}; - -int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm) -{ - struct snd_card *card = chip->card; - struct snd_pcm *pcm; - int err; - size_t max_prealloc = 64 * 1024; - - if (rpcm) - *rpcm = NULL; - if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0) - return err; - sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); - pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; - pcm->private_data = chip; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops); - - if (chip->dma8 > 3 || chip->dma16 >= 0) - max_prealloc = 128 * 1024; - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, max_prealloc); - - if (rpcm) - *rpcm = pcm; - return 0; -} - -EXPORT_SYMBOL(snd_sb8dsp_pcm); -EXPORT_SYMBOL(snd_sb8dsp_interrupt); - /* sb8_midi.c */ -EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt); -EXPORT_SYMBOL(snd_sb8dsp_midi); - -/* - * INIT part - */ - -static int __init alsa_sb8_init(void) -{ - return 0; -} - -static void __exit alsa_sb8_exit(void) -{ -} - -module_init(alsa_sb8_init) -module_exit(alsa_sb8_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb8_midi.c b/ANDROID_3.4.5/sound/isa/sb/sb8_midi.c deleted file mode 100644 index 988a8b73..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb8_midi.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of SoundBlaster cards - MIDI interface - * - * 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 - * - * -- - * - * Sun May 9 22:54:38 BST 1999 George David Morrison <gdm@gedamo.demon.co.uk> - * Fixed typo in snd_sb8dsp_midi_new_device which prevented midi from - * working. - * - * Sun May 11 12:34:56 UTC 2003 Clemens Ladisch <clemens@ladisch.de> - * Added full duplex UART mode for DSP version 2.0 and later. - */ - -#include <asm/io.h> -#include <linux/time.h> -#include <sound/core.h> -#include <sound/sb.h> - - -irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip) -{ - struct snd_rawmidi *rmidi; - int max = 64; - char byte; - - if (!chip) - return IRQ_NONE; - - rmidi = chip->rmidi; - if (!rmidi) { - inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */ - return IRQ_NONE; - } - - spin_lock(&chip->midi_input_lock); - while (max-- > 0) { - if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { - byte = inb(SBP(chip, READ)); - if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) { - snd_rawmidi_receive(chip->midi_substream_input, &byte, 1); - } - } - } - spin_unlock(&chip->midi_input_lock); - return IRQ_HANDLED; -} - -static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - unsigned int valid_open_flags; - - chip = substream->rmidi->private_data; - valid_open_flags = chip->hardware >= SB_HW_20 - ? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open & ~valid_open_flags) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_MIDI_INPUT; - chip->midi_substream_input = substream; - if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - if (chip->hardware >= SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static int snd_sb8dsp_midi_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - unsigned int valid_open_flags; - - chip = substream->rmidi->private_data; - valid_open_flags = chip->hardware >= SB_HW_20 - ? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0; - spin_lock_irqsave(&chip->open_lock, flags); - if (chip->open & ~valid_open_flags) { - spin_unlock_irqrestore(&chip->open_lock, flags); - return -EAGAIN; - } - chip->open |= SB_OPEN_MIDI_OUTPUT; - chip->midi_substream_output = substream; - if (!(chip->open & SB_OPEN_MIDI_INPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - if (chip->hardware >= SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static int snd_sb8dsp_midi_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER); - chip->midi_substream_input = NULL; - if (!(chip->open & SB_OPEN_MIDI_OUTPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER); - chip->midi_substream_output = NULL; - if (!(chip->open & SB_OPEN_MIDI_INPUT)) { - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sbdsp_reset(chip); /* reset DSP */ - } else { - spin_unlock_irqrestore(&chip->open_lock, flags); - } - return 0; -} - -static void snd_sb8dsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - if (up) { - if (!(chip->open & SB_OPEN_MIDI_INPUT_TRIGGER)) { - if (chip->hardware < SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ); - chip->open |= SB_OPEN_MIDI_INPUT_TRIGGER; - } - } else { - if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) { - if (chip->hardware < SB_HW_20) - snd_sbdsp_command(chip, SB_DSP_MIDI_INPUT_IRQ); - chip->open &= ~SB_OPEN_MIDI_INPUT_TRIGGER; - } - } - spin_unlock_irqrestore(&chip->open_lock, flags); -} - -static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - struct snd_sb *chip; - char byte; - int max = 32; - - /* how big is Tx FIFO? */ - chip = substream->rmidi->private_data; - while (max-- > 0) { - spin_lock_irqsave(&chip->open_lock, flags); - if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) { - chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; - del_timer(&chip->midi_timer); - spin_unlock_irqrestore(&chip->open_lock, flags); - break; - } - if (chip->hardware >= SB_HW_20) { - int timeout = 8; - while ((inb(SBP(chip, STATUS)) & 0x80) != 0 && --timeout > 0) - ; - if (timeout == 0) { - /* Tx FIFO full - try again later */ - spin_unlock_irqrestore(&chip->open_lock, flags); - break; - } - outb(byte, SBP(chip, WRITE)); - } else { - snd_sbdsp_command(chip, SB_DSP_MIDI_OUTPUT); - snd_sbdsp_command(chip, byte); - } - snd_rawmidi_transmit_ack(substream, 1); - spin_unlock_irqrestore(&chip->open_lock, flags); - } -} - -static void snd_sb8dsp_midi_output_timer(unsigned long data) -{ - struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *) data; - struct snd_sb * chip = substream->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&chip->open_lock, flags); - chip->midi_timer.expires = 1 + jiffies; - add_timer(&chip->midi_timer); - spin_unlock_irqrestore(&chip->open_lock, flags); - snd_sb8dsp_midi_output_write(substream); -} - -static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - struct snd_sb *chip; - - chip = substream->rmidi->private_data; - spin_lock_irqsave(&chip->open_lock, flags); - if (up) { - if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) { - init_timer(&chip->midi_timer); - chip->midi_timer.function = snd_sb8dsp_midi_output_timer; - chip->midi_timer.data = (unsigned long) substream; - chip->midi_timer.expires = 1 + jiffies; - add_timer(&chip->midi_timer); - chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER; - } - } else { - if (chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER) { - chip->open &= ~SB_OPEN_MIDI_OUTPUT_TRIGGER; - } - } - spin_unlock_irqrestore(&chip->open_lock, flags); - - if (up) - snd_sb8dsp_midi_output_write(substream); -} - -static struct snd_rawmidi_ops snd_sb8dsp_midi_output = -{ - .open = snd_sb8dsp_midi_output_open, - .close = snd_sb8dsp_midi_output_close, - .trigger = snd_sb8dsp_midi_output_trigger, -}; - -static struct snd_rawmidi_ops snd_sb8dsp_midi_input = -{ - .open = snd_sb8dsp_midi_input_open, - .close = snd_sb8dsp_midi_input_close, - .trigger = snd_sb8dsp_midi_input_trigger, -}; - -int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawmidi) -{ - struct snd_rawmidi *rmidi; - int err; - - if (rrawmidi) - *rrawmidi = NULL; - if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0) - return err; - strcpy(rmidi->name, "SB8 MIDI"); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_sb8dsp_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_sb8dsp_midi_input); - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT; - if (chip->hardware >= SB_HW_20) - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; - rmidi->private_data = chip; - chip->rmidi = rmidi; - if (rrawmidi) - *rrawmidi = rmidi; - return 0; -} diff --git a/ANDROID_3.4.5/sound/isa/sb/sb_common.c b/ANDROID_3.4.5/sound/isa/sb/sb_common.c deleted file mode 100644 index 3ef99060..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb_common.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Uros Bizjak <uros@kss-loka.si> - * - * Lowlevel routines for control of Sound Blaster cards - * - * 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/slab.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/sb.h> -#include <sound/initval.h> - -#include <asm/io.h> -#include <asm/dma.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards"); -MODULE_LICENSE("GPL"); - -#define BUSY_LOOPS 100000 - -#undef IO_DEBUG - -int snd_sbdsp_command(struct snd_sb *chip, unsigned char val) -{ - int i; -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "command 0x%x\n", val); -#endif - for (i = BUSY_LOOPS; i; i--) - if ((inb(SBP(chip, STATUS)) & 0x80) == 0) { - outb(val, SBP(chip, COMMAND)); - return 1; - } - snd_printd("%s [0x%lx]: timeout (0x%x)\n", __func__, chip->port, val); - return 0; -} - -int snd_sbdsp_get_byte(struct snd_sb *chip) -{ - int val; - int i; - for (i = BUSY_LOOPS; i; i--) { - if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { - val = inb(SBP(chip, READ)); -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "get_byte 0x%x\n", val); -#endif - return val; - } - } - snd_printd("%s [0x%lx]: timeout\n", __func__, chip->port); - return -ENODEV; -} - -int snd_sbdsp_reset(struct snd_sb *chip) -{ - int i; - - outb(1, SBP(chip, RESET)); - udelay(10); - outb(0, SBP(chip, RESET)); - udelay(30); - for (i = BUSY_LOOPS; i; i--) - if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { - if (inb(SBP(chip, READ)) == 0xaa) - return 0; - else - break; - } - snd_printdd("%s [0x%lx] failed...\n", __func__, chip->port); - return -ENODEV; -} - -static int snd_sbdsp_version(struct snd_sb * chip) -{ - unsigned int result = -ENODEV; - - snd_sbdsp_command(chip, SB_DSP_GET_VERSION); - result = (short) snd_sbdsp_get_byte(chip) << 8; - result |= (short) snd_sbdsp_get_byte(chip); - return result; -} - -static int snd_sbdsp_probe(struct snd_sb * chip) -{ - int version; - int major, minor; - char *str; - unsigned long flags; - - /* - * initialization sequence - */ - - spin_lock_irqsave(&chip->reg_lock, flags); - if (snd_sbdsp_reset(chip) < 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - version = snd_sbdsp_version(chip); - if (version < 0) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return -ENODEV; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - major = version >> 8; - minor = version & 0xff; - snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n", - chip->port, major, minor); - - switch (chip->hardware) { - case SB_HW_AUTO: - switch (major) { - case 1: - chip->hardware = SB_HW_10; - str = "1.0"; - break; - case 2: - if (minor) { - chip->hardware = SB_HW_201; - str = "2.01+"; - } else { - chip->hardware = SB_HW_20; - str = "2.0"; - } - break; - case 3: - chip->hardware = SB_HW_PRO; - str = "Pro"; - break; - case 4: - chip->hardware = SB_HW_16; - str = "16"; - break; - default: - snd_printk(KERN_INFO "SB [0x%lx]: unknown DSP chip version %i.%i\n", - chip->port, major, minor); - return -ENODEV; - } - break; - case SB_HW_ALS100: - str = "16 (ALS-100)"; - break; - case SB_HW_ALS4000: - str = "16 (ALS-4000)"; - break; - case SB_HW_DT019X: - str = "(DT019X/ALS007)"; - break; - case SB_HW_CS5530: - str = "16 (CS5530)"; - break; - case SB_HW_JAZZ16: - str = "Pro (Jazz16)"; - break; - default: - return -ENODEV; - } - sprintf(chip->name, "Sound Blaster %s", str); - chip->version = (major << 8) | minor; - return 0; -} - -static int snd_sbdsp_free(struct snd_sb *chip) -{ - if (chip->res_port) - release_and_free_resource(chip->res_port); - if (chip->irq >= 0) - free_irq(chip->irq, (void *) chip); -#ifdef CONFIG_ISA - if (chip->dma8 >= 0) { - disable_dma(chip->dma8); - free_dma(chip->dma8); - } - if (chip->dma16 >= 0 && chip->dma16 != chip->dma8) { - disable_dma(chip->dma16); - free_dma(chip->dma16); - } -#endif - kfree(chip); - return 0; -} - -static int snd_sbdsp_dev_free(struct snd_device *device) -{ - struct snd_sb *chip = device->device_data; - return snd_sbdsp_free(chip); -} - -int snd_sbdsp_create(struct snd_card *card, - unsigned long port, - int irq, - irq_handler_t irq_handler, - int dma8, - int dma16, - unsigned short hardware, - struct snd_sb **r_chip) -{ - struct snd_sb *chip; - int err; - static struct snd_device_ops ops = { - .dev_free = snd_sbdsp_dev_free, - }; - - if (snd_BUG_ON(!r_chip)) - return -EINVAL; - *r_chip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->reg_lock); - spin_lock_init(&chip->open_lock); - spin_lock_init(&chip->midi_input_lock); - spin_lock_init(&chip->mixer_lock); - chip->irq = -1; - chip->dma8 = -1; - chip->dma16 = -1; - chip->port = port; - - if (request_irq(irq, irq_handler, - (hardware == SB_HW_ALS4000 || - hardware == SB_HW_CS5530) ? - IRQF_SHARED : 0, - "SoundBlaster", (void *) chip)) { - snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); - snd_sbdsp_free(chip); - return -EBUSY; - } - chip->irq = irq; - - if (hardware == SB_HW_ALS4000) - goto __skip_allocation; - - if ((chip->res_port = request_region(port, 16, "SoundBlaster")) == NULL) { - snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port); - snd_sbdsp_free(chip); - return -EBUSY; - } - -#ifdef CONFIG_ISA - if (dma8 >= 0 && request_dma(dma8, "SoundBlaster - 8bit")) { - snd_printk(KERN_ERR "sb: can't grab DMA8 %d\n", dma8); - snd_sbdsp_free(chip); - return -EBUSY; - } - chip->dma8 = dma8; - if (dma16 >= 0) { - if (hardware != SB_HW_ALS100 && (dma16 < 5 || dma16 > 7)) { - /* no duplex */ - dma16 = -1; - } else if (request_dma(dma16, "SoundBlaster - 16bit")) { - snd_printk(KERN_ERR "sb: can't grab DMA16 %d\n", dma16); - snd_sbdsp_free(chip); - return -EBUSY; - } - } - chip->dma16 = dma16; -#endif - - __skip_allocation: - chip->card = card; - chip->hardware = hardware; - if ((err = snd_sbdsp_probe(chip)) < 0) { - snd_sbdsp_free(chip); - return err; - } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_sbdsp_free(chip); - return err; - } - *r_chip = chip; - return 0; -} - -EXPORT_SYMBOL(snd_sbdsp_command); -EXPORT_SYMBOL(snd_sbdsp_get_byte); -EXPORT_SYMBOL(snd_sbdsp_reset); -EXPORT_SYMBOL(snd_sbdsp_create); -/* sb_mixer.c */ -EXPORT_SYMBOL(snd_sbmixer_write); -EXPORT_SYMBOL(snd_sbmixer_read); -EXPORT_SYMBOL(snd_sbmixer_new); -EXPORT_SYMBOL(snd_sbmixer_add_ctl); -#ifdef CONFIG_PM -EXPORT_SYMBOL(snd_sbmixer_suspend); -EXPORT_SYMBOL(snd_sbmixer_resume); -#endif - -/* - * INIT part - */ - -static int __init alsa_sb_common_init(void) -{ - return 0; -} - -static void __exit alsa_sb_common_exit(void) -{ -} - -module_init(alsa_sb_common_init) -module_exit(alsa_sb_common_exit) diff --git a/ANDROID_3.4.5/sound/isa/sb/sb_mixer.c b/ANDROID_3.4.5/sound/isa/sb/sb_mixer.c deleted file mode 100644 index 6496822c..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sb_mixer.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for Sound Blaster mixer control - * - * - * 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 <asm/io.h> -#include <linux/delay.h> -#include <linux/time.h> -#include <sound/core.h> -#include <sound/sb.h> -#include <sound/control.h> - -#undef IO_DEBUG - -void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data) -{ - outb(reg, SBP(chip, MIXER_ADDR)); - udelay(10); - outb(data, SBP(chip, MIXER_DATA)); - udelay(10); -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "mixer_write 0x%x 0x%x\n", reg, data); -#endif -} - -unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg) -{ - unsigned char result; - - outb(reg, SBP(chip, MIXER_ADDR)); - udelay(10); - result = inb(SBP(chip, MIXER_DATA)); - udelay(10); -#ifdef IO_DEBUG - snd_printk(KERN_DEBUG "mixer_read 0x%x 0x%x\n", reg, result); -#endif - return result; -} - -/* - * Single channel mixer element - */ - -static int snd_sbmixer_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 16) & 0xff; - int mask = (kcontrol->private_value >> 24) & 0xff; - unsigned char val; - - spin_lock_irqsave(&sb->mixer_lock, flags); - val = (snd_sbmixer_read(sb, reg) >> shift) & mask; - spin_unlock_irqrestore(&sb->mixer_lock, flags); - ucontrol->value.integer.value[0] = val; - return 0; -} - -static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 16) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned char val, oval; - - val = (ucontrol->value.integer.value[0] & mask) << shift; - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, reg); - val = (oval & ~(mask << shift)) | val; - change = val != oval; - if (change) - snd_sbmixer_write(sb, reg, val); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * Double channel mixer element - */ - -static int snd_sbmixer_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x07; - int right_shift = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - unsigned char left, right; - - spin_lock_irqsave(&sb->mixer_lock, flags); - left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask; - right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask; - spin_unlock_irqrestore(&sb->mixer_lock, flags); - ucontrol->value.integer.value[0] = left; - ucontrol->value.integer.value[1] = right; - return 0; -} - -static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x07; - int right_shift = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned char left, right, oleft, oright; - - left = (ucontrol->value.integer.value[0] & mask) << left_shift; - right = (ucontrol->value.integer.value[1] & mask) << right_shift; - spin_lock_irqsave(&sb->mixer_lock, flags); - if (left_reg == right_reg) { - oleft = snd_sbmixer_read(sb, left_reg); - left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right; - change = left != oleft; - if (change) - snd_sbmixer_write(sb, left_reg, left); - } else { - oleft = snd_sbmixer_read(sb, left_reg); - oright = snd_sbmixer_read(sb, right_reg); - left = (oleft & ~(mask << left_shift)) | left; - right = (oright & ~(mask << right_shift)) | right; - change = left != oleft || right != oright; - if (change) { - snd_sbmixer_write(sb, left_reg, left); - snd_sbmixer_write(sb, right_reg, right); - } - } - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * DT-019x / ALS-007 capture/input switch - */ - -static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[5] = { - "CD", "Mic", "Line", "Synth", "Master" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - switch (oval & 0x07) { - case SB_DT019X_CAP_CD: - ucontrol->value.enumerated.item[0] = 0; - break; - case SB_DT019X_CAP_MIC: - ucontrol->value.enumerated.item[0] = 1; - break; - case SB_DT019X_CAP_LINE: - ucontrol->value.enumerated.item[0] = 2; - break; - case SB_DT019X_CAP_MAIN: - ucontrol->value.enumerated.item[0] = 4; - break; - /* To record the synth on these cards you must record the main. */ - /* Thus SB_DT019X_CAP_SYNTH == SB_DT019X_CAP_MAIN and would cause */ - /* duplicate case labels if left uncommented. */ - /* case SB_DT019X_CAP_SYNTH: - * ucontrol->value.enumerated.item[0] = 3; - * break; - */ - default: - ucontrol->value.enumerated.item[0] = 4; - break; - } - return 0; -} - -static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval, oval; - - if (ucontrol->value.enumerated.item[0] > 4) - return -EINVAL; - switch (ucontrol->value.enumerated.item[0]) { - case 0: - nval = SB_DT019X_CAP_CD; - break; - case 1: - nval = SB_DT019X_CAP_MIC; - break; - case 2: - nval = SB_DT019X_CAP_LINE; - break; - case 3: - nval = SB_DT019X_CAP_SYNTH; - break; - case 4: - nval = SB_DT019X_CAP_MAIN; - break; - default: - nval = SB_DT019X_CAP_MAIN; - } - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW); - change = nval != oval; - if (change) - snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * ALS4000 mono recording control switch - */ - -static int snd_als4k_mono_capture_route_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[3] = { - "L chan only", "R chan only", "L ch/2 + R ch/2" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - oval >>= 6; - if (oval > 2) - oval = 2; - - ucontrol->value.enumerated.item[0] = oval; - return 0; -} - -static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval, oval; - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL); - - nval = (oval & ~(3 << 6)) - | (ucontrol->value.enumerated.item[0] << 6); - change = nval != oval; - if (change) - snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * SBPRO input multiplexer - */ - -static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - static const char *texts[3] = { - "Mic", "CD", "Line" - }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 3; - if (uinfo->value.enumerated.item > 2) - uinfo->value.enumerated.item = 2; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); - return 0; -} - - -static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned char oval; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - switch ((oval >> 0x01) & 0x03) { - case SB_DSP_MIXS_CD: - ucontrol->value.enumerated.item[0] = 1; - break; - case SB_DSP_MIXS_LINE: - ucontrol->value.enumerated.item[0] = 2; - break; - default: - ucontrol->value.enumerated.item[0] = 0; - break; - } - return 0; -} - -static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int change; - unsigned char nval, oval; - - if (ucontrol->value.enumerated.item[0] > 2) - return -EINVAL; - switch (ucontrol->value.enumerated.item[0]) { - case 1: - nval = SB_DSP_MIXS_CD; - break; - case 2: - nval = SB_DSP_MIXS_LINE; - break; - default: - nval = SB_DSP_MIXS_MIC; - } - nval <<= 1; - spin_lock_irqsave(&sb->mixer_lock, flags); - oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE); - nval |= oval & ~0x06; - change = nval != oval; - if (change) - snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - -/* - * SB16 input switch - */ - -static int snd_sb16mixer_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 4; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg1 = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x0f; - int right_shift = (kcontrol->private_value >> 24) & 0x0f; - unsigned char val1, val2; - - spin_lock_irqsave(&sb->mixer_lock, flags); - val1 = snd_sbmixer_read(sb, reg1); - val2 = snd_sbmixer_read(sb, reg2); - spin_unlock_irqrestore(&sb->mixer_lock, flags); - ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01; - ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01; - ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01; - ucontrol->value.integer.value[3] = (val2 >> right_shift) & 0x01; - return 0; -} - -static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) -{ - struct snd_sb *sb = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg1 = kcontrol->private_value & 0xff; - int reg2 = (kcontrol->private_value >> 8) & 0xff; - int left_shift = (kcontrol->private_value >> 16) & 0x0f; - int right_shift = (kcontrol->private_value >> 24) & 0x0f; - int change; - unsigned char val1, val2, oval1, oval2; - - spin_lock_irqsave(&sb->mixer_lock, flags); - oval1 = snd_sbmixer_read(sb, reg1); - oval2 = snd_sbmixer_read(sb, reg2); - val1 = oval1 & ~((1 << left_shift) | (1 << right_shift)); - val2 = oval2 & ~((1 << left_shift) | (1 << right_shift)); - val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift; - val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift; - val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift; - val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift; - change = val1 != oval1 || val2 != oval2; - if (change) { - snd_sbmixer_write(sb, reg1, val1); - snd_sbmixer_write(sb, reg2, val2); - } - spin_unlock_irqrestore(&sb->mixer_lock, flags); - return change; -} - - -/* - */ -/* - */ -int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value) -{ - static struct snd_kcontrol_new newctls[] = { - [SB_MIX_SINGLE] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sbmixer_info_single, - .get = snd_sbmixer_get_single, - .put = snd_sbmixer_put_single, - }, - [SB_MIX_DOUBLE] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sbmixer_info_double, - .get = snd_sbmixer_get_double, - .put = snd_sbmixer_put_double, - }, - [SB_MIX_INPUT_SW] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sb16mixer_info_input_sw, - .get = snd_sb16mixer_get_input_sw, - .put = snd_sb16mixer_put_input_sw, - }, - [SB_MIX_CAPTURE_PRO] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_sb8mixer_info_mux, - .get = snd_sb8mixer_get_mux, - .put = snd_sb8mixer_put_mux, - }, - [SB_MIX_CAPTURE_DT019X] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_dt019x_input_sw_info, - .get = snd_dt019x_input_sw_get, - .put = snd_dt019x_input_sw_put, - }, - [SB_MIX_MONO_CAPTURE_ALS4K] = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_als4k_mono_capture_route_info, - .get = snd_als4k_mono_capture_route_get, - .put = snd_als4k_mono_capture_route_put, - }, - }; - struct snd_kcontrol *ctl; - int err; - - ctl = snd_ctl_new1(&newctls[type], chip); - if (! ctl) - return -ENOMEM; - strlcpy(ctl->id.name, name, sizeof(ctl->id.name)); - ctl->id.index = index; - ctl->private_value = value; - if ((err = snd_ctl_add(chip->card, ctl)) < 0) - return err; - return 0; -} - -/* - * SB 2.0 specific mixer elements - */ - -static struct sbmix_elem snd_sb20_controls[] = { - SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7), - SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3), - SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7), - SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7) -}; - -static unsigned char snd_sb20_init_values[][2] = { - { SB_DSP20_MASTER_DEV, 0 }, - { SB_DSP20_FM_DEV, 0 }, -}; - -/* - * SB Pro specific mixer elements - */ -static struct sbmix_elem snd_sbpro_controls[] = { - SB_DOUBLE("Master Playback Volume", - SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7), - SB_DOUBLE("PCM Playback Volume", - SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7), - SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1), - SB_DOUBLE("Synth Playback Volume", - SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7), - SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7), - SB_DOUBLE("Line Playback Volume", - SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7), - SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3), - { - .name = "Capture Source", - .type = SB_MIX_CAPTURE_PRO - }, - SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1), - SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1) -}; - -static unsigned char snd_sbpro_init_values[][2] = { - { SB_DSP_MASTER_DEV, 0 }, - { SB_DSP_PCM_DEV, 0 }, - { SB_DSP_FM_DEV, 0 }, -}; - -/* - * SB16 specific mixer elements - */ -static struct sbmix_elem snd_sb16_controls[] = { - SB_DOUBLE("Master Playback Volume", - SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31), - SB_DOUBLE("PCM Playback Volume", - SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31), - SB16_INPUT_SW("Synth Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5), - SB_DOUBLE("Synth Playback Volume", - SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31), - SB16_INPUT_SW("CD Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1), - SB_DOUBLE("CD Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1), - SB_DOUBLE("CD Playback Volume", - SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31), - SB16_INPUT_SW("Mic Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0), - SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), - SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), - SB_SINGLE("Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3), - SB_DOUBLE("Capture Volume", - SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3), - SB_DOUBLE("Playback Volume", - SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3), - SB16_INPUT_SW("Line Capture Route", - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3), - SB_DOUBLE("Line Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1), - SB_DOUBLE("Line Playback Volume", - SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31), - SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1), - SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1), - SB_DOUBLE("Tone Control - Bass", - SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15), - SB_DOUBLE("Tone Control - Treble", - SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15) -}; - -static unsigned char snd_sb16_init_values[][2] = { - { SB_DSP4_MASTER_DEV + 0, 0 }, - { SB_DSP4_MASTER_DEV + 1, 0 }, - { SB_DSP4_PCM_DEV + 0, 0 }, - { SB_DSP4_PCM_DEV + 1, 0 }, - { SB_DSP4_SYNTH_DEV + 0, 0 }, - { SB_DSP4_SYNTH_DEV + 1, 0 }, - { SB_DSP4_INPUT_LEFT, 0 }, - { SB_DSP4_INPUT_RIGHT, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DSP4_SPEAKER_DEV, 0 }, -}; - -/* - * DT019x specific mixer elements - */ -static struct sbmix_elem snd_dt019x_controls[] = { - /* ALS4000 below has some parts which we might be lacking, - * e.g. snd_als4000_ctl_mono_playback_switch - check it! */ - SB_DOUBLE("Master Playback Volume", - SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4, 0, 15), - SB_DOUBLE("PCM Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1), - SB_DOUBLE("PCM Playback Volume", - SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4, 0, 15), - SB_DOUBLE("Synth Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1), - SB_DOUBLE("Synth Playback Volume", - SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4, 0, 15), - SB_DOUBLE("CD Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1), - SB_DOUBLE("CD Playback Volume", - SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4, 0, 15), - SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1), - SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7), - SB_SINGLE("Beep Volume", SB_DT019X_SPKR_DEV, 0, 7), - SB_DOUBLE("Line Playback Switch", - SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1), - SB_DOUBLE("Line Playback Volume", - SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4, 0, 15), - { - .name = "Capture Source", - .type = SB_MIX_CAPTURE_DT019X - } -}; - -static unsigned char snd_dt019x_init_values[][2] = { - { SB_DT019X_MASTER_DEV, 0 }, - { SB_DT019X_PCM_DEV, 0 }, - { SB_DT019X_SYNTH_DEV, 0 }, - { SB_DT019X_CD_DEV, 0 }, - { SB_DT019X_MIC_DEV, 0 }, /* Includes PC-speaker in high nibble */ - { SB_DT019X_LINE_DEV, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DT019X_OUTPUT_SW2, 0 }, - { SB_DT019X_CAPTURE_SW, 0x06 }, -}; - -/* - * ALS4000 specific mixer elements - */ -static struct sbmix_elem snd_als4000_controls[] = { - SB_DOUBLE("PCM Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1), - SB_DOUBLE("Synth Playback Switch", - SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4, 3, 1), - SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03), - SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1), - { - .name = "Master Mono Capture Route", - .type = SB_MIX_MONO_CAPTURE_ALS4K - }, - SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1), - SB_SINGLE("Analog Loopback Switch", SB_ALS4000_MIC_IN_GAIN, 7, 0x01), - SB_SINGLE("3D Control - Switch", SB_ALS4000_3D_SND_FX, 6, 0x01), - SB_SINGLE("Digital Loopback Switch", - SB_ALS4000_CR3_CONFIGURATION, 7, 0x01), - /* FIXME: functionality of 3D controls might be swapped, I didn't find - * a description of how to identify what is supposed to be what */ - SB_SINGLE("3D Control - Level", SB_ALS4000_3D_SND_FX, 0, 0x07), - /* FIXME: maybe there's actually some standard 3D ctrl name for it?? */ - SB_SINGLE("3D Control - Freq", SB_ALS4000_3D_SND_FX, 4, 0x03), - /* FIXME: ALS4000a.pdf mentions BBD (Bucket Brigade Device) time delay, - * but what ALSA 3D attribute is that actually? "Center", "Depth", - * "Wide" or "Space" or even "Level"? Assuming "Wide" for now... */ - SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f), - SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01), - SB_SINGLE("Master Playback 8kHz / 20kHz LPF Switch", - SB_ALS4000_FMDAC, 5, 0x01), -#ifdef NOT_AVAILABLE - SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01), - SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f), -#endif -}; - -static unsigned char snd_als4000_init_values[][2] = { - { SB_DSP4_MASTER_DEV + 0, 0 }, - { SB_DSP4_MASTER_DEV + 1, 0 }, - { SB_DSP4_PCM_DEV + 0, 0 }, - { SB_DSP4_PCM_DEV + 1, 0 }, - { SB_DSP4_SYNTH_DEV + 0, 0 }, - { SB_DSP4_SYNTH_DEV + 1, 0 }, - { SB_DSP4_SPEAKER_DEV, 0 }, - { SB_DSP4_OUTPUT_SW, 0 }, - { SB_DSP4_INPUT_LEFT, 0 }, - { SB_DSP4_INPUT_RIGHT, 0 }, - { SB_DT019X_OUTPUT_SW2, 0 }, - { SB_ALS4000_MIC_IN_GAIN, 0 }, -}; - -/* - */ -static int snd_sbmixer_init(struct snd_sb *chip, - struct sbmix_elem *controls, - int controls_count, - unsigned char map[][2], - int map_count, - char *name) -{ - unsigned long flags; - struct snd_card *card = chip->card; - int idx, err; - - /* mixer reset */ - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, 0x00, 0x00); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - - /* mute and zero volume channels */ - for (idx = 0; idx < map_count; idx++) { - spin_lock_irqsave(&chip->mixer_lock, flags); - snd_sbmixer_write(chip, map[idx][0], map[idx][1]); - spin_unlock_irqrestore(&chip->mixer_lock, flags); - } - - for (idx = 0; idx < controls_count; idx++) { - err = snd_sbmixer_add_ctl_elem(chip, &controls[idx]); - if (err < 0) - return err; - } - snd_component_add(card, name); - strcpy(card->mixername, name); - return 0; -} - -int snd_sbmixer_new(struct snd_sb *chip) -{ - struct snd_card *card; - int err; - - if (snd_BUG_ON(!chip || !chip->card)) - return -EINVAL; - - card = chip->card; - - switch (chip->hardware) { - case SB_HW_10: - return 0; /* no mixer chip on SB1.x */ - case SB_HW_20: - case SB_HW_201: - if ((err = snd_sbmixer_init(chip, - snd_sb20_controls, - ARRAY_SIZE(snd_sb20_controls), - snd_sb20_init_values, - ARRAY_SIZE(snd_sb20_init_values), - "CTL1335")) < 0) - return err; - break; - case SB_HW_PRO: - case SB_HW_JAZZ16: - if ((err = snd_sbmixer_init(chip, - snd_sbpro_controls, - ARRAY_SIZE(snd_sbpro_controls), - snd_sbpro_init_values, - ARRAY_SIZE(snd_sbpro_init_values), - "CTL1345")) < 0) - return err; - break; - case SB_HW_16: - case SB_HW_ALS100: - case SB_HW_CS5530: - if ((err = snd_sbmixer_init(chip, - snd_sb16_controls, - ARRAY_SIZE(snd_sb16_controls), - snd_sb16_init_values, - ARRAY_SIZE(snd_sb16_init_values), - "CTL1745")) < 0) - return err; - break; - case SB_HW_ALS4000: - /* use only the first 16 controls from SB16 */ - err = snd_sbmixer_init(chip, - snd_sb16_controls, - 16, - snd_sb16_init_values, - ARRAY_SIZE(snd_sb16_init_values), - "ALS4000"); - if (err < 0) - return err; - if ((err = snd_sbmixer_init(chip, - snd_als4000_controls, - ARRAY_SIZE(snd_als4000_controls), - snd_als4000_init_values, - ARRAY_SIZE(snd_als4000_init_values), - "ALS4000")) < 0) - return err; - break; - case SB_HW_DT019X: - if ((err = snd_sbmixer_init(chip, - snd_dt019x_controls, - ARRAY_SIZE(snd_dt019x_controls), - snd_dt019x_init_values, - ARRAY_SIZE(snd_dt019x_init_values), - "DT019X")) < 0) - break; - default: - strcpy(card->mixername, "???"); - } - return 0; -} - -#ifdef CONFIG_PM -static unsigned char sb20_saved_regs[] = { - SB_DSP20_MASTER_DEV, - SB_DSP20_PCM_DEV, - SB_DSP20_FM_DEV, - SB_DSP20_CD_DEV, -}; - -static unsigned char sbpro_saved_regs[] = { - SB_DSP_MASTER_DEV, - SB_DSP_PCM_DEV, - SB_DSP_PLAYBACK_FILT, - SB_DSP_FM_DEV, - SB_DSP_CD_DEV, - SB_DSP_LINE_DEV, - SB_DSP_MIC_DEV, - SB_DSP_CAPTURE_SOURCE, - SB_DSP_CAPTURE_FILT, -}; - -static unsigned char sb16_saved_regs[] = { - SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, - SB_DSP4_3DSE, - SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1, - SB_DSP4_TREBLE_DEV, SB_DSP4_TREBLE_DEV + 1, - SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, - SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, - SB_DSP4_OUTPUT_SW, - SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, - SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1, - SB_DSP4_MIC_DEV, - SB_DSP4_SPEAKER_DEV, - SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, - SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1, - SB_DSP4_MIC_AGC -}; - -static unsigned char dt019x_saved_regs[] = { - SB_DT019X_MASTER_DEV, - SB_DT019X_PCM_DEV, - SB_DT019X_SYNTH_DEV, - SB_DT019X_CD_DEV, - SB_DT019X_MIC_DEV, - SB_DT019X_SPKR_DEV, - SB_DT019X_LINE_DEV, - SB_DSP4_OUTPUT_SW, - SB_DT019X_OUTPUT_SW2, - SB_DT019X_CAPTURE_SW, -}; - -static unsigned char als4000_saved_regs[] = { - /* please verify in dsheet whether regs to be added - are actually real H/W or just dummy */ - SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, - SB_DSP4_OUTPUT_SW, - SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, - SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, - SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, - SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, - SB_DSP4_MIC_DEV, - SB_DSP4_SPEAKER_DEV, - SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1, - SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1, - SB_DT019X_OUTPUT_SW2, - SB_ALS4000_MONO_IO_CTRL, - SB_ALS4000_MIC_IN_GAIN, - SB_ALS4000_FMDAC, - SB_ALS4000_3D_SND_FX, - SB_ALS4000_3D_TIME_DELAY, - SB_ALS4000_CR3_CONFIGURATION, -}; - -static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) -{ - unsigned char *val = chip->saved_regs; - if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs))) - return; - for (; num_regs; num_regs--) - *val++ = snd_sbmixer_read(chip, *regs++); -} - -static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs) -{ - unsigned char *val = chip->saved_regs; - if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs))) - return; - for (; num_regs; num_regs--) - snd_sbmixer_write(chip, *regs++, *val++); -} - -void snd_sbmixer_suspend(struct snd_sb *chip) -{ - switch (chip->hardware) { - case SB_HW_20: - case SB_HW_201: - save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); - break; - case SB_HW_PRO: - case SB_HW_JAZZ16: - save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); - break; - case SB_HW_16: - case SB_HW_ALS100: - case SB_HW_CS5530: - save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); - break; - case SB_HW_ALS4000: - save_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs)); - break; - case SB_HW_DT019X: - save_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs)); - break; - default: - break; - } -} - -void snd_sbmixer_resume(struct snd_sb *chip) -{ - switch (chip->hardware) { - case SB_HW_20: - case SB_HW_201: - restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs)); - break; - case SB_HW_PRO: - case SB_HW_JAZZ16: - restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs)); - break; - case SB_HW_16: - case SB_HW_ALS100: - case SB_HW_CS5530: - restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); - break; - case SB_HW_ALS4000: - restore_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs)); - break; - case SB_HW_DT019X: - restore_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs)); - break; - default: - break; - } -} -#endif diff --git a/ANDROID_3.4.5/sound/isa/sb/sbawe.c b/ANDROID_3.4.5/sound/isa/sb/sbawe.c deleted file mode 100644 index 2ec52a34..00000000 --- a/ANDROID_3.4.5/sound/isa/sb/sbawe.c +++ /dev/null @@ -1,2 +0,0 @@ -#define SNDRV_SBAWE -#include "sb16.c" diff --git a/ANDROID_3.4.5/sound/isa/sc6000.c b/ANDROID_3.4.5/sound/isa/sc6000.c deleted file mode 100644 index d97d0f38..00000000 --- a/ANDROID_3.4.5/sound/isa/sc6000.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Driver for Gallant SC-6000 soundcard. This card is also known as - * Audio Excel DSP 16 or Zoltrix AV302. - * These cards use CompuMedia ASC-9308 chip + AD1848 codec. - * SC-6600 and SC-7000 cards are also supported. They are based on - * CompuMedia ASC-9408 chip and CS4231 codec. - * - * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl> - * - * I don't have documentation for this card. I used the driver - * for OSS/Free included in the kernel source as reference. - * - * 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/module.h> -#include <linux/delay.h> -#include <linux/isa.h> -#include <linux/io.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/opl3.h> -#include <sound/mpu401.h> -#include <sound/control.h> -#define SNDRV_LEGACY_FIND_FREE_IRQ -#define SNDRV_LEGACY_FIND_FREE_DMA -#include <sound/initval.h> - -MODULE_AUTHOR("Krzysztof Helt"); -MODULE_DESCRIPTION("Gallant SC-6000"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Gallant, SC-6000}," - "{AudioExcel, Audio Excel DSP 16}," - "{Zoltrix, AV302}}"); - -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; /* Enable this card */ -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220, 0x240 */ -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 11 */ -static long mss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530, 0xe80 */ -static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; - /* 0x300, 0x310, 0x320, 0x330 */ -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 0 */ -static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0, 1, 3 */ -static bool joystick[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = false }; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for sc-6000 based soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable sc-6000 based soundcard."); -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for sc-6000 driver."); -module_param_array(mss_port, long, NULL, 0444); -MODULE_PARM_DESC(mss_port, "MSS Port # for sc-6000 driver."); -module_param_array(mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(mpu_port, "MPU-401 port # for sc-6000 driver."); -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for sc-6000 driver."); -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver."); -module_param_array(dma, int, NULL, 0444); -MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver."); -module_param_array(joystick, bool, NULL, 0444); -MODULE_PARM_DESC(joystick, "Enable gameport."); - -/* - * Commands of SC6000's DSP (SBPRO+special). - * Some of them are COMMAND_xx, in the future they may change. - */ -#define WRITE_MDIRQ_CFG 0x50 /* Set M&I&DRQ mask (the real config) */ -#define COMMAND_52 0x52 /* */ -#define READ_HARD_CFG 0x58 /* Read Hardware Config (I/O base etc) */ -#define COMMAND_5C 0x5c /* */ -#define COMMAND_60 0x60 /* */ -#define COMMAND_66 0x66 /* */ -#define COMMAND_6C 0x6c /* */ -#define COMMAND_6E 0x6e /* */ -#define COMMAND_88 0x88 /* Unknown command */ -#define DSP_INIT_MSS 0x8c /* Enable Microsoft Sound System mode */ -#define COMMAND_C5 0xc5 /* */ -#define GET_DSP_VERSION 0xe1 /* Get DSP Version */ -#define GET_DSP_COPYRIGHT 0xe3 /* Get DSP Copyright */ - -/* - * Offsets of SC6000 DSP I/O ports. The offset is added to base I/O port - * to have the actual I/O port. - * Register permissions are: - * (wo) == Write Only - * (ro) == Read Only - * (w-) == Write - * (r-) == Read - */ -#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */ -#define DSP_READ 0x0a /* offset of DSP READ (ro) */ -#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */ -#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */ -#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */ -#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */ - -#define PFX "sc6000: " -#define DRV_NAME "SC-6000" - -/* hardware dependent functions */ - -/* - * sc6000_irq_to_softcfg - Decode irq number into cfg code. - */ -static __devinit unsigned char sc6000_irq_to_softcfg(int irq) -{ - unsigned char val = 0; - - switch (irq) { - case 5: - val = 0x28; - break; - case 7: - val = 0x8; - break; - case 9: - val = 0x10; - break; - case 10: - val = 0x18; - break; - case 11: - val = 0x20; - break; - default: - break; - } - return val; -} - -/* - * sc6000_dma_to_softcfg - Decode dma number into cfg code. - */ -static __devinit unsigned char sc6000_dma_to_softcfg(int dma) -{ - unsigned char val = 0; - - switch (dma) { - case 0: - val = 1; - break; - case 1: - val = 2; - break; - case 3: - val = 3; - break; - default: - break; - } - return val; -} - -/* - * sc6000_mpu_irq_to_softcfg - Decode MPU-401 irq number into cfg code. - */ -static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq) -{ - unsigned char val = 0; - - switch (mpu_irq) { - case 5: - val = 4; - break; - case 7: - val = 0x44; - break; - case 9: - val = 0x84; - break; - case 10: - val = 0xc4; - break; - default: - break; - } - return val; -} - -static int sc6000_wait_data(char __iomem *vport) -{ - int loop = 1000; - unsigned char val = 0; - - do { - val = ioread8(vport + DSP_DATAVAIL); - if (val & 0x80) - return 0; - cpu_relax(); - } while (loop--); - - return -EAGAIN; -} - -static int sc6000_read(char __iomem *vport) -{ - if (sc6000_wait_data(vport)) - return -EBUSY; - - return ioread8(vport + DSP_READ); - -} - -static int sc6000_write(char __iomem *vport, int cmd) -{ - unsigned char val; - int loop = 500000; - - do { - val = ioread8(vport + DSP_STATUS); - /* - * DSP ready to receive data if bit 7 of val == 0 - */ - if (!(val & 0x80)) { - iowrite8(cmd, vport + DSP_COMMAND); - return 0; - } - cpu_relax(); - } while (loop--); - - snd_printk(KERN_ERR "DSP Command (0x%x) timeout.\n", cmd); - - return -EIO; -} - -static int __devinit sc6000_dsp_get_answer(char __iomem *vport, int command, - char *data, int data_len) -{ - int len = 0; - - if (sc6000_write(vport, command)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", command); - return -EIO; - } - - do { - int val = sc6000_read(vport); - - if (val < 0) - break; - - data[len++] = val; - - } while (len < data_len); - - /* - * If no more data available, return to the caller, no error if len>0. - * We have no other way to know when the string is finished. - */ - return len ? len : -EIO; -} - -static int __devinit sc6000_dsp_reset(char __iomem *vport) -{ - iowrite8(1, vport + DSP_RESET); - udelay(10); - iowrite8(0, vport + DSP_RESET); - udelay(20); - if (sc6000_read(vport) == 0xaa) - return 0; - return -ENODEV; -} - -/* detection and initialization */ -static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg) -{ - if (sc6000_write(vport, COMMAND_6C) < 0) { - snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C); - return -EIO; - } - if (sc6000_write(vport, COMMAND_5C) < 0) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_5C); - return -EIO; - } - if (sc6000_write(vport, cfg[0]) < 0) { - snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[0]); - return -EIO; - } - if (sc6000_write(vport, cfg[1]) < 0) { - snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[1]); - return -EIO; - } - if (sc6000_write(vport, COMMAND_C5) < 0) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_C5); - return -EIO; - } - - return 0; -} - -static int sc6000_cfg_write(char __iomem *vport, unsigned char softcfg) -{ - - if (sc6000_write(vport, WRITE_MDIRQ_CFG)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG); - return -EIO; - } - if (sc6000_write(vport, softcfg)) { - snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); - return -EIO; - } - return 0; -} - -static int sc6000_setup_board(char __iomem *vport, int config) -{ - int loop = 10; - - do { - if (sc6000_write(vport, COMMAND_88)) { - snd_printk(KERN_ERR "CMD 0x%x: failed!\n", - COMMAND_88); - return -EIO; - } - } while ((sc6000_wait_data(vport) < 0) && loop--); - - if (sc6000_read(vport) < 0) { - snd_printk(KERN_ERR "sc6000_read after CMD 0x%x: failed\n", - COMMAND_88); - return -EIO; - } - - if (sc6000_cfg_write(vport, config)) - return -ENODEV; - - return 0; -} - -static int __devinit sc6000_init_mss(char __iomem *vport, int config, - char __iomem *vmss_port, int mss_config) -{ - if (sc6000_write(vport, DSP_INIT_MSS)) { - snd_printk(KERN_ERR "sc6000_init_mss [0x%x]: failed!\n", - DSP_INIT_MSS); - return -EIO; - } - - msleep(10); - - if (sc6000_cfg_write(vport, config)) - return -EIO; - - iowrite8(mss_config, vmss_port); - - return 0; -} - -static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, - long xport, long xmpu, - long xmss_port, int joystick) -{ - cfg[0] = 0; - cfg[1] = 0; - if (xport == 0x240) - cfg[0] |= 1; - if (xmpu != SNDRV_AUTO_PORT) { - cfg[0] |= (xmpu & 0x30) >> 2; - cfg[1] |= 0x20; - } - if (xmss_port == 0xe80) - cfg[0] |= 0x10; - cfg[0] |= 0x40; /* always set */ - if (!joystick) - cfg[0] |= 0x02; - cfg[1] |= 0x80; /* enable WSS system */ - cfg[1] &= ~0x40; /* disable IDE */ - snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]); -} - -static int __devinit sc6000_init_board(char __iomem *vport, - char __iomem *vmss_port, int dev) -{ - char answer[15]; - char version[2]; - int mss_config = sc6000_irq_to_softcfg(irq[dev]) | - sc6000_dma_to_softcfg(dma[dev]); - int config = mss_config | - sc6000_mpu_irq_to_softcfg(mpu_irq[dev]); - int err; - int old = 0; - - err = sc6000_dsp_reset(vport); - if (err < 0) { - snd_printk(KERN_ERR "sc6000_dsp_reset: failed!\n"); - return err; - } - - memset(answer, 0, sizeof(answer)); - err = sc6000_dsp_get_answer(vport, GET_DSP_COPYRIGHT, answer, 15); - if (err <= 0) { - snd_printk(KERN_ERR "sc6000_dsp_copyright: failed!\n"); - return -ENODEV; - } - /* - * My SC-6000 card return "SC-6000" in DSPCopyright, so - * if we have something different, we have to be warned. - */ - if (strncmp("SC-6000", answer, 7)) - snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n"); - - if (sc6000_dsp_get_answer(vport, GET_DSP_VERSION, version, 2) < 2) { - snd_printk(KERN_ERR "sc6000_dsp_version: failed!\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n", - answer, version[0], version[1]); - - /* set configuration */ - sc6000_write(vport, COMMAND_5C); - if (sc6000_read(vport) < 0) - old = 1; - - if (!old) { - int cfg[2]; - sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], - mss_port[dev], joystick[dev]); - if (sc6000_hw_cfg_write(vport, cfg) < 0) { - snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); - return -EIO; - } - } - err = sc6000_setup_board(vport, config); - if (err < 0) { - snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); - return -ENODEV; - } - - sc6000_dsp_reset(vport); - - if (!old) { - sc6000_write(vport, COMMAND_60); - sc6000_write(vport, 0x02); - sc6000_dsp_reset(vport); - } - - err = sc6000_setup_board(vport, config); - if (err < 0) { - snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); - return -ENODEV; - } - err = sc6000_init_mss(vport, config, vmss_port, mss_config); - if (err < 0) { - snd_printk(KERN_ERR "Cannot initialize " - "Microsoft Sound System mode.\n"); - return -ENODEV; - } - - return 0; -} - -static int __devinit snd_sc6000_mixer(struct snd_wss *chip) -{ - struct snd_card *card = chip->card; - struct snd_ctl_elem_id id1, id2; - int err; - - memset(&id1, 0, sizeof(id1)); - memset(&id2, 0, sizeof(id2)); - id1.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - /* reassign AUX0 to FM */ - strcpy(id1.name, "Aux Playback Switch"); - strcpy(id2.name, "FM Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "FM Playback Volume"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - /* reassign AUX1 to CD */ - strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; - strcpy(id2.name, "CD Playback Switch"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - strcpy(id1.name, "Aux Playback Volume"); - strcpy(id2.name, "CD Playback Volume"); - err = snd_ctl_rename_id(card, &id1, &id2); - if (err < 0) - return err; - return 0; -} - -static int __devinit snd_sc6000_match(struct device *devptr, unsigned int dev) -{ - if (!enable[dev]) - return 0; - if (port[dev] == SNDRV_AUTO_PORT) { - printk(KERN_ERR PFX "specify IO port\n"); - return 0; - } - if (mss_port[dev] == SNDRV_AUTO_PORT) { - printk(KERN_ERR PFX "specify MSS port\n"); - return 0; - } - if (port[dev] != 0x220 && port[dev] != 0x240) { - printk(KERN_ERR PFX "Port must be 0x220 or 0x240\n"); - return 0; - } - if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) { - printk(KERN_ERR PFX "MSS port must be 0x530 or 0xe80\n"); - return 0; - } - if (irq[dev] != SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) { - printk(KERN_ERR PFX "invalid IRQ %d\n", irq[dev]); - return 0; - } - if (dma[dev] != SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) { - printk(KERN_ERR PFX "invalid DMA %d\n", dma[dev]); - return 0; - } - if (mpu_port[dev] != SNDRV_AUTO_PORT && - (mpu_port[dev] & ~0x30L) != 0x300) { - printk(KERN_ERR PFX "invalid MPU-401 port %lx\n", - mpu_port[dev]); - return 0; - } - if (mpu_port[dev] != SNDRV_AUTO_PORT && - mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] != 0 && - !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) { - printk(KERN_ERR PFX "invalid MPU-401 IRQ %d\n", mpu_irq[dev]); - return 0; - } - return 1; -} - -static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) -{ - static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 }; - static int possible_dmas[] = { 1, 3, 0, -1 }; - int err; - int xirq = irq[dev]; - int xdma = dma[dev]; - struct snd_card *card; - struct snd_wss *chip; - struct snd_opl3 *opl3; - char __iomem **vport; - char __iomem *vmss_port; - - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(vport), - &card); - if (err < 0) - return err; - - vport = card->private_data; - if (xirq == SNDRV_AUTO_IRQ) { - xirq = snd_legacy_find_free_irq(possible_irqs); - if (xirq < 0) { - snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); - err = -EBUSY; - goto err_exit; - } - } - - if (xdma == SNDRV_AUTO_DMA) { - xdma = snd_legacy_find_free_dma(possible_dmas); - if (xdma < 0) { - snd_printk(KERN_ERR PFX "unable to find a free DMA\n"); - err = -EBUSY; - goto err_exit; - } - } - - if (!request_region(port[dev], 0x10, DRV_NAME)) { - snd_printk(KERN_ERR PFX - "I/O port region is already in use.\n"); - err = -EBUSY; - goto err_exit; - } - *vport = devm_ioport_map(devptr, port[dev], 0x10); - if (*vport == NULL) { - snd_printk(KERN_ERR PFX - "I/O port cannot be iomaped.\n"); - err = -EBUSY; - goto err_unmap1; - } - - /* to make it marked as used */ - if (!request_region(mss_port[dev], 4, DRV_NAME)) { - snd_printk(KERN_ERR PFX - "SC-6000 port I/O port region is already in use.\n"); - err = -EBUSY; - goto err_unmap1; - } - vmss_port = devm_ioport_map(devptr, mss_port[dev], 4); - if (!vmss_port) { - snd_printk(KERN_ERR PFX - "MSS port I/O cannot be iomaped.\n"); - err = -EBUSY; - goto err_unmap2; - } - - snd_printd("Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n", - port[dev], xirq, xdma, - mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); - - err = sc6000_init_board(*vport, vmss_port, dev); - if (err < 0) - goto err_unmap2; - - err = snd_wss_create(card, mss_port[dev] + 4, -1, xirq, xdma, -1, - WSS_HW_DETECT, 0, &chip); - if (err < 0) - goto err_unmap2; - - err = snd_wss_pcm(chip, 0, NULL); - if (err < 0) { - snd_printk(KERN_ERR PFX - "error creating new WSS PCM device\n"); - goto err_unmap2; - } - err = snd_wss_mixer(chip); - if (err < 0) { - snd_printk(KERN_ERR PFX "error creating new WSS mixer\n"); - goto err_unmap2; - } - err = snd_sc6000_mixer(chip); - if (err < 0) { - snd_printk(KERN_ERR PFX "the mixer rewrite failed\n"); - goto err_unmap2; - } - if (snd_opl3_create(card, - 0x388, 0x388 + 2, - OPL3_HW_AUTO, 0, &opl3) < 0) { - snd_printk(KERN_ERR PFX "no OPL device at 0x%x-0x%x ?\n", - 0x388, 0x388 + 2); - } else { - err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); - if (err < 0) - goto err_unmap2; - } - - if (mpu_port[dev] != SNDRV_AUTO_PORT) { - if (mpu_irq[dev] == SNDRV_AUTO_IRQ) - mpu_irq[dev] = -1; - if (snd_mpu401_uart_new(card, 0, - MPU401_HW_MPU401, - mpu_port[dev], 0, - mpu_irq[dev], NULL) < 0) - snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n", - mpu_port[dev]); - } - - strcpy(card->driver, DRV_NAME); - strcpy(card->shortname, "SC-6000"); - sprintf(card->longname, "Gallant SC-6000 at 0x%lx, irq %d, dma %d", - mss_port[dev], xirq, xdma); - - snd_card_set_dev(card, devptr); - - err = snd_card_register(card); - if (err < 0) - goto err_unmap2; - - dev_set_drvdata(devptr, card); - return 0; - -err_unmap2: - sc6000_setup_board(*vport, 0); - release_region(mss_port[dev], 4); -err_unmap1: - release_region(port[dev], 0x10); -err_exit: - snd_card_free(card); - return err; -} - -static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev) -{ - struct snd_card *card = dev_get_drvdata(devptr); - char __iomem **vport = card->private_data; - - if (sc6000_setup_board(*vport, 0) < 0) - snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n"); - - release_region(port[dev], 0x10); - release_region(mss_port[dev], 4); - - dev_set_drvdata(devptr, NULL); - snd_card_free(card); - return 0; -} - -static struct isa_driver snd_sc6000_driver = { - .match = snd_sc6000_match, - .probe = snd_sc6000_probe, - .remove = __devexit_p(snd_sc6000_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DRV_NAME, - }, -}; - - -static int __init alsa_card_sc6000_init(void) -{ - return isa_register_driver(&snd_sc6000_driver, SNDRV_CARDS); -} - -static void __exit alsa_card_sc6000_exit(void) -{ - isa_unregister_driver(&snd_sc6000_driver); -} - -module_init(alsa_card_sc6000_init) -module_exit(alsa_card_sc6000_exit) diff --git a/ANDROID_3.4.5/sound/isa/sscape.c b/ANDROID_3.4.5/sound/isa/sscape.c deleted file mode 100644 index 8490f597..00000000 --- a/ANDROID_3.4.5/sound/isa/sscape.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* - * Low-level ALSA driver for the ENSONIQ SoundScape - * Copyright (c) by Chris Rankin - * - * This driver was written in part using information obtained from - * the OSS/Free SoundScape driver, written by Hannu Savolainen. - * - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/delay.h> -#include <linux/firmware.h> -#include <linux/pnp.h> -#include <linux/spinlock.h> -#include <linux/module.h> -#include <asm/dma.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/mpu401.h> -#include <sound/initval.h> - - -MODULE_AUTHOR("Chris Rankin"); -MODULE_DESCRIPTION("ENSONIQ SoundScape driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE("sndscape.co0"); -MODULE_FIRMWARE("sndscape.co1"); -MODULE_FIRMWARE("sndscape.co2"); -MODULE_FIRMWARE("sndscape.co3"); -MODULE_FIRMWARE("sndscape.co4"); -MODULE_FIRMWARE("scope.cod"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; -static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; -static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; -static bool joystick[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index number for SoundScape soundcard"); - -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "Description for SoundScape card"); - -module_param_array(port, long, NULL, 0444); -MODULE_PARM_DESC(port, "Port # for SoundScape driver."); - -module_param_array(wss_port, long, NULL, 0444); -MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver."); - -module_param_array(irq, int, NULL, 0444); -MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver."); - -module_param_array(mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver."); - -module_param_array(dma, int, NULL, 0444); -MODULE_PARM_DESC(dma, "DMA # for SoundScape driver."); - -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver."); - -module_param_array(joystick, bool, NULL, 0444); -MODULE_PARM_DESC(joystick, "Enable gameport."); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id sscape_pnpids[] = { - { .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */ - { .id = "ENS4081", .devs = { { "ENS1011" } } }, /* VIVO90 */ - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids); -#endif - - -#define HOST_CTRL_IO(i) ((i) + 2) -#define HOST_DATA_IO(i) ((i) + 3) -#define ODIE_ADDR_IO(i) ((i) + 4) -#define ODIE_DATA_IO(i) ((i) + 5) -#define CODEC_IO(i) ((i) + 8) - -#define IC_ODIE 1 -#define IC_OPUS 2 - -#define RX_READY 0x01 -#define TX_READY 0x02 - -#define CMD_ACK 0x80 -#define CMD_SET_MIDI_VOL 0x84 -#define CMD_GET_MIDI_VOL 0x85 -#define CMD_XXX_MIDI_VOL 0x86 -#define CMD_SET_EXTMIDI 0x8a -#define CMD_GET_EXTMIDI 0x8b -#define CMD_SET_MT32 0x8c -#define CMD_GET_MT32 0x8d - -enum GA_REG { - GA_INTSTAT_REG = 0, - GA_INTENA_REG, - GA_DMAA_REG, - GA_DMAB_REG, - GA_INTCFG_REG, - GA_DMACFG_REG, - GA_CDCFG_REG, - GA_SMCFGA_REG, - GA_SMCFGB_REG, - GA_HMCTL_REG -}; - -#define DMA_8BIT 0x80 - - -enum card_type { - MEDIA_FX, /* Sequoia S-1000 */ - SSCAPE, /* Sequoia S-2000 */ - SSCAPE_PNP, - SSCAPE_VIVO, -}; - -struct soundscape { - spinlock_t lock; - unsigned io_base; - int ic_type; - enum card_type type; - struct resource *io_res; - struct resource *wss_res; - struct snd_wss *chip; - - unsigned char midi_vol; -}; - -#define INVALID_IRQ ((unsigned)-1) - - -static inline struct soundscape *get_card_soundscape(struct snd_card *c) -{ - return (struct soundscape *) (c->private_data); -} - -/* - * Allocates some kernel memory that we can use for DMA. - * I think this means that the memory has to map to - * contiguous pages of physical memory. - */ -static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, - unsigned long size) -{ - if (buf) { - if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - size, buf) < 0) { - snd_printk(KERN_ERR "sscape: Failed to allocate " - "%lu bytes for DMA\n", - size); - return NULL; - } - } - - return buf; -} - -/* - * Release the DMA-able kernel memory ... - */ -static void free_dmabuf(struct snd_dma_buffer *buf) -{ - if (buf && buf->area) - snd_dma_free_pages(buf); -} - -/* - * This function writes to the SoundScape's control registers, - * but doesn't do any locking. It's up to the caller to do that. - * This is why this function is "unsafe" ... - */ -static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, - unsigned char val) -{ - outb(reg, ODIE_ADDR_IO(io_base)); - outb(val, ODIE_DATA_IO(io_base)); -} - -/* - * Write to the SoundScape's control registers, and do the - * necessary locking ... - */ -static void sscape_write(struct soundscape *s, enum GA_REG reg, - unsigned char val) -{ - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); - sscape_write_unsafe(s->io_base, reg, val); - spin_unlock_irqrestore(&s->lock, flags); -} - -/* - * Read from the SoundScape's control registers, but leave any - * locking to the caller. This is why the function is "unsafe" ... - */ -static inline unsigned char sscape_read_unsafe(unsigned io_base, - enum GA_REG reg) -{ - outb(reg, ODIE_ADDR_IO(io_base)); - return inb(ODIE_DATA_IO(io_base)); -} - -/* - * Puts the SoundScape into "host" mode, as compared to "MIDI" mode - */ -static inline void set_host_mode_unsafe(unsigned io_base) -{ - outb(0x0, HOST_CTRL_IO(io_base)); -} - -/* - * Puts the SoundScape into "MIDI" mode, as compared to "host" mode - */ -static inline void set_midi_mode_unsafe(unsigned io_base) -{ - outb(0x3, HOST_CTRL_IO(io_base)); -} - -/* - * Read the SoundScape's host-mode control register, but leave - * any locking issues to the caller ... - */ -static inline int host_read_unsafe(unsigned io_base) -{ - int data = -1; - if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) - data = inb(HOST_DATA_IO(io_base)); - - return data; -} - -/* - * Read the SoundScape's host-mode control register, performing - * a limited amount of busy-waiting if the register isn't ready. - * Also leaves all locking-issues to the caller ... - */ -static int host_read_ctrl_unsafe(unsigned io_base, unsigned timeout) -{ - int data; - - while (((data = host_read_unsafe(io_base)) < 0) && (timeout != 0)) { - udelay(100); - --timeout; - } /* while */ - - return data; -} - -/* - * Write to the SoundScape's host-mode control registers, but - * leave any locking issues to the caller ... - */ -static inline int host_write_unsafe(unsigned io_base, unsigned char data) -{ - if ((inb(HOST_CTRL_IO(io_base)) & TX_READY) != 0) { - outb(data, HOST_DATA_IO(io_base)); - return 1; - } - - return 0; -} - -/* - * Write to the SoundScape's host-mode control registers, performing - * a limited amount of busy-waiting if the register isn't ready. - * Also leaves all locking-issues to the caller ... - */ -static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data, - unsigned timeout) -{ - int err; - - while (!(err = host_write_unsafe(io_base, data)) && (timeout != 0)) { - udelay(100); - --timeout; - } /* while */ - - return err; -} - - -/* - * Check that the MIDI subsystem is operational. If it isn't, - * then we will hang the computer if we try to use it ... - * - * NOTE: This check is based upon observation, not documentation. - */ -static inline int verify_mpu401(const struct snd_mpu401 *mpu) -{ - return ((inb(MPU401C(mpu)) & 0xc0) == 0x80); -} - -/* - * This is apparently the standard way to initailise an MPU-401 - */ -static inline void initialise_mpu401(const struct snd_mpu401 *mpu) -{ - outb(0, MPU401D(mpu)); -} - -/* - * Tell the SoundScape to activate the AD1845 chip (I think). - * The AD1845 detection fails if we *don't* do this, so I - * think that this is a good idea ... - */ -static void activate_ad1845_unsafe(unsigned io_base) -{ - unsigned char val = sscape_read_unsafe(io_base, GA_HMCTL_REG); - sscape_write_unsafe(io_base, GA_HMCTL_REG, (val & 0xcf) | 0x10); - sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80); -} - -/* - * Do the necessary ALSA-level cleanup to deallocate our driver ... - */ -static void soundscape_free(struct snd_card *c) -{ - struct soundscape *sscape = get_card_soundscape(c); - release_and_free_resource(sscape->io_res); - release_and_free_resource(sscape->wss_res); - free_dma(sscape->chip->dma1); -} - -/* - * Tell the SoundScape to begin a DMA tranfer using the given channel. - * All locking issues are left to the caller. - */ -static void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg) -{ - sscape_write_unsafe(io_base, reg, - sscape_read_unsafe(io_base, reg) | 0x01); - sscape_write_unsafe(io_base, reg, - sscape_read_unsafe(io_base, reg) & 0xfe); -} - -/* - * Wait for a DMA transfer to complete. This is a "limited busy-wait", - * and all locking issues are left to the caller. - */ -static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, - unsigned timeout) -{ - while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) { - udelay(100); - --timeout; - } /* while */ - - return sscape_read_unsafe(io_base, reg) & 0x01; -} - -/* - * Wait for the On-Board Processor to return its start-up - * acknowledgement sequence. This wait is too long for - * us to perform "busy-waiting", and so we must sleep. - * This in turn means that we must not be holding any - * spinlocks when we call this function. - */ -static int obp_startup_ack(struct soundscape *s, unsigned timeout) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(timeout); - - do { - unsigned long flags; - int x; - - spin_lock_irqsave(&s->lock, flags); - x = host_read_unsafe(s->io_base); - spin_unlock_irqrestore(&s->lock, flags); - if (x == 0xfe || x == 0xff) - return 1; - - msleep(10); - } while (time_before(jiffies, end_time)); - - return 0; -} - -/* - * Wait for the host to return its start-up acknowledgement - * sequence. This wait is too long for us to perform - * "busy-waiting", and so we must sleep. This in turn means - * that we must not be holding any spinlocks when we call - * this function. - */ -static int host_startup_ack(struct soundscape *s, unsigned timeout) -{ - unsigned long end_time = jiffies + msecs_to_jiffies(timeout); - - do { - unsigned long flags; - int x; - - spin_lock_irqsave(&s->lock, flags); - x = host_read_unsafe(s->io_base); - spin_unlock_irqrestore(&s->lock, flags); - if (x == 0xfe) - return 1; - - msleep(10); - } while (time_before(jiffies, end_time)); - - return 0; -} - -/* - * Upload a byte-stream into the SoundScape using DMA channel A. - */ -static int upload_dma_data(struct soundscape *s, const unsigned char *data, - size_t size) -{ - unsigned long flags; - struct snd_dma_buffer dma; - int ret; - unsigned char val; - - if (!get_dmabuf(&dma, PAGE_ALIGN(32 * 1024))) - return -ENOMEM; - - spin_lock_irqsave(&s->lock, flags); - - /* - * Reset the board ... - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f); - - /* - * Enable the DMA channels and configure them ... - */ - val = (s->chip->dma1 << 4) | DMA_8BIT; - sscape_write_unsafe(s->io_base, GA_DMAA_REG, val); - sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20); - - /* - * Take the board out of reset ... - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80); - - /* - * Upload the firmware to the SoundScape - * board through the DMA channel ... - */ - while (size != 0) { - unsigned long len; - - len = min(size, dma.bytes); - memcpy(dma.area, data, len); - data += len; - size -= len; - - snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE); - sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG); - if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) { - /* - * Don't forget to release this spinlock we're holding - */ - spin_unlock_irqrestore(&s->lock, flags); - - snd_printk(KERN_ERR - "sscape: DMA upload has timed out\n"); - ret = -EAGAIN; - goto _release_dma; - } - } /* while */ - - set_host_mode_unsafe(s->io_base); - outb(0x0, s->io_base); - - /* - * Boot the board ... (I think) - */ - val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40); - spin_unlock_irqrestore(&s->lock, flags); - - /* - * If all has gone well, then the board should acknowledge - * the new upload and tell us that it has rebooted OK. We - * give it 5 seconds (max) ... - */ - ret = 0; - if (!obp_startup_ack(s, 5000)) { - snd_printk(KERN_ERR "sscape: No response " - "from on-board processor after upload\n"); - ret = -EAGAIN; - } else if (!host_startup_ack(s, 5000)) { - snd_printk(KERN_ERR - "sscape: SoundScape failed to initialise\n"); - ret = -EAGAIN; - } - -_release_dma: - /* - * NOTE!!! We are NOT holding any spinlocks at this point !!! - */ - sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_OPUS ? 0x40 : 0x70)); - free_dmabuf(&dma); - - return ret; -} - -/* - * Upload the bootblock(?) into the SoundScape. The only - * purpose of this block of code seems to be to tell - * us which version of the microcode we should be using. - */ -static int sscape_upload_bootblock(struct snd_card *card) -{ - struct soundscape *sscape = get_card_soundscape(card); - unsigned long flags; - const struct firmware *init_fw = NULL; - int data = 0; - int ret; - - ret = request_firmware(&init_fw, "scope.cod", card->dev); - if (ret < 0) { - snd_printk(KERN_ERR "sscape: Error loading scope.cod"); - return ret; - } - ret = upload_dma_data(sscape, init_fw->data, init_fw->size); - - release_firmware(init_fw); - - spin_lock_irqsave(&sscape->lock, flags); - if (ret == 0) - data = host_read_ctrl_unsafe(sscape->io_base, 100); - - if (data & 0x10) - sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f); - - spin_unlock_irqrestore(&sscape->lock, flags); - - data &= 0xf; - if (ret == 0 && data > 7) { - snd_printk(KERN_ERR - "sscape: timeout reading firmware version\n"); - ret = -EAGAIN; - } - - return (ret == 0) ? data : ret; -} - -/* - * Upload the microcode into the SoundScape. - */ -static int sscape_upload_microcode(struct snd_card *card, int version) -{ - struct soundscape *sscape = get_card_soundscape(card); - const struct firmware *init_fw = NULL; - char name[14]; - int err; - - snprintf(name, sizeof(name), "sndscape.co%d", version); - - err = request_firmware(&init_fw, name, card->dev); - if (err < 0) { - snd_printk(KERN_ERR "sscape: Error loading sndscape.co%d", - version); - return err; - } - err = upload_dma_data(sscape, init_fw->data, init_fw->size); - if (err == 0) - snd_printk(KERN_INFO "sscape: MIDI firmware loaded %d KBs\n", - init_fw->size >> 10); - - release_firmware(init_fw); - - return err; -} - -/* - * Mixer control for the SoundScape's MIDI device. - */ -static int sscape_midi_info(struct snd_kcontrol *ctl, - 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 = 127; - return 0; -} - -static int sscape_midi_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct snd_wss *chip = snd_kcontrol_chip(kctl); - struct snd_card *card = chip->card; - register struct soundscape *s = get_card_soundscape(card); - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); - uctl->value.integer.value[0] = s->midi_vol; - spin_unlock_irqrestore(&s->lock, flags); - return 0; -} - -static int sscape_midi_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct snd_wss *chip = snd_kcontrol_chip(kctl); - struct snd_card *card = chip->card; - struct soundscape *s = get_card_soundscape(card); - unsigned long flags; - int change; - unsigned char new_val; - - spin_lock_irqsave(&s->lock, flags); - - new_val = uctl->value.integer.value[0] & 127; - /* - * We need to put the board into HOST mode before we - * can send any volume-changing HOST commands ... - */ - set_host_mode_unsafe(s->io_base); - - /* - * To successfully change the MIDI volume setting, you seem to - * have to write a volume command, write the new volume value, - * and then perform another volume-related command. Perhaps the - * first command is an "open" and the second command is a "close"? - */ - if (s->midi_vol == new_val) { - change = 0; - goto __skip_change; - } - change = host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) - && host_write_ctrl_unsafe(s->io_base, new_val, 100) - && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100) - && host_write_ctrl_unsafe(s->io_base, new_val, 100); - s->midi_vol = new_val; -__skip_change: - - /* - * Take the board out of HOST mode and back into MIDI mode ... - */ - set_midi_mode_unsafe(s->io_base); - - spin_unlock_irqrestore(&s->lock, flags); - return change; -} - -static struct snd_kcontrol_new midi_mixer_ctl = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "MIDI", - .info = sscape_midi_info, - .get = sscape_midi_get, - .put = sscape_midi_put -}; - -/* - * The SoundScape can use two IRQs from a possible set of four. - * These IRQs are encoded as bit patterns so that they can be - * written to the control registers. - */ -static unsigned __devinit get_irq_config(int sscape_type, int irq) -{ - static const int valid_irq[] = { 9, 5, 7, 10 }; - static const int old_irq[] = { 9, 7, 5, 15 }; - unsigned cfg; - - if (sscape_type == MEDIA_FX) { - for (cfg = 0; cfg < ARRAY_SIZE(old_irq); ++cfg) - if (irq == old_irq[cfg]) - return cfg; - } else { - for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) - if (irq == valid_irq[cfg]) - return cfg; - } - - return INVALID_IRQ; -} - -/* - * Perform certain arcane port-checks to see whether there - * is a SoundScape board lurking behind the given ports. - */ -static int __devinit detect_sscape(struct soundscape *s, long wss_io) -{ - unsigned long flags; - unsigned d; - int retval = 0; - - spin_lock_irqsave(&s->lock, flags); - - /* - * The following code is lifted from the original OSS driver, - * and as I don't have a datasheet I cannot really comment - * on what it is doing... - */ - if ((inb(HOST_CTRL_IO(s->io_base)) & 0x78) != 0) - goto _done; - - d = inb(ODIE_ADDR_IO(s->io_base)) & 0xf0; - if ((d & 0x80) != 0) - goto _done; - - if (d == 0) - s->ic_type = IC_ODIE; - else if ((d & 0x60) != 0) - s->ic_type = IC_OPUS; - else - goto _done; - - outb(0xfa, ODIE_ADDR_IO(s->io_base)); - if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0a) - goto _done; - - outb(0xfe, ODIE_ADDR_IO(s->io_base)); - if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e) - goto _done; - - outb(0xfe, ODIE_ADDR_IO(s->io_base)); - d = inb(ODIE_DATA_IO(s->io_base)); - if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e) - goto _done; - - if (s->ic_type == IC_OPUS) - activate_ad1845_unsafe(s->io_base); - - if (s->type == SSCAPE_VIVO) - wss_io += 4; - - d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); - - /* wait for WSS codec */ - for (d = 0; d < 500; d++) { - if ((inb(wss_io) & 0x80) == 0) - break; - spin_unlock_irqrestore(&s->lock, flags); - msleep(1); - spin_lock_irqsave(&s->lock, flags); - } - - if ((inb(wss_io) & 0x80) != 0) - goto _done; - - if (inb(wss_io + 2) == 0xff) - goto _done; - - d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f; - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d); - - if ((inb(wss_io) & 0x80) != 0) - s->type = MEDIA_FX; - - d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG); - sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); - /* wait for WSS codec */ - for (d = 0; d < 500; d++) { - if ((inb(wss_io) & 0x80) == 0) - break; - spin_unlock_irqrestore(&s->lock, flags); - msleep(1); - spin_lock_irqsave(&s->lock, flags); - } - - /* - * SoundScape successfully detected! - */ - retval = 1; - -_done: - spin_unlock_irqrestore(&s->lock, flags); - return retval; -} - -/* - * ALSA callback function, called when attempting to open the MIDI device. - * Check that the MIDI firmware has been loaded, because we don't want - * to crash the machine. Also check that someone isn't using the hardware - * IOCTL device. - */ -static int mpu401_open(struct snd_mpu401 *mpu) -{ - if (!verify_mpu401(mpu)) { - snd_printk(KERN_ERR "sscape: MIDI disabled, " - "please load firmware\n"); - return -ENODEV; - } - - return 0; -} - -/* - * Initialse an MPU-401 subdevice for MIDI support on the SoundScape. - */ -static int __devinit create_mpu401(struct snd_card *card, int devnum, - unsigned long port, int irq) -{ - struct soundscape *sscape = get_card_soundscape(card); - struct snd_rawmidi *rawmidi; - int err; - - err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port, - MPU401_INFO_INTEGRATED, irq, &rawmidi); - if (err == 0) { - struct snd_mpu401 *mpu = rawmidi->private_data; - mpu->open_input = mpu401_open; - mpu->open_output = mpu401_open; - mpu->private_data = sscape; - - initialise_mpu401(mpu); - } - - return err; -} - - -/* - * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 - * is very much like a CS4231, with a few extra bits. We will - * try to support at least some of the extra bits by overriding - * some of the CS4231 callback. - */ -static int __devinit create_ad1845(struct snd_card *card, unsigned port, - int irq, int dma1, int dma2) -{ - register struct soundscape *sscape = get_card_soundscape(card); - struct snd_wss *chip; - int err; - int codec_type = WSS_HW_DETECT; - - switch (sscape->type) { - case MEDIA_FX: - case SSCAPE: - /* - * There are some freak examples of early Soundscape cards - * with CS4231 instead of AD1848/CS4248. Unfortunately, the - * CS4231 works only in CS4248 compatibility mode on - * these cards so force it. - */ - if (sscape->ic_type != IC_OPUS) - codec_type = WSS_HW_AD1848; - break; - - case SSCAPE_VIVO: - port += 4; - break; - default: - break; - } - - err = snd_wss_create(card, port, -1, irq, dma1, dma2, - codec_type, WSS_HWSHARE_DMA1, &chip); - if (!err) { - unsigned long flags; - struct snd_pcm *pcm; - - if (sscape->type != SSCAPE_VIVO) { - /* - * The input clock frequency on the SoundScape must - * be 14.31818 MHz, because we must set this register - * to get the playback to sound correct ... - */ - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, AD1845_CLOCK, 0x20); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - - } - - err = snd_wss_pcm(chip, 0, &pcm); - if (err < 0) { - snd_printk(KERN_ERR "sscape: No PCM device " - "for AD1845 chip\n"); - goto _error; - } - - err = snd_wss_mixer(chip); - if (err < 0) { - snd_printk(KERN_ERR "sscape: No mixer device " - "for AD1845 chip\n"); - goto _error; - } - if (chip->hardware != WSS_HW_AD1848) { - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) { - snd_printk(KERN_ERR "sscape: No timer device " - "for AD1845 chip\n"); - goto _error; - } - } - - if (sscape->type != SSCAPE_VIVO) { - err = snd_ctl_add(card, - snd_ctl_new1(&midi_mixer_ctl, chip)); - if (err < 0) { - snd_printk(KERN_ERR "sscape: Could not create " - "MIDI mixer control\n"); - goto _error; - } - } - - sscape->chip = chip; - } - -_error: - return err; -} - - -/* - * Create an ALSA soundcard entry for the SoundScape, using - * the given list of port, IRQ and DMA resources. - */ -static int __devinit create_sscape(int dev, struct snd_card *card) -{ - struct soundscape *sscape = get_card_soundscape(card); - unsigned dma_cfg; - unsigned irq_cfg; - unsigned mpu_irq_cfg; - struct resource *io_res; - struct resource *wss_res; - unsigned long flags; - int err; - int val; - const char *name; - - /* - * Grab IO ports that we will need to probe so that we - * can detect and control this hardware ... - */ - io_res = request_region(port[dev], 8, "SoundScape"); - if (!io_res) { - snd_printk(KERN_ERR - "sscape: can't grab port 0x%lx\n", port[dev]); - return -EBUSY; - } - wss_res = NULL; - if (sscape->type == SSCAPE_VIVO) { - wss_res = request_region(wss_port[dev], 4, "SoundScape"); - if (!wss_res) { - snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", - wss_port[dev]); - err = -EBUSY; - goto _release_region; - } - } - - /* - * Grab one DMA channel ... - */ - err = request_dma(dma[dev], "SoundScape"); - if (err < 0) { - snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]); - goto _release_region; - } - - spin_lock_init(&sscape->lock); - sscape->io_res = io_res; - sscape->wss_res = wss_res; - sscape->io_base = port[dev]; - - if (!detect_sscape(sscape, wss_port[dev])) { - printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", - sscape->io_base); - err = -ENODEV; - goto _release_dma; - } - - switch (sscape->type) { - case MEDIA_FX: - name = "MediaFX/SoundFX"; - break; - case SSCAPE: - name = "Soundscape"; - break; - case SSCAPE_PNP: - name = "Soundscape PnP"; - break; - case SSCAPE_VIVO: - name = "Soundscape VIVO"; - break; - default: - name = "unknown Soundscape"; - break; - } - - printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n", - name, sscape->io_base, irq[dev], dma[dev]); - - /* - * Check that the user didn't pass us garbage data ... - */ - irq_cfg = get_irq_config(sscape->type, irq[dev]); - if (irq_cfg == INVALID_IRQ) { - snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]); - err = -ENXIO; - goto _release_dma; - } - - mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]); - if (mpu_irq_cfg == INVALID_IRQ) { - snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); - err = -ENXIO; - goto _release_dma; - } - - /* - * Tell the on-board devices where their resources are (I think - - * I can't be sure without a datasheet ... So many magic values!) - */ - spin_lock_irqsave(&sscape->lock, flags); - - sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e); - sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00); - - /* - * Enable and configure the DMA channels ... - */ - sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50); - dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70); - sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg); - sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20); - - mpu_irq_cfg |= mpu_irq_cfg << 2; - val = sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7; - if (joystick[dev]) - val |= 8; - sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10); - sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg); - sscape_write_unsafe(sscape->io_base, - GA_CDCFG_REG, 0x09 | DMA_8BIT - | (dma[dev] << 4) | (irq_cfg << 1)); - /* - * Enable the master IRQ ... - */ - sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80); - - spin_unlock_irqrestore(&sscape->lock, flags); - - /* - * We have now enabled the codec chip, and so we should - * detect the AD1845 device ... - */ - err = create_ad1845(card, wss_port[dev], irq[dev], - dma[dev], dma2[dev]); - if (err < 0) { - snd_printk(KERN_ERR - "sscape: No AD1845 device at 0x%lx, IRQ %d\n", - wss_port[dev], irq[dev]); - goto _release_dma; - } - strcpy(card->driver, "SoundScape"); - strcpy(card->shortname, name); - snprintf(card->longname, sizeof(card->longname), - "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n", - name, sscape->chip->port, sscape->chip->irq, - sscape->chip->dma1, sscape->chip->dma2); - -#define MIDI_DEVNUM 0 - if (sscape->type != SSCAPE_VIVO) { - err = sscape_upload_bootblock(card); - if (err >= 0) - err = sscape_upload_microcode(card, err); - - if (err == 0) { - err = create_mpu401(card, MIDI_DEVNUM, port[dev], - mpu_irq[dev]); - if (err < 0) { - snd_printk(KERN_ERR "sscape: Failed to create " - "MPU-401 device at 0x%lx\n", - port[dev]); - goto _release_dma; - } - - /* - * Initialize mixer - */ - spin_lock_irqsave(&sscape->lock, flags); - sscape->midi_vol = 0; - host_write_ctrl_unsafe(sscape->io_base, - CMD_SET_MIDI_VOL, 100); - host_write_ctrl_unsafe(sscape->io_base, - sscape->midi_vol, 100); - host_write_ctrl_unsafe(sscape->io_base, - CMD_XXX_MIDI_VOL, 100); - host_write_ctrl_unsafe(sscape->io_base, - sscape->midi_vol, 100); - host_write_ctrl_unsafe(sscape->io_base, - CMD_SET_EXTMIDI, 100); - host_write_ctrl_unsafe(sscape->io_base, - 0, 100); - host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100); - - set_midi_mode_unsafe(sscape->io_base); - spin_unlock_irqrestore(&sscape->lock, flags); - } - } - - /* - * Now that we have successfully created this sound card, - * it is safe to store the pointer. - * NOTE: we only register the sound card's "destructor" - * function now that our "constructor" has completed. - */ - card->private_free = soundscape_free; - - return 0; - -_release_dma: - free_dma(dma[dev]); - -_release_region: - release_and_free_resource(wss_res); - release_and_free_resource(io_res); - - return err; -} - - -static int __devinit snd_sscape_match(struct device *pdev, unsigned int i) -{ - /* - * Make sure we were given ALL of the other parameters. - */ - if (port[i] == SNDRV_AUTO_PORT) - return 0; - - if (irq[i] == SNDRV_AUTO_IRQ || - mpu_irq[i] == SNDRV_AUTO_IRQ || - dma[i] == SNDRV_AUTO_DMA) { - printk(KERN_INFO - "sscape: insufficient parameters, " - "need IO, IRQ, MPU-IRQ and DMA\n"); - return 0; - } - - return 1; -} - -static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev) -{ - struct snd_card *card; - struct soundscape *sscape; - int ret; - - ret = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(struct soundscape), &card); - if (ret < 0) - return ret; - - sscape = get_card_soundscape(card); - sscape->type = SSCAPE; - - dma[dev] &= 0x03; - snd_card_set_dev(card, pdev); - - ret = create_sscape(dev, card); - if (ret < 0) - goto _release_card; - - ret = snd_card_register(card); - if (ret < 0) { - snd_printk(KERN_ERR "sscape: Failed to register sound card\n"); - goto _release_card; - } - dev_set_drvdata(pdev, card); - return 0; - -_release_card: - snd_card_free(card); - return ret; -} - -static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "sscape" - -static struct isa_driver snd_sscape_driver = { - .match = snd_sscape_match, - .probe = snd_sscape_probe, - .remove = __devexit_p(snd_sscape_remove), - /* FIXME: suspend/resume */ - .driver = { - .name = DEV_NAME - }, -}; - -#ifdef CONFIG_PNP -static inline int __devinit get_next_autoindex(int i) -{ - while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT) - ++i; - return i; -} - - -static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int idx = 0; - struct pnp_dev *dev; - struct snd_card *card; - struct soundscape *sscape; - int ret; - - /* - * Allow this function to fail *quietly* if all the ISA PnP - * devices were configured using module parameters instead. - */ - idx = get_next_autoindex(idx); - if (idx >= SNDRV_CARDS) - return -ENOSPC; - - /* - * Check that we still have room for another sound card ... - */ - dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); - if (!dev) - return -ENODEV; - - if (!pnp_is_active(dev)) { - if (pnp_activate_dev(dev) < 0) { - snd_printk(KERN_INFO "sscape: device is inactive\n"); - return -EBUSY; - } - } - - /* - * Create a new ALSA sound card entry, in anticipation - * of detecting our hardware ... - */ - ret = snd_card_create(index[idx], id[idx], THIS_MODULE, - sizeof(struct soundscape), &card); - if (ret < 0) - return ret; - - sscape = get_card_soundscape(card); - - /* - * Identify card model ... - */ - if (!strncmp("ENS4081", pid->id, 7)) - sscape->type = SSCAPE_VIVO; - else - sscape->type = SSCAPE_PNP; - - /* - * Read the correct parameters off the ISA PnP bus ... - */ - port[idx] = pnp_port_start(dev, 0); - irq[idx] = pnp_irq(dev, 0); - mpu_irq[idx] = pnp_irq(dev, 1); - dma[idx] = pnp_dma(dev, 0) & 0x03; - if (sscape->type == SSCAPE_PNP) { - dma2[idx] = dma[idx]; - wss_port[idx] = CODEC_IO(port[idx]); - } else { - wss_port[idx] = pnp_port_start(dev, 1); - dma2[idx] = pnp_dma(dev, 1); - } - snd_card_set_dev(card, &pcard->card->dev); - - ret = create_sscape(idx, card); - if (ret < 0) - goto _release_card; - - ret = snd_card_register(card); - if (ret < 0) { - snd_printk(KERN_ERR "sscape: Failed to register sound card\n"); - goto _release_card; - } - - pnp_set_card_drvdata(pcard, card); - ++idx; - return 0; - -_release_card: - snd_card_free(card); - return ret; -} - -static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver sscape_pnpc_driver = { - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - .name = "sscape", - .id_table = sscape_pnpids, - .probe = sscape_pnp_detect, - .remove = __devexit_p(sscape_pnp_remove), -}; - -#endif /* CONFIG_PNP */ - -static int __init sscape_init(void) -{ - int err; - - err = isa_register_driver(&snd_sscape_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&sscape_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit sscape_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&sscape_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_sscape_driver); -} - -module_init(sscape_init); -module_exit(sscape_exit); diff --git a/ANDROID_3.4.5/sound/isa/wavefront/Makefile b/ANDROID_3.4.5/sound/isa/wavefront/Makefile deleted file mode 100644 index 601bdddd..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> -# - -snd-wavefront-objs := wavefront.o wavefront_fx.o wavefront_synth.o wavefront_midi.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_WAVEFRONT) += snd-wavefront.o diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront.c deleted file mode 100644 index e0a73271..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * ALSA card-level driver for Turtle Beach Wavefront cards - * (Maui,Tropez,Tropez+) - * - * Copyright (c) 1997-1999 by Paul Barton-Davis <pbd@op.net> - * - * 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/err.h> -#include <linux/isa.h> -#include <linux/pnp.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/opl3.h> -#include <sound/wss.h> -#include <sound/snd_wavefront.h> - -MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>"); -MODULE_DESCRIPTION("Turtle Beach Wavefront"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}"); - -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; /* Enable this card */ -#ifdef CONFIG_PNP -static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; -#endif -static long cs4232_pcm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int cs4232_pcm_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ -static long cs4232_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int cs4232_mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */ -static long ics2115_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */ -static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ -static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ -static bool use_cs4232_midi[SNDRV_CARDS]; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for WaveFront soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for WaveFront soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable WaveFront soundcard."); -#ifdef CONFIG_PNP -module_param_array(isapnp, bool, NULL, 0444); -MODULE_PARM_DESC(isapnp, "ISA PnP detection for WaveFront soundcards."); -#endif -module_param_array(cs4232_pcm_port, long, NULL, 0444); -MODULE_PARM_DESC(cs4232_pcm_port, "Port # for CS4232 PCM interface."); -module_param_array(cs4232_pcm_irq, int, NULL, 0444); -MODULE_PARM_DESC(cs4232_pcm_irq, "IRQ # for CS4232 PCM interface."); -module_param_array(dma1, int, NULL, 0444); -MODULE_PARM_DESC(dma1, "DMA1 # for CS4232 PCM interface."); -module_param_array(dma2, int, NULL, 0444); -MODULE_PARM_DESC(dma2, "DMA2 # for CS4232 PCM interface."); -module_param_array(cs4232_mpu_port, long, NULL, 0444); -MODULE_PARM_DESC(cs4232_mpu_port, "port # for CS4232 MPU-401 interface."); -module_param_array(cs4232_mpu_irq, int, NULL, 0444); -MODULE_PARM_DESC(cs4232_mpu_irq, "IRQ # for CS4232 MPU-401 interface."); -module_param_array(ics2115_irq, int, NULL, 0444); -MODULE_PARM_DESC(ics2115_irq, "IRQ # for ICS2115."); -module_param_array(ics2115_port, long, NULL, 0444); -MODULE_PARM_DESC(ics2115_port, "Port # for ICS2115."); -module_param_array(fm_port, long, NULL, 0444); -MODULE_PARM_DESC(fm_port, "FM port #."); -module_param_array(use_cs4232_midi, bool, NULL, 0444); -MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)"); - -#ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; - -static struct pnp_card_device_id snd_wavefront_pnpids[] = { - /* Tropez */ - { .id = "CSC7532", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } }, - /* Tropez+ */ - { .id = "CSC7632", .devs = { { "CSC0000" }, { "CSC0010" }, { "PnPb006" }, { "CSC0004" } } }, - { .id = "" } -}; - -MODULE_DEVICE_TABLE(pnp_card, snd_wavefront_pnpids); - -static int __devinit -snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card, - const struct pnp_card_device_id *id) -{ - struct pnp_dev *pdev; - int err; - - /* Check for each logical device. */ - - /* CS4232 chip (aka "windows sound system") is logical device 0 */ - - acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL); - if (acard->wss == NULL) - return -EBUSY; - - /* there is a game port at logical device 1, but we ignore it completely */ - - /* the control interface is logical device 2, but we ignore it - completely. in fact, nobody even seems to know what it - does. - */ - - /* Only configure the CS4232 MIDI interface if its been - specifically requested. It is logical device 3. - */ - - if (use_cs4232_midi[dev]) { - acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); - if (acard->mpu == NULL) - return -EBUSY; - } - - /* The ICS2115 synth is logical device 4 */ - - acard->synth = pnp_request_card_device(card, id->devs[3].id, NULL); - if (acard->synth == NULL) - return -EBUSY; - - /* PCM/FM initialization */ - - pdev = acard->wss; - - /* An interesting note from the Tropez+ FAQ: - - Q. [Ports] Why is the base address of the WSS I/O ports off by 4? - - A. WSS I/O requires a block of 8 I/O addresses ("ports"). Of these, the first - 4 are used to identify and configure the board. With the advent of PnP, - these first 4 addresses have become obsolete, and software applications - only use the last 4 addresses to control the codec chip. Therefore, the - base address setting "skips past" the 4 unused addresses. - - */ - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "PnP WSS pnp configure failure\n"); - return err; - } - - cs4232_pcm_port[dev] = pnp_port_start(pdev, 0); - fm_port[dev] = pnp_port_start(pdev, 1); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - cs4232_pcm_irq[dev] = pnp_irq(pdev, 0); - - /* Synth initialization */ - - pdev = acard->synth; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n"); - return err; - } - - ics2115_port[dev] = pnp_port_start(pdev, 0); - ics2115_irq[dev] = pnp_irq(pdev, 0); - - /* CS4232 MPU initialization. Configure this only if - explicitly requested, since its physically inaccessible and - consumes another IRQ. - */ - - if (use_cs4232_midi[dev]) { - - pdev = acard->mpu; - - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n"); - cs4232_mpu_port[dev] = SNDRV_AUTO_PORT; - } else { - cs4232_mpu_port[dev] = pnp_port_start(pdev, 0); - cs4232_mpu_irq[dev] = pnp_irq(pdev, 0); - } - - snd_printk (KERN_INFO "CS4232 MPU: port=0x%lx, irq=%i\n", - cs4232_mpu_port[dev], - cs4232_mpu_irq[dev]); - } - - snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n", - cs4232_pcm_port[dev], - fm_port[dev], - dma1[dev], - dma2[dev], - cs4232_pcm_irq[dev], - ics2115_port[dev], - ics2115_irq[dev]); - - return 0; -} - -#endif /* CONFIG_PNP */ - -static irqreturn_t snd_wavefront_ics2115_interrupt(int irq, void *dev_id) -{ - snd_wavefront_card_t *acard; - - acard = (snd_wavefront_card_t *) dev_id; - - if (acard == NULL) - return IRQ_NONE; - - if (acard->wavefront.interrupts_are_midi) { - snd_wavefront_midi_interrupt (acard); - } else { - snd_wavefront_internal_interrupt (acard); - } - return IRQ_HANDLED; -} - -static struct snd_hwdep * __devinit -snd_wavefront_new_synth (struct snd_card *card, - int hw_dev, - snd_wavefront_card_t *acard) -{ - struct snd_hwdep *wavefront_synth; - - if (snd_wavefront_detect (acard) < 0) { - return NULL; - } - - if (snd_wavefront_start (&acard->wavefront) < 0) { - return NULL; - } - - if (snd_hwdep_new(card, "WaveFront", hw_dev, &wavefront_synth) < 0) - return NULL; - strcpy (wavefront_synth->name, - "WaveFront (ICS2115) wavetable synthesizer"); - wavefront_synth->ops.open = snd_wavefront_synth_open; - wavefront_synth->ops.release = snd_wavefront_synth_release; - wavefront_synth->ops.ioctl = snd_wavefront_synth_ioctl; - - return wavefront_synth; -} - -static struct snd_hwdep * __devinit -snd_wavefront_new_fx (struct snd_card *card, - int hw_dev, - snd_wavefront_card_t *acard, - unsigned long port) - -{ - struct snd_hwdep *fx_processor; - - if (snd_wavefront_fx_start (&acard->wavefront)) { - snd_printk (KERN_ERR "cannot initialize YSS225 FX processor"); - return NULL; - } - - if (snd_hwdep_new (card, "YSS225", hw_dev, &fx_processor) < 0) - return NULL; - sprintf (fx_processor->name, "YSS225 FX Processor at 0x%lx", port); - fx_processor->ops.open = snd_wavefront_fx_open; - fx_processor->ops.release = snd_wavefront_fx_release; - fx_processor->ops.ioctl = snd_wavefront_fx_ioctl; - - return fx_processor; -} - -static snd_wavefront_mpu_id internal_id = internal_mpu; -static snd_wavefront_mpu_id external_id = external_mpu; - -static struct snd_rawmidi *__devinit -snd_wavefront_new_midi (struct snd_card *card, - int midi_dev, - snd_wavefront_card_t *acard, - unsigned long port, - snd_wavefront_mpu_id mpu) - -{ - struct snd_rawmidi *rmidi; - static int first = 1; - - if (first) { - first = 0; - acard->wavefront.midi.base = port; - if (snd_wavefront_midi_start (acard)) { - snd_printk (KERN_ERR "cannot initialize MIDI interface\n"); - return NULL; - } - } - - if (snd_rawmidi_new (card, "WaveFront MIDI", midi_dev, 1, 1, &rmidi) < 0) - return NULL; - - if (mpu == internal_mpu) { - strcpy(rmidi->name, "WaveFront MIDI (Internal)"); - rmidi->private_data = &internal_id; - } else { - strcpy(rmidi->name, "WaveFront MIDI (External)"); - rmidi->private_data = &external_id; - } - - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_wavefront_midi_output); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_wavefront_midi_input); - - rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - return rmidi; -} - -static void -snd_wavefront_free(struct snd_card *card) -{ - snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data; - - if (acard) { - release_and_free_resource(acard->wavefront.res_base); - if (acard->wavefront.irq > 0) - free_irq(acard->wavefront.irq, (void *)acard); - } -} - -static int snd_wavefront_card_new(int dev, struct snd_card **cardp) -{ - struct snd_card *card; - snd_wavefront_card_t *acard; - int err; - - err = snd_card_create(index[dev], id[dev], THIS_MODULE, - sizeof(snd_wavefront_card_t), &card); - if (err < 0) - return err; - - acard = card->private_data; - acard->wavefront.irq = -1; - spin_lock_init(&acard->wavefront.irq_lock); - init_waitqueue_head(&acard->wavefront.interrupt_sleeper); - spin_lock_init(&acard->wavefront.midi.open); - spin_lock_init(&acard->wavefront.midi.virtual); - acard->wavefront.card = card; - card->private_free = snd_wavefront_free; - - *cardp = card; - return 0; -} - -static int __devinit -snd_wavefront_probe (struct snd_card *card, int dev) -{ - snd_wavefront_card_t *acard = card->private_data; - struct snd_wss *chip; - struct snd_hwdep *wavefront_synth; - struct snd_rawmidi *ics2115_internal_rmidi = NULL; - struct snd_rawmidi *ics2115_external_rmidi = NULL; - struct snd_hwdep *fx_processor; - int hw_dev = 0, midi_dev = 0, err; - - /* --------- PCM --------------- */ - - err = snd_wss_create(card, cs4232_pcm_port[dev], -1, - cs4232_pcm_irq[dev], dma1[dev], dma2[dev], - WSS_HW_DETECT, 0, &chip); - if (err < 0) { - snd_printk(KERN_ERR "can't allocate WSS device\n"); - return err; - } - - err = snd_wss_pcm(chip, 0, NULL); - if (err < 0) - return err; - - err = snd_wss_timer(chip, 0, NULL); - if (err < 0) - return err; - - /* ---------- OPL3 synth --------- */ - - if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) { - struct snd_opl3 *opl3; - - err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2, - OPL3_HW_OPL3_CS, 0, &opl3); - if (err < 0) { - snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n"); - return err; - } - - err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL); - if (err < 0) - return err; - hw_dev++; - } - - /* ------- ICS2115 Wavetable synth ------- */ - - acard->wavefront.res_base = request_region(ics2115_port[dev], 16, - "ICS2115"); - if (acard->wavefront.res_base == NULL) { - snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", - ics2115_port[dev], ics2115_port[dev] + 16 - 1); - return -EBUSY; - } - if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, - 0, "ICS2115", acard)) { - snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); - return -EBUSY; - } - - acard->wavefront.irq = ics2115_irq[dev]; - acard->wavefront.base = ics2115_port[dev]; - - wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard); - if (wavefront_synth == NULL) { - snd_printk (KERN_ERR "can't create WaveFront synth device\n"); - return -ENOMEM; - } - - strcpy (wavefront_synth->name, "ICS2115 Wavetable MIDI Synthesizer"); - wavefront_synth->iface = SNDRV_HWDEP_IFACE_ICS2115; - hw_dev++; - - /* --------- Mixer ------------ */ - - err = snd_wss_mixer(chip); - if (err < 0) { - snd_printk (KERN_ERR "can't allocate mixer device\n"); - return err; - } - - /* -------- CS4232 MPU-401 interface -------- */ - - if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { - err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, - cs4232_mpu_port[dev], 0, - cs4232_mpu_irq[dev], NULL); - if (err < 0) { - snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); - return err; - } - midi_dev++; - } - - /* ------ ICS2115 internal MIDI ------------ */ - - if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) { - ics2115_internal_rmidi = - snd_wavefront_new_midi (card, - midi_dev, - acard, - ics2115_port[dev], - internal_mpu); - if (ics2115_internal_rmidi == NULL) { - snd_printk (KERN_ERR "can't setup ICS2115 internal MIDI device\n"); - return -ENOMEM; - } - midi_dev++; - } - - /* ------ ICS2115 external MIDI ------------ */ - - if (ics2115_port[dev] > 0 && ics2115_port[dev] != SNDRV_AUTO_PORT) { - ics2115_external_rmidi = - snd_wavefront_new_midi (card, - midi_dev, - acard, - ics2115_port[dev], - external_mpu); - if (ics2115_external_rmidi == NULL) { - snd_printk (KERN_ERR "can't setup ICS2115 external MIDI device\n"); - return -ENOMEM; - } - midi_dev++; - } - - /* FX processor for Tropez+ */ - - if (acard->wavefront.has_fx) { - fx_processor = snd_wavefront_new_fx (card, - hw_dev, - acard, - ics2115_port[dev]); - if (fx_processor == NULL) { - snd_printk (KERN_ERR "can't setup FX device\n"); - return -ENOMEM; - } - - hw_dev++; - - strcpy(card->driver, "Tropez+"); - strcpy(card->shortname, "Turtle Beach Tropez+"); - } else { - /* Need a way to distinguish between Maui and Tropez */ - strcpy(card->driver, "WaveFront"); - strcpy(card->shortname, "Turtle Beach WaveFront"); - } - - /* ----- Register the card --------- */ - - /* Not safe to include "Turtle Beach" in longname, due to - length restrictions - */ - - sprintf(card->longname, "%s PCM 0x%lx irq %d dma %d", - card->driver, - chip->port, - cs4232_pcm_irq[dev], - dma1[dev]); - - if (dma2[dev] >= 0 && dma2[dev] < 8) - sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); - - if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) { - sprintf (card->longname + strlen (card->longname), - " MPU-401 0x%lx irq %d", - cs4232_mpu_port[dev], - cs4232_mpu_irq[dev]); - } - - sprintf (card->longname + strlen (card->longname), - " SYNTH 0x%lx irq %d", - ics2115_port[dev], - ics2115_irq[dev]); - - return snd_card_register(card); -} - -static int __devinit snd_wavefront_isa_match(struct device *pdev, - unsigned int dev) -{ - if (!enable[dev]) - return 0; -#ifdef CONFIG_PNP - if (isapnp[dev]) - return 0; -#endif - if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify CS4232 port\n"); - return 0; - } - if (ics2115_port[dev] == SNDRV_AUTO_PORT) { - snd_printk(KERN_ERR "specify ICS2115 port\n"); - return 0; - } - return 1; -} - -static int __devinit snd_wavefront_isa_probe(struct device *pdev, - unsigned int dev) -{ - struct snd_card *card; - int err; - - err = snd_wavefront_card_new(dev, &card); - if (err < 0) - return err; - snd_card_set_dev(card, pdev); - if ((err = snd_wavefront_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - - dev_set_drvdata(pdev, card); - return 0; -} - -static int __devexit snd_wavefront_isa_remove(struct device *devptr, - unsigned int dev) -{ - snd_card_free(dev_get_drvdata(devptr)); - dev_set_drvdata(devptr, NULL); - return 0; -} - -#define DEV_NAME "wavefront" - -static struct isa_driver snd_wavefront_driver = { - .match = snd_wavefront_isa_match, - .probe = snd_wavefront_isa_probe, - .remove = __devexit_p(snd_wavefront_isa_remove), - /* FIXME: suspend, resume */ - .driver = { - .name = DEV_NAME - }, -}; - - -#ifdef CONFIG_PNP -static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, - const struct pnp_card_device_id *pid) -{ - static int dev; - struct snd_card *card; - int res; - - for ( ; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - res = snd_wavefront_card_new(dev, &card); - if (res < 0) - return res; - - if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) { - if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) { - snd_printk (KERN_ERR "isapnp detection failed\n"); - snd_card_free (card); - return -ENODEV; - } - } - snd_card_set_dev(card, &pcard->card->dev); - - if ((res = snd_wavefront_probe(card, dev)) < 0) - return res; - - pnp_set_card_drvdata(pcard, card); - dev++; - return 0; -} - -static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard) -{ - snd_card_free(pnp_get_card_drvdata(pcard)); - pnp_set_card_drvdata(pcard, NULL); -} - -static struct pnp_card_driver wavefront_pnpc_driver = { - .flags = PNP_DRIVER_RES_DISABLE, - .name = "wavefront", - .id_table = snd_wavefront_pnpids, - .probe = snd_wavefront_pnp_detect, - .remove = __devexit_p(snd_wavefront_pnp_remove), - /* FIXME: suspend,resume */ -}; - -#endif /* CONFIG_PNP */ - -static int __init alsa_card_wavefront_init(void) -{ - int err; - - err = isa_register_driver(&snd_wavefront_driver, SNDRV_CARDS); -#ifdef CONFIG_PNP - if (!err) - isa_registered = 1; - - err = pnp_register_card_driver(&wavefront_pnpc_driver); - if (!err) - pnp_registered = 1; - - if (isa_registered) - err = 0; -#endif - return err; -} - -static void __exit alsa_card_wavefront_exit(void) -{ -#ifdef CONFIG_PNP - if (pnp_registered) - pnp_unregister_card_driver(&wavefront_pnpc_driver); - if (isa_registered) -#endif - isa_unregister_driver(&snd_wavefront_driver); -} - -module_init(alsa_card_wavefront_init) -module_exit(alsa_card_wavefront_exit) diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c deleted file mode 100644 index e51e0906..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_fx.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 1998-2002 by Paul Davis <pbd@op.net> - * - * 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 <asm/io.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/firmware.h> -#include <sound/core.h> -#include <sound/snd_wavefront.h> -#include <sound/initval.h> - -/* Control bits for the Load Control Register - */ - -#define FX_LSB_TRANSFER 0x01 /* transfer after DSP LSB byte written */ -#define FX_MSB_TRANSFER 0x02 /* transfer after DSP MSB byte written */ -#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */ - -#define WAIT_IDLE 0xff - -static int -wavefront_fx_idle (snd_wavefront_t *dev) - -{ - int i; - unsigned int x = 0x80; - - for (i = 0; i < 1000; i++) { - x = inb (dev->fx_status); - if ((x & 0x80) == 0) { - break; - } - } - - if (x & 0x80) { - snd_printk ("FX device never idle.\n"); - return 0; - } - - return (1); -} - -static void -wavefront_fx_mute (snd_wavefront_t *dev, int onoff) - -{ - if (!wavefront_fx_idle(dev)) { - return; - } - - outb (onoff ? 0x02 : 0x00, dev->fx_op); -} - -static int -wavefront_fx_memset (snd_wavefront_t *dev, - int page, - int addr, - int cnt, - unsigned short *data) -{ - if (page < 0 || page > 7) { - snd_printk ("FX memset: " - "page must be >= 0 and <= 7\n"); - return -(EINVAL); - } - - if (addr < 0 || addr > 0x7f) { - snd_printk ("FX memset: " - "addr must be >= 0 and <= 7f\n"); - return -(EINVAL); - } - - if (cnt == 1) { - - outb (FX_LSB_TRANSFER, dev->fx_lcr); - outb (page, dev->fx_dsp_page); - outb (addr, dev->fx_dsp_addr); - outb ((data[0] >> 8), dev->fx_dsp_msb); - outb ((data[0] & 0xff), dev->fx_dsp_lsb); - - snd_printk ("FX: addr %d:%x set to 0x%x\n", - page, addr, data[0]); - - } else { - int i; - - outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr); - outb (page, dev->fx_dsp_page); - outb (addr, dev->fx_dsp_addr); - - for (i = 0; i < cnt; i++) { - outb ((data[i] >> 8), dev->fx_dsp_msb); - outb ((data[i] & 0xff), dev->fx_dsp_lsb); - if (!wavefront_fx_idle (dev)) { - break; - } - } - - if (i != cnt) { - snd_printk ("FX memset " - "(0x%x, 0x%x, 0x%lx, %d) incomplete\n", - page, addr, (unsigned long) data, cnt); - return -(EIO); - } - } - - return 0; -} - -int -snd_wavefront_fx_detect (snd_wavefront_t *dev) - -{ - /* This is a crude check, but its the best one I have for now. - Certainly on the Maui and the Tropez, wavefront_fx_idle() will - report "never idle", which suggests that this test should - work OK. - */ - - if (inb (dev->fx_status) & 0x80) { - snd_printk ("Hmm, probably a Maui or Tropez.\n"); - return -1; - } - - return 0; -} - -int -snd_wavefront_fx_open (struct snd_hwdep *hw, struct file *file) - -{ - if (!try_module_get(hw->card->module)) - return -EFAULT; - file->private_data = hw; - return 0; -} - -int -snd_wavefront_fx_release (struct snd_hwdep *hw, struct file *file) - -{ - module_put(hw->card->module); - return 0; -} - -int -snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file, - unsigned int cmd, unsigned long arg) - -{ - struct snd_card *card; - snd_wavefront_card_t *acard; - snd_wavefront_t *dev; - wavefront_fx_info r; - unsigned short *page_data = NULL; - unsigned short *pd; - int err = 0; - - card = sdev->card; - if (snd_BUG_ON(!card)) - return -ENODEV; - if (snd_BUG_ON(!card->private_data)) - return -ENODEV; - - acard = card->private_data; - dev = &acard->wavefront; - - if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info))) - return -EFAULT; - - switch (r.request) { - case WFFX_MUTE: - wavefront_fx_mute (dev, r.data[0]); - return -EIO; - - case WFFX_MEMSET: - if (r.data[2] <= 0) { - snd_printk ("cannot write " - "<= 0 bytes to FX\n"); - return -EIO; - } else if (r.data[2] == 1) { - pd = (unsigned short *) &r.data[3]; - } else { - if (r.data[2] > 256) { - snd_printk ("cannot write " - "> 512 bytes to FX\n"); - return -EIO; - } - page_data = memdup_user((unsigned char __user *) - r.data[3], - r.data[2] * sizeof(short)); - if (IS_ERR(page_data)) - return PTR_ERR(page_data); - pd = page_data; - } - - err = wavefront_fx_memset (dev, - r.data[0], /* page */ - r.data[1], /* addr */ - r.data[2], /* cnt */ - pd); - kfree(page_data); - break; - - default: - snd_printk ("FX: ioctl %d not yet supported\n", - r.request); - return -ENOTTY; - } - return err; -} - -/* YSS225 initialization. - - This code was developed using DOSEMU. The Turtle Beach SETUPSND - utility was run with I/O tracing in DOSEMU enabled, and a reconstruction - of the port I/O done, using the Yamaha faxback document as a guide - to add more logic to the code. Its really pretty weird. - - This is the approach of just dumping the whole I/O - sequence as a series of port/value pairs and a simple loop - that outputs it. -*/ - -int __devinit -snd_wavefront_fx_start (snd_wavefront_t *dev) -{ - unsigned int i; - int err; - const struct firmware *firmware = NULL; - - if (dev->fx_initialized) - return 0; - - err = request_firmware(&firmware, "yamaha/yss225_registers.bin", - dev->card->dev); - if (err < 0) { - err = -1; - goto out; - } - - for (i = 0; i + 1 < firmware->size; i += 2) { - if (firmware->data[i] >= 8 && firmware->data[i] < 16) { - outb(firmware->data[i + 1], - dev->base + firmware->data[i]); - } else if (firmware->data[i] == WAIT_IDLE) { - if (!wavefront_fx_idle(dev)) { - err = -1; - goto out; - } - } else { - snd_printk(KERN_ERR "invalid address" - " in register data\n"); - err = -1; - goto out; - } - } - - dev->fx_initialized = 1; - err = 0; - -out: - release_firmware(firmware); - return err; -} - -MODULE_FIRMWARE("yamaha/yss225_registers.bin"); diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c deleted file mode 100644 index 65329f3a..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_midi.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright (C) by Paul Barton-Davis 1998-1999 - * - * This file is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this - * software for more info. - */ - -/* The low level driver for the WaveFront ICS2115 MIDI interface(s) - * - * Note that there is also an MPU-401 emulation (actually, a UART-401 - * emulation) on the CS4232 on the Tropez and Tropez Plus. This code - * has nothing to do with that interface at all. - * - * The interface is essentially just a UART-401, but is has the - * interesting property of supporting what Turtle Beach called - * "Virtual MIDI" mode. In this mode, there are effectively *two* - * MIDI buses accessible via the interface, one that is routed - * solely to/from the external WaveFront synthesizer and the other - * corresponding to the pin/socket connector used to link external - * MIDI devices to the board. - * - * This driver fully supports this mode, allowing two distinct MIDI - * busses to be used completely independently, giving 32 channels of - * MIDI routing, 16 to the WaveFront synth and 16 to the external MIDI - * bus. The devices are named /dev/snd/midiCnD0 and /dev/snd/midiCnD1, - * where `n' is the card number. Note that the device numbers may be - * something other than 0 and 1 if the CS4232 UART/MPU-401 interface - * is enabled. - * - * Switching between the two is accomplished externally by the driver - * using the two otherwise unused MIDI bytes. See the code for more details. - * - * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see lowlevel/isa/wavefront.c) - * - * The main reason to turn off Virtual MIDI mode is when you want to - * tightly couple the WaveFront synth with an external MIDI - * device. You won't be able to distinguish the source of any MIDI - * data except via SysEx ID, but thats probably OK, since for the most - * part, the WaveFront won't be sending any MIDI data at all. - * - * The main reason to turn on Virtual MIDI Mode is to provide two - * completely independent 16-channel MIDI buses, one to the - * WaveFront and one to any external MIDI devices. Given the 32 - * voice nature of the WaveFront, its pretty easy to find a use - * for all 16 channels driving just that synth. - * - */ - -#include <asm/io.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <sound/core.h> -#include <sound/snd_wavefront.h> - -static inline int -wf_mpu_status (snd_wavefront_midi_t *midi) - -{ - return inb (midi->mpu_status_port); -} - -static inline int -input_avail (snd_wavefront_midi_t *midi) - -{ - return !(wf_mpu_status(midi) & INPUT_AVAIL); -} - -static inline int -output_ready (snd_wavefront_midi_t *midi) - -{ - return !(wf_mpu_status(midi) & OUTPUT_READY); -} - -static inline int -read_data (snd_wavefront_midi_t *midi) - -{ - return inb (midi->mpu_data_port); -} - -static inline void -write_data (snd_wavefront_midi_t *midi, unsigned char byte) - -{ - outb (byte, midi->mpu_data_port); -} - -static snd_wavefront_midi_t * -get_wavefront_midi (struct snd_rawmidi_substream *substream) - -{ - struct snd_card *card; - snd_wavefront_card_t *acard; - - if (substream == NULL || substream->rmidi == NULL) - return NULL; - - card = substream->rmidi->card; - - if (card == NULL) - return NULL; - - if (card->private_data == NULL) - return NULL; - - acard = card->private_data; - - return &acard->wavefront.midi; -} - -static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card) -{ - snd_wavefront_midi_t *midi = &card->wavefront.midi; - snd_wavefront_mpu_id mpu; - unsigned long flags; - unsigned char midi_byte; - int max = 256, mask = 1; - int timeout; - - /* Its not OK to try to change the status of "virtuality" of - the MIDI interface while we're outputting stuff. See - snd_wavefront_midi_{enable,disable}_virtual () for the - other half of this. - - The first loop attempts to flush any data from the - current output device, and then the second - emits the switch byte (if necessary), and starts - outputting data for the output device currently in use. - */ - - if (midi->substream_output[midi->output_mpu] == NULL) { - goto __second; - } - - while (max > 0) { - - /* XXX fix me - no hard timing loops allowed! */ - - for (timeout = 30000; timeout > 0; timeout--) { - if (output_ready (midi)) - break; - } - - spin_lock_irqsave (&midi->virtual, flags); - if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) { - spin_unlock_irqrestore (&midi->virtual, flags); - goto __second; - } - if (output_ready (midi)) { - if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) { - if (!midi->isvirtual || - (midi_byte != WF_INTERNAL_SWITCH && - midi_byte != WF_EXTERNAL_SWITCH)) - write_data(midi, midi_byte); - max--; - } else { - if (midi->istimer) { - if (--midi->istimer <= 0) - del_timer(&midi->timer); - } - midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - spin_unlock_irqrestore (&midi->virtual, flags); - goto __second; - } - } else { - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - spin_unlock_irqrestore (&midi->virtual, flags); - } - - __second: - - if (midi->substream_output[!midi->output_mpu] == NULL) { - return; - } - - while (max > 0) { - - /* XXX fix me - no hard timing loops allowed! */ - - for (timeout = 30000; timeout > 0; timeout--) { - if (output_ready (midi)) - break; - } - - spin_lock_irqsave (&midi->virtual, flags); - if (!midi->isvirtual) - mask = 0; - mpu = midi->output_mpu ^ mask; - mask = 0; /* don't invert the value from now */ - if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) { - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - if (snd_rawmidi_transmit_empty(midi->substream_output[mpu])) - goto __timer; - if (output_ready (midi)) { - if (mpu != midi->output_mpu) { - write_data(midi, mpu == internal_mpu ? - WF_INTERNAL_SWITCH : - WF_EXTERNAL_SWITCH); - midi->output_mpu = mpu; - } else if (snd_rawmidi_transmit(midi->substream_output[mpu], &midi_byte, 1) == 1) { - if (!midi->isvirtual || - (midi_byte != WF_INTERNAL_SWITCH && - midi_byte != WF_EXTERNAL_SWITCH)) - write_data(midi, midi_byte); - max--; - } else { - __timer: - if (midi->istimer) { - if (--midi->istimer <= 0) - del_timer(&midi->timer); - } - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - } else { - spin_unlock_irqrestore (&midi->virtual, flags); - return; - } - spin_unlock_irqrestore (&midi->virtual, flags); - } -} - -static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] |= MPU401_MODE_INPUT; - midi->substream_input[mpu] = substream; - spin_unlock_irqrestore (&midi->open, flags); - - return 0; -} - -static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] |= MPU401_MODE_OUTPUT; - midi->substream_output[mpu] = substream; - spin_unlock_irqrestore (&midi->open, flags); - - return 0; -} - -static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] &= ~MPU401_MODE_INPUT; - spin_unlock_irqrestore (&midi->open, flags); - - return 0; -} - -static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (snd_BUG_ON(!substream || !substream->rmidi)) - return -ENXIO; - if (snd_BUG_ON(!substream->rmidi->private_data)) - return -ENXIO; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) - return -EIO; - - spin_lock_irqsave (&midi->open, flags); - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT; - spin_unlock_irqrestore (&midi->open, flags); - return 0; -} - -static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (substream == NULL || substream->rmidi == NULL) - return; - - if (substream->rmidi->private_data == NULL) - return; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) { - return; - } - - spin_lock_irqsave (&midi->virtual, flags); - if (up) { - midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER; - } else { - midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER; - } - spin_unlock_irqrestore (&midi->virtual, flags); -} - -static void snd_wavefront_midi_output_timer(unsigned long data) -{ - snd_wavefront_card_t *card = (snd_wavefront_card_t *)data; - snd_wavefront_midi_t *midi = &card->wavefront.midi; - unsigned long flags; - - spin_lock_irqsave (&midi->virtual, flags); - midi->timer.expires = 1 + jiffies; - add_timer(&midi->timer); - spin_unlock_irqrestore (&midi->virtual, flags); - snd_wavefront_midi_output_write(card); -} - -static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - snd_wavefront_mpu_id mpu; - - if (substream == NULL || substream->rmidi == NULL) - return; - - if (substream->rmidi->private_data == NULL) - return; - - mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - - if ((midi = get_wavefront_midi (substream)) == NULL) { - return; - } - - spin_lock_irqsave (&midi->virtual, flags); - if (up) { - if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { - if (!midi->istimer) { - init_timer(&midi->timer); - midi->timer.function = snd_wavefront_midi_output_timer; - midi->timer.data = (unsigned long) substream->rmidi->card->private_data; - midi->timer.expires = 1 + jiffies; - add_timer(&midi->timer); - } - midi->istimer++; - midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; - } - } else { - midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; - } - spin_unlock_irqrestore (&midi->virtual, flags); - - if (up) - snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data); -} - -void -snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) - -{ - unsigned long flags; - snd_wavefront_midi_t *midi; - static struct snd_rawmidi_substream *substream = NULL; - static int mpu = external_mpu; - int max = 128; - unsigned char byte; - - midi = &card->wavefront.midi; - - if (!input_avail (midi)) { /* not for us */ - snd_wavefront_midi_output_write(card); - return; - } - - spin_lock_irqsave (&midi->virtual, flags); - while (--max) { - - if (input_avail (midi)) { - byte = read_data (midi); - - if (midi->isvirtual) { - if (byte == WF_EXTERNAL_SWITCH) { - substream = midi->substream_input[external_mpu]; - mpu = external_mpu; - } else if (byte == WF_INTERNAL_SWITCH) { - substream = midi->substream_output[internal_mpu]; - mpu = internal_mpu; - } /* else just leave it as it is */ - } else { - substream = midi->substream_input[internal_mpu]; - mpu = internal_mpu; - } - - if (substream == NULL) { - continue; - } - - if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { - snd_rawmidi_receive(substream, &byte, 1); - } - } else { - break; - } - } - spin_unlock_irqrestore (&midi->virtual, flags); - - snd_wavefront_midi_output_write(card); -} - -void -snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *card) - -{ - unsigned long flags; - - spin_lock_irqsave (&card->wavefront.midi.virtual, flags); - card->wavefront.midi.isvirtual = 1; - card->wavefront.midi.output_mpu = internal_mpu; - card->wavefront.midi.input_mpu = internal_mpu; - spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); -} - -void -snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) - -{ - unsigned long flags; - - spin_lock_irqsave (&card->wavefront.midi.virtual, flags); - // snd_wavefront_midi_input_close (card->ics2115_external_rmidi); - // snd_wavefront_midi_output_close (card->ics2115_external_rmidi); - card->wavefront.midi.isvirtual = 0; - spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); -} - -int __devinit -snd_wavefront_midi_start (snd_wavefront_card_t *card) - -{ - int ok, i; - unsigned char rbuf[4], wbuf[4]; - snd_wavefront_t *dev; - snd_wavefront_midi_t *midi; - - dev = &card->wavefront; - midi = &dev->midi; - - /* The ICS2115 MPU-401 interface doesn't do anything - until its set into UART mode. - */ - - /* XXX fix me - no hard timing loops allowed! */ - - for (i = 0; i < 30000 && !output_ready (midi); i++); - - if (!output_ready (midi)) { - snd_printk ("MIDI interface not ready for command\n"); - return -1; - } - - /* Any interrupts received from now on - are owned by the MIDI side of things. - */ - - dev->interrupts_are_midi = 1; - - outb (UART_MODE_ON, midi->mpu_command_port); - - for (ok = 0, i = 50000; i > 0 && !ok; i--) { - if (input_avail (midi)) { - if (read_data (midi) == MPU_ACK) { - ok = 1; - break; - } - } - } - - if (!ok) { - snd_printk ("cannot set UART mode for MIDI interface"); - dev->interrupts_are_midi = 0; - return -1; - } - - /* Route external MIDI to WaveFront synth (by default) */ - - if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) { - snd_printk ("can't enable MIDI-IN-2-synth routing.\n"); - /* XXX error ? */ - } - - /* Turn on Virtual MIDI, but first *always* turn it off, - since otherwise consecutive reloads of the driver will - never cause the hardware to generate the initial "internal" or - "external" source bytes in the MIDI data stream. This - is pretty important, since the internal hardware generally will - be used to generate none or very little MIDI output, and - thus the only source of MIDI data is actually external. Without - the switch bytes, the driver will think it all comes from - the internal interface. Duh. - */ - - if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { - snd_printk ("virtual MIDI mode not disabled\n"); - return 0; /* We're OK, but missing the external MIDI dev */ - } - - snd_wavefront_midi_enable_virtual (card); - - if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) { - snd_printk ("cannot enable virtual MIDI mode.\n"); - snd_wavefront_midi_disable_virtual (card); - } - return 0; -} - -struct snd_rawmidi_ops snd_wavefront_midi_output = -{ - .open = snd_wavefront_midi_output_open, - .close = snd_wavefront_midi_output_close, - .trigger = snd_wavefront_midi_output_trigger, -}; - -struct snd_rawmidi_ops snd_wavefront_midi_input = -{ - .open = snd_wavefront_midi_input_open, - .close = snd_wavefront_midi_input_close, - .trigger = snd_wavefront_midi_input_trigger, -}; - diff --git a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_synth.c b/ANDROID_3.4.5/sound/isa/wavefront/wavefront_synth.c deleted file mode 100644 index 405f8b6a..00000000 --- a/ANDROID_3.4.5/sound/isa/wavefront/wavefront_synth.c +++ /dev/null @@ -1,2199 +0,0 @@ -/* Copyright (C) by Paul Barton-Davis 1998-1999 - * - * Some portions of this file are taken from work that is - * copyright (C) by Hannu Savolainen 1993-1996 - * - * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) - * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. - */ - -/* - * An ALSA lowlevel driver for Turtle Beach ICS2115 wavetable synth - * (Maui, Tropez, Tropez Plus) - * - * This driver supports the onboard wavetable synthesizer (an ICS2115), - * including patch, sample and program loading and unloading, conversion - * of GUS patches during loading, and full user-level access to all - * WaveFront commands. It tries to provide semi-intelligent patch and - * sample management as well. - * - */ - -#include <asm/io.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/time.h> -#include <linux/wait.h> -#include <linux/firmware.h> -#include <linux/moduleparam.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/snd_wavefront.h> -#include <sound/initval.h> - -static int wf_raw = 0; /* we normally check for "raw state" to firmware - loading. if non-zero, then during driver loading, the - state of the board is ignored, and we reset the - board and load the firmware anyway. - */ - -static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in - whatever state it is when the driver is loaded. - The default is to download the microprogram and - associated coefficients to set it up for "default" - operation, whatever that means. - */ - -static int debug_default = 0; /* you can set this to control debugging - during driver loading. it takes any combination - of the WF_DEBUG_* flags defined in - wavefront.h - */ - -/* XXX this needs to be made firmware and hardware version dependent */ - -#define DEFAULT_OSPATH "wavefront.os" -static char *ospath = DEFAULT_OSPATH; /* the firmware file name */ - -static int wait_usecs = 150; /* This magic number seems to give pretty optimal - throughput based on my limited experimentation. - If you want to play around with it and find a better - value, be my guest. Remember, the idea is to - get a number that causes us to just busy wait - for as many WaveFront commands as possible, without - coming up with a number so large that we hog the - whole CPU. - - Specifically, with this number, out of about 134,000 - status waits, only about 250 result in a sleep. - */ - -static int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */ -static int sleep_tries = 50; /* number of times we'll try to sleep */ - -static int reset_time = 2; /* hundreths of a second we wait after a HW - reset for the expected interrupt. - */ - -static int ramcheck_time = 20; /* time in seconds to wait while ROM code - checks on-board RAM. - */ - -static int osrun_time = 10; /* time in seconds we wait for the OS to - start running. - */ -module_param(wf_raw, int, 0444); -MODULE_PARM_DESC(wf_raw, "if non-zero, assume that we need to boot the OS"); -module_param(fx_raw, int, 0444); -MODULE_PARM_DESC(fx_raw, "if non-zero, assume that the FX process needs help"); -module_param(debug_default, int, 0444); -MODULE_PARM_DESC(debug_default, "debug parameters for card initialization"); -module_param(wait_usecs, int, 0444); -MODULE_PARM_DESC(wait_usecs, "how long to wait without sleeping, usecs"); -module_param(sleep_interval, int, 0444); -MODULE_PARM_DESC(sleep_interval, "how long to sleep when waiting for reply"); -module_param(sleep_tries, int, 0444); -MODULE_PARM_DESC(sleep_tries, "how many times to try sleeping during a wait"); -module_param(ospath, charp, 0444); -MODULE_PARM_DESC(ospath, "pathname to processed ICS2115 OS firmware"); -module_param(reset_time, int, 0444); -MODULE_PARM_DESC(reset_time, "how long to wait for a reset to take effect"); -module_param(ramcheck_time, int, 0444); -MODULE_PARM_DESC(ramcheck_time, "how many seconds to wait for the RAM test"); -module_param(osrun_time, int, 0444); -MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS"); - -/* if WF_DEBUG not defined, no run-time debugging messages will - be available via the debug flag setting. Given the current - beta state of the driver, this will remain set until a future - version. -*/ - -#define WF_DEBUG 1 - -#ifdef WF_DEBUG - -#define DPRINT(cond, ...) \ - if ((dev->debug & (cond)) == (cond)) { \ - snd_printk (__VA_ARGS__); \ - } -#else -#define DPRINT(cond, args...) -#endif /* WF_DEBUG */ - -#define LOGNAME "WaveFront: " - -/* bitmasks for WaveFront status port value */ - -#define STAT_RINTR_ENABLED 0x01 -#define STAT_CAN_READ 0x02 -#define STAT_INTR_READ 0x04 -#define STAT_WINTR_ENABLED 0x10 -#define STAT_CAN_WRITE 0x20 -#define STAT_INTR_WRITE 0x40 - -static int wavefront_delete_sample (snd_wavefront_t *, int sampnum); -static int wavefront_find_free_sample (snd_wavefront_t *); - -struct wavefront_command { - int cmd; - char *action; - unsigned int read_cnt; - unsigned int write_cnt; - int need_ack; -}; - -static struct { - int errno; - const char *errstr; -} wavefront_errors[] = { - { 0x01, "Bad sample number" }, - { 0x02, "Out of sample memory" }, - { 0x03, "Bad patch number" }, - { 0x04, "Error in number of voices" }, - { 0x06, "Sample load already in progress" }, - { 0x0B, "No sample load request pending" }, - { 0x0E, "Bad MIDI channel number" }, - { 0x10, "Download Record Error" }, - { 0x80, "Success" }, - { 0x0 } -}; - -#define NEEDS_ACK 1 - -static struct wavefront_command wavefront_commands[] = { - { WFC_SET_SYNTHVOL, "set synthesizer volume", 0, 1, NEEDS_ACK }, - { WFC_GET_SYNTHVOL, "get synthesizer volume", 1, 0, 0}, - { WFC_SET_NVOICES, "set number of voices", 0, 1, NEEDS_ACK }, - { WFC_GET_NVOICES, "get number of voices", 1, 0, 0 }, - { WFC_SET_TUNING, "set synthesizer tuning", 0, 2, NEEDS_ACK }, - { WFC_GET_TUNING, "get synthesizer tuning", 2, 0, 0 }, - { WFC_DISABLE_CHANNEL, "disable synth channel", 0, 1, NEEDS_ACK }, - { WFC_ENABLE_CHANNEL, "enable synth channel", 0, 1, NEEDS_ACK }, - { WFC_GET_CHANNEL_STATUS, "get synth channel status", 3, 0, 0 }, - { WFC_MISYNTH_OFF, "disable midi-in to synth", 0, 0, NEEDS_ACK }, - { WFC_MISYNTH_ON, "enable midi-in to synth", 0, 0, NEEDS_ACK }, - { WFC_VMIDI_ON, "enable virtual midi mode", 0, 0, NEEDS_ACK }, - { WFC_VMIDI_OFF, "disable virtual midi mode", 0, 0, NEEDS_ACK }, - { WFC_MIDI_STATUS, "report midi status", 1, 0, 0 }, - { WFC_FIRMWARE_VERSION, "report firmware version", 2, 0, 0 }, - { WFC_HARDWARE_VERSION, "report hardware version", 2, 0, 0 }, - { WFC_GET_NSAMPLES, "report number of samples", 2, 0, 0 }, - { WFC_INSTOUT_LEVELS, "report instantaneous output levels", 7, 0, 0 }, - { WFC_PEAKOUT_LEVELS, "report peak output levels", 7, 0, 0 }, - { WFC_DOWNLOAD_SAMPLE, "download sample", - 0, WF_SAMPLE_BYTES, NEEDS_ACK }, - { WFC_DOWNLOAD_BLOCK, "download block", 0, 0, NEEDS_ACK}, - { WFC_DOWNLOAD_SAMPLE_HEADER, "download sample header", - 0, WF_SAMPLE_HDR_BYTES, NEEDS_ACK }, - { WFC_UPLOAD_SAMPLE_HEADER, "upload sample header", 13, 2, 0 }, - - /* This command requires a variable number of bytes to be written. - There is a hack in snd_wavefront_cmd() to support this. The actual - count is passed in as the read buffer ptr, cast appropriately. - Ugh. - */ - - { WFC_DOWNLOAD_MULTISAMPLE, "download multisample", 0, 0, NEEDS_ACK }, - - /* This one is a hack as well. We just read the first byte of the - response, don't fetch an ACK, and leave the rest to the - calling function. Ugly, ugly, ugly. - */ - - { WFC_UPLOAD_MULTISAMPLE, "upload multisample", 2, 1, 0 }, - { WFC_DOWNLOAD_SAMPLE_ALIAS, "download sample alias", - 0, WF_ALIAS_BYTES, NEEDS_ACK }, - { WFC_UPLOAD_SAMPLE_ALIAS, "upload sample alias", WF_ALIAS_BYTES, 2, 0}, - { WFC_DELETE_SAMPLE, "delete sample", 0, 2, NEEDS_ACK }, - { WFC_IDENTIFY_SAMPLE_TYPE, "identify sample type", 5, 2, 0 }, - { WFC_UPLOAD_SAMPLE_PARAMS, "upload sample parameters" }, - { WFC_REPORT_FREE_MEMORY, "report free memory", 4, 0, 0 }, - { WFC_DOWNLOAD_PATCH, "download patch", 0, 134, NEEDS_ACK }, - { WFC_UPLOAD_PATCH, "upload patch", 132, 2, 0 }, - { WFC_DOWNLOAD_PROGRAM, "download program", 0, 33, NEEDS_ACK }, - { WFC_UPLOAD_PROGRAM, "upload program", 32, 1, 0 }, - { WFC_DOWNLOAD_EDRUM_PROGRAM, "download enhanced drum program", 0, 9, - NEEDS_ACK}, - { WFC_UPLOAD_EDRUM_PROGRAM, "upload enhanced drum program", 8, 1, 0}, - { WFC_SET_EDRUM_CHANNEL, "set enhanced drum program channel", - 0, 1, NEEDS_ACK }, - { WFC_DISABLE_DRUM_PROGRAM, "disable drum program", 0, 1, NEEDS_ACK }, - { WFC_REPORT_CHANNEL_PROGRAMS, "report channel program numbers", - 32, 0, 0 }, - { WFC_NOOP, "the no-op command", 0, 0, NEEDS_ACK }, - { 0x00 } -}; - -static const char * -wavefront_errorstr (int errnum) - -{ - int i; - - for (i = 0; wavefront_errors[i].errstr; i++) { - if (wavefront_errors[i].errno == errnum) { - return wavefront_errors[i].errstr; - } - } - - return "Unknown WaveFront error"; -} - -static struct wavefront_command * -wavefront_get_command (int cmd) - -{ - int i; - - for (i = 0; wavefront_commands[i].cmd != 0; i++) { - if (cmd == wavefront_commands[i].cmd) { - return &wavefront_commands[i]; - } - } - - return NULL; -} - -static inline int -wavefront_status (snd_wavefront_t *dev) - -{ - return inb (dev->status_port); -} - -static int -wavefront_sleep (int limit) - -{ - schedule_timeout_interruptible(limit); - - return signal_pending(current); -} - -static int -wavefront_wait (snd_wavefront_t *dev, int mask) - -{ - int i; - - /* Spin for a short period of time, because >99% of all - requests to the WaveFront can be serviced inline like this. - */ - - for (i = 0; i < wait_usecs; i += 5) { - if (wavefront_status (dev) & mask) { - return 1; - } - udelay(5); - } - - for (i = 0; i < sleep_tries; i++) { - - if (wavefront_status (dev) & mask) { - return 1; - } - - if (wavefront_sleep (HZ/sleep_interval)) { - return (0); - } - } - - return (0); -} - -static int -wavefront_read (snd_wavefront_t *dev) - -{ - if (wavefront_wait (dev, STAT_CAN_READ)) - return inb (dev->data_port); - - DPRINT (WF_DEBUG_DATA, "read timeout.\n"); - - return -1; -} - -static int -wavefront_write (snd_wavefront_t *dev, unsigned char data) - -{ - if (wavefront_wait (dev, STAT_CAN_WRITE)) { - outb (data, dev->data_port); - return 0; - } - - DPRINT (WF_DEBUG_DATA, "write timeout.\n"); - - return -1; -} - -int -snd_wavefront_cmd (snd_wavefront_t *dev, - int cmd, unsigned char *rbuf, unsigned char *wbuf) - -{ - int ack; - unsigned int i; - int c; - struct wavefront_command *wfcmd; - - if ((wfcmd = wavefront_get_command (cmd)) == NULL) { - snd_printk ("command 0x%x not supported.\n", - cmd); - return 1; - } - - /* Hack to handle the one variable-size write command. See - wavefront_send_multisample() for the other half of this - gross and ugly strategy. - */ - - if (cmd == WFC_DOWNLOAD_MULTISAMPLE) { - wfcmd->write_cnt = (unsigned long) rbuf; - rbuf = NULL; - } - - DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n", - cmd, wfcmd->action, wfcmd->read_cnt, - wfcmd->write_cnt, wfcmd->need_ack); - - if (wavefront_write (dev, cmd)) { - DPRINT ((WF_DEBUG_IO|WF_DEBUG_CMD), "cannot request " - "0x%x [%s].\n", - cmd, wfcmd->action); - return 1; - } - - if (wfcmd->write_cnt > 0) { - DPRINT (WF_DEBUG_DATA, "writing %d bytes " - "for 0x%x\n", - wfcmd->write_cnt, cmd); - - for (i = 0; i < wfcmd->write_cnt; i++) { - if (wavefront_write (dev, wbuf[i])) { - DPRINT (WF_DEBUG_IO, "bad write for byte " - "%d of 0x%x [%s].\n", - i, cmd, wfcmd->action); - return 1; - } - - DPRINT (WF_DEBUG_DATA, "write[%d] = 0x%x\n", - i, wbuf[i]); - } - } - - if (wfcmd->read_cnt > 0) { - DPRINT (WF_DEBUG_DATA, "reading %d ints " - "for 0x%x\n", - wfcmd->read_cnt, cmd); - - for (i = 0; i < wfcmd->read_cnt; i++) { - - if ((c = wavefront_read (dev)) == -1) { - DPRINT (WF_DEBUG_IO, "bad read for byte " - "%d of 0x%x [%s].\n", - i, cmd, wfcmd->action); - return 1; - } - - /* Now handle errors. Lots of special cases here */ - - if (c == 0xff) { - if ((c = wavefront_read (dev)) == -1) { - DPRINT (WF_DEBUG_IO, "bad read for " - "error byte at " - "read byte %d " - "of 0x%x [%s].\n", - i, cmd, - wfcmd->action); - return 1; - } - - /* Can you believe this madness ? */ - - if (c == 1 && - wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) { - rbuf[0] = WF_ST_EMPTY; - return (0); - - } else if (c == 3 && - wfcmd->cmd == WFC_UPLOAD_PATCH) { - - return 3; - - } else if (c == 1 && - wfcmd->cmd == WFC_UPLOAD_PROGRAM) { - - return 1; - - } else { - - DPRINT (WF_DEBUG_IO, "error %d (%s) " - "during " - "read for byte " - "%d of 0x%x " - "[%s].\n", - c, - wavefront_errorstr (c), - i, cmd, - wfcmd->action); - return 1; - - } - - } else { - rbuf[i] = c; - } - - DPRINT (WF_DEBUG_DATA, "read[%d] = 0x%x\n",i, rbuf[i]); - } - } - - if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) { - - DPRINT (WF_DEBUG_CMD, "reading ACK for 0x%x\n", cmd); - - /* Some commands need an ACK, but return zero instead - of the standard value. - */ - - if ((ack = wavefront_read (dev)) == 0) { - ack = WF_ACK; - } - - if (ack != WF_ACK) { - if (ack == -1) { - DPRINT (WF_DEBUG_IO, "cannot read ack for " - "0x%x [%s].\n", - cmd, wfcmd->action); - return 1; - - } else { - int err = -1; /* something unknown */ - - if (ack == 0xff) { /* explicit error */ - - if ((err = wavefront_read (dev)) == -1) { - DPRINT (WF_DEBUG_DATA, - "cannot read err " - "for 0x%x [%s].\n", - cmd, wfcmd->action); - } - } - - DPRINT (WF_DEBUG_IO, "0x%x [%s] " - "failed (0x%x, 0x%x, %s)\n", - cmd, wfcmd->action, ack, err, - wavefront_errorstr (err)); - - return -err; - } - } - - DPRINT (WF_DEBUG_DATA, "ack received " - "for 0x%x [%s]\n", - cmd, wfcmd->action); - } else { - - DPRINT (WF_DEBUG_CMD, "0x%x [%s] does not need " - "ACK (%d,%d,%d)\n", - cmd, wfcmd->action, wfcmd->read_cnt, - wfcmd->write_cnt, wfcmd->need_ack); - } - - return 0; - -} - -/*********************************************************************** -WaveFront data munging - -Things here are weird. All data written to the board cannot -have its most significant bit set. Any data item with values -potentially > 0x7F (127) must be split across multiple bytes. - -Sometimes, we need to munge numeric values that are represented on -the x86 side as 8-32 bit values. Sometimes, we need to munge data -that is represented on the x86 side as an array of bytes. The most -efficient approach to handling both cases seems to be to use 2 -different functions for munging and 2 for de-munging. This avoids -weird casting and worrying about bit-level offsets. - -**********************************************************************/ - -static unsigned char * -munge_int32 (unsigned int src, - unsigned char *dst, - unsigned int dst_size) -{ - unsigned int i; - - for (i = 0; i < dst_size; i++) { - *dst = src & 0x7F; /* Mask high bit of LSB */ - src = src >> 7; /* Rotate Right 7 bits */ - /* Note: we leave the upper bits in place */ - - dst++; - }; - return dst; -}; - -static int -demunge_int32 (unsigned char* src, int src_size) - -{ - int i; - int outval = 0; - - for (i = src_size - 1; i >= 0; i--) { - outval=(outval<<7)+src[i]; - } - - return outval; -}; - -static -unsigned char * -munge_buf (unsigned char *src, unsigned char *dst, unsigned int dst_size) - -{ - unsigned int i; - unsigned int last = dst_size / 2; - - for (i = 0; i < last; i++) { - *dst++ = src[i] & 0x7f; - *dst++ = src[i] >> 7; - } - return dst; -} - -static -unsigned char * -demunge_buf (unsigned char *src, unsigned char *dst, unsigned int src_bytes) - -{ - int i; - unsigned char *end = src + src_bytes; - - end = src + src_bytes; - - /* NOTE: src and dst *CAN* point to the same address */ - - for (i = 0; src != end; i++) { - dst[i] = *src++; - dst[i] |= (*src++)<<7; - } - - return dst; -} - -/*********************************************************************** -WaveFront: sample, patch and program management. -***********************************************************************/ - -static int -wavefront_delete_sample (snd_wavefront_t *dev, int sample_num) - -{ - unsigned char wbuf[2]; - int x; - - wbuf[0] = sample_num & 0x7f; - wbuf[1] = sample_num >> 7; - - if ((x = snd_wavefront_cmd (dev, WFC_DELETE_SAMPLE, NULL, wbuf)) == 0) { - dev->sample_status[sample_num] = WF_ST_EMPTY; - } - - return x; -} - -static int -wavefront_get_sample_status (snd_wavefront_t *dev, int assume_rom) - -{ - int i; - unsigned char rbuf[32], wbuf[32]; - unsigned int sc_real, sc_alias, sc_multi; - - /* check sample status */ - - if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) { - snd_printk ("cannot request sample count.\n"); - return -1; - } - - sc_real = sc_alias = sc_multi = dev->samples_used = 0; - - for (i = 0; i < WF_MAX_SAMPLE; i++) { - - wbuf[0] = i & 0x7f; - wbuf[1] = i >> 7; - - if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { - snd_printk(KERN_WARNING "cannot identify sample " - "type of slot %d\n", i); - dev->sample_status[i] = WF_ST_EMPTY; - continue; - } - - dev->sample_status[i] = (WF_SLOT_FILLED|rbuf[0]); - - if (assume_rom) { - dev->sample_status[i] |= WF_SLOT_ROM; - } - - switch (rbuf[0] & WF_ST_MASK) { - case WF_ST_SAMPLE: - sc_real++; - break; - case WF_ST_MULTISAMPLE: - sc_multi++; - break; - case WF_ST_ALIAS: - sc_alias++; - break; - case WF_ST_EMPTY: - break; - - default: - snd_printk ("unknown sample type for " - "slot %d (0x%x)\n", - i, rbuf[0]); - } - - if (rbuf[0] != WF_ST_EMPTY) { - dev->samples_used++; - } - } - - snd_printk ("%d samples used (%d real, %d aliases, %d multi), " - "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi, - WF_MAX_SAMPLE - dev->samples_used); - - - return (0); - -} - -static int -wavefront_get_patch_status (snd_wavefront_t *dev) - -{ - unsigned char patchbuf[WF_PATCH_BYTES]; - unsigned char patchnum[2]; - wavefront_patch *p; - int i, x, cnt, cnt2; - - for (i = 0; i < WF_MAX_PATCH; i++) { - patchnum[0] = i & 0x7f; - patchnum[1] = i >> 7; - - if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PATCH, patchbuf, - patchnum)) == 0) { - - dev->patch_status[i] |= WF_SLOT_FILLED; - p = (wavefront_patch *) patchbuf; - dev->sample_status - [p->sample_number|(p->sample_msb<<7)] |= - WF_SLOT_USED; - - } else if (x == 3) { /* Bad patch number */ - dev->patch_status[i] = 0; - } else { - snd_printk ("upload patch " - "error 0x%x\n", x); - dev->patch_status[i] = 0; - return 1; - } - } - - /* program status has already filled in slot_used bits */ - - for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) { - if (dev->patch_status[i] & WF_SLOT_FILLED) { - cnt++; - } - if (dev->patch_status[i] & WF_SLOT_USED) { - cnt2++; - } - - } - snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2); - - return (0); -} - -static int -wavefront_get_program_status (snd_wavefront_t *dev) - -{ - unsigned char progbuf[WF_PROGRAM_BYTES]; - wavefront_program prog; - unsigned char prognum; - int i, x, l, cnt; - - for (i = 0; i < WF_MAX_PROGRAM; i++) { - prognum = i; - - if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PROGRAM, progbuf, - &prognum)) == 0) { - - dev->prog_status[i] |= WF_SLOT_USED; - - demunge_buf (progbuf, (unsigned char *) &prog, - WF_PROGRAM_BYTES); - - for (l = 0; l < WF_NUM_LAYERS; l++) { - if (prog.layer[l].mute) { - dev->patch_status - [prog.layer[l].patch_number] |= - WF_SLOT_USED; - } - } - } else if (x == 1) { /* Bad program number */ - dev->prog_status[i] = 0; - } else { - snd_printk ("upload program " - "error 0x%x\n", x); - dev->prog_status[i] = 0; - } - } - - for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) { - if (dev->prog_status[i]) { - cnt++; - } - } - - snd_printk ("%d programs slots in use\n", cnt); - - return (0); -} - -static int -wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char buf[WF_PATCH_BYTES+2]; - unsigned char *bptr; - - DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n", - header->number); - - dev->patch_status[header->number] |= WF_SLOT_FILLED; - - bptr = buf; - bptr = munge_int32 (header->number, buf, 2); - munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) { - snd_printk ("download patch failed\n"); - return -(EIO); - } - - return (0); -} - -static int -wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char buf[WF_PROGRAM_BYTES+1]; - int i; - - DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n", - header->number); - - dev->prog_status[header->number] = WF_SLOT_USED; - - /* XXX need to zero existing SLOT_USED bit for program_status[i] - where `i' is the program that's being (potentially) overwritten. - */ - - for (i = 0; i < WF_NUM_LAYERS; i++) { - if (header->hdr.pr.layer[i].mute) { - dev->patch_status[header->hdr.pr.layer[i].patch_number] |= - WF_SLOT_USED; - - /* XXX need to mark SLOT_USED for sample used by - patch_number, but this means we have to load it. Ick. - */ - } - } - - buf[0] = header->number; - munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES); - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) { - snd_printk ("download patch failed\n"); - return -(EIO); - } - - return (0); -} - -static int -wavefront_freemem (snd_wavefront_t *dev) - -{ - char rbuf[8]; - - if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) { - snd_printk ("can't get memory stats.\n"); - return -1; - } else { - return demunge_int32 (rbuf, 4); - } -} - -static int -wavefront_send_sample (snd_wavefront_t *dev, - wavefront_patch_info *header, - u16 __user *dataptr, - int data_is_unsigned) - -{ - /* samples are downloaded via a 16-bit wide i/o port - (you could think of it as 2 adjacent 8-bit wide ports - but its less efficient that way). therefore, all - the blocksizes and so forth listed in the documentation, - and used conventionally to refer to sample sizes, - which are given in 8-bit units (bytes), need to be - divided by 2. - */ - - u16 sample_short = 0; - u32 length; - u16 __user *data_end = NULL; - unsigned int i; - const unsigned int max_blksize = 4096/2; - unsigned int written; - unsigned int blocksize; - int dma_ack; - int blocknum; - unsigned char sample_hdr[WF_SAMPLE_HDR_BYTES]; - unsigned char *shptr; - int skip = 0; - int initial_skip = 0; - - DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, " - "type %d, %d bytes from 0x%lx\n", - header->size ? "" : "header ", - header->number, header->subkey, - header->size, - (unsigned long) header->dataptr); - - if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) { - int x; - - if ((x = wavefront_find_free_sample (dev)) < 0) { - return -ENOMEM; - } - snd_printk ("unspecified sample => %d\n", x); - header->number = x; - } - - if (header->size) { - - /* XXX it's a debatable point whether or not RDONLY semantics - on the ROM samples should cover just the sample data or - the sample header. For now, it only covers the sample data, - so anyone is free at all times to rewrite sample headers. - - My reason for this is that we have the sample headers - available in the WFB file for General MIDI, and so these - can always be reset if needed. The sample data, however, - cannot be recovered without a complete reset and firmware - reload of the ICS2115, which is a very expensive operation. - - So, doing things this way allows us to honor the notion of - "RESETSAMPLES" reasonably cheaply. Note however, that this - is done purely at user level: there is no WFB parser in - this driver, and so a complete reset (back to General MIDI, - or theoretically some other configuration) is the - responsibility of the user level library. - - To try to do this in the kernel would be a little - crazy: we'd need 158K of kernel space just to hold - a copy of the patch/program/sample header data. - */ - - if (dev->rom_samples_rdonly) { - if (dev->sample_status[header->number] & WF_SLOT_ROM) { - snd_printk ("sample slot %d " - "write protected\n", - header->number); - return -EACCES; - } - } - - wavefront_delete_sample (dev, header->number); - } - - if (header->size) { - dev->freemem = wavefront_freemem (dev); - - if (dev->freemem < (int)header->size) { - snd_printk ("insufficient memory to " - "load %d byte sample.\n", - header->size); - return -ENOMEM; - } - - } - - skip = WF_GET_CHANNEL(&header->hdr.s); - - if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) { - snd_printk ("channel selection only " - "possible on 16-bit samples"); - return -(EINVAL); - } - - switch (skip) { - case 0: - initial_skip = 0; - skip = 1; - break; - case 1: - initial_skip = 0; - skip = 2; - break; - case 2: - initial_skip = 1; - skip = 2; - break; - case 3: - initial_skip = 2; - skip = 3; - break; - case 4: - initial_skip = 3; - skip = 4; - break; - case 5: - initial_skip = 4; - skip = 5; - break; - case 6: - initial_skip = 5; - skip = 6; - break; - } - - DPRINT (WF_DEBUG_LOAD_PATCH, "channel selection: %d => " - "initial skip = %d, skip = %d\n", - WF_GET_CHANNEL (&header->hdr.s), - initial_skip, skip); - - /* Be safe, and zero the "Unused" bits ... */ - - WF_SET_CHANNEL(&header->hdr.s, 0); - - /* adjust size for 16 bit samples by dividing by two. We always - send 16 bits per write, even for 8 bit samples, so the length - is always half the size of the sample data in bytes. - */ - - length = header->size / 2; - - /* the data we're sent has not been munged, and in fact, the - header we have to send isn't just a munged copy either. - so, build the sample header right here. - */ - - shptr = &sample_hdr[0]; - - shptr = munge_int32 (header->number, shptr, 2); - - if (header->size) { - shptr = munge_int32 (length, shptr, 4); - } - - /* Yes, a 4 byte result doesn't contain all of the offset bits, - but the offset only uses 24 bits. - */ - - shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleStartOffset), - shptr, 4); - shptr = munge_int32 (*((u32 *) &header->hdr.s.loopStartOffset), - shptr, 4); - shptr = munge_int32 (*((u32 *) &header->hdr.s.loopEndOffset), - shptr, 4); - shptr = munge_int32 (*((u32 *) &header->hdr.s.sampleEndOffset), - shptr, 4); - - /* This one is truly weird. What kind of weirdo decided that in - a system dominated by 16 and 32 bit integers, they would use - a just 12 bits ? - */ - - shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3); - - /* Why is this nybblified, when the MSB is *always* zero ? - Anyway, we can't take address of bitfield, so make a - good-faith guess at where it starts. - */ - - shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1), - shptr, 2); - - if (snd_wavefront_cmd (dev, - header->size ? - WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER, - NULL, sample_hdr)) { - snd_printk ("sample %sdownload refused.\n", - header->size ? "" : "header "); - return -(EIO); - } - - if (header->size == 0) { - goto sent; /* Sorry. Just had to have one somewhere */ - } - - data_end = dataptr + length; - - /* Do any initial skip over an unused channel's data */ - - dataptr += initial_skip; - - for (written = 0, blocknum = 0; - written < length; written += max_blksize, blocknum++) { - - if ((length - written) > max_blksize) { - blocksize = max_blksize; - } else { - /* round to nearest 16-byte value */ - blocksize = ALIGN(length - written, 8); - } - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) { - snd_printk ("download block " - "request refused.\n"); - return -(EIO); - } - - for (i = 0; i < blocksize; i++) { - - if (dataptr < data_end) { - - __get_user (sample_short, dataptr); - dataptr += skip; - - if (data_is_unsigned) { /* GUS ? */ - - if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) { - - /* 8 bit sample - resolution, sign - extend both bytes. - */ - - ((unsigned char*) - &sample_short)[0] += 0x7f; - ((unsigned char*) - &sample_short)[1] += 0x7f; - - } else { - - /* 16 bit sample - resolution, sign - extend the MSB. - */ - - sample_short += 0x7fff; - } - } - - } else { - - /* In padding section of final block: - - Don't fetch unsupplied data from - user space, just continue with - whatever the final value was. - */ - } - - if (i < blocksize - 1) { - outw (sample_short, dev->block_port); - } else { - outw (sample_short, dev->last_block_port); - } - } - - /* Get "DMA page acknowledge", even though its really - nothing to do with DMA at all. - */ - - if ((dma_ack = wavefront_read (dev)) != WF_DMA_ACK) { - if (dma_ack == -1) { - snd_printk ("upload sample " - "DMA ack timeout\n"); - return -(EIO); - } else { - snd_printk ("upload sample " - "DMA ack error 0x%x\n", - dma_ack); - return -(EIO); - } - } - } - - dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE); - - /* Note, label is here because sending the sample header shouldn't - alter the sample_status info at all. - */ - - sent: - return (0); -} - -static int -wavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char alias_hdr[WF_ALIAS_BYTES]; - - DPRINT (WF_DEBUG_LOAD_PATCH, "download alias, %d is " - "alias for %d\n", - header->number, - header->hdr.a.OriginalSample); - - munge_int32 (header->number, &alias_hdr[0], 2); - munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2); - munge_int32 (*((unsigned int *)&header->hdr.a.sampleStartOffset), - &alias_hdr[4], 4); - munge_int32 (*((unsigned int *)&header->hdr.a.loopStartOffset), - &alias_hdr[8], 4); - munge_int32 (*((unsigned int *)&header->hdr.a.loopEndOffset), - &alias_hdr[12], 4); - munge_int32 (*((unsigned int *)&header->hdr.a.sampleEndOffset), - &alias_hdr[16], 4); - munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3); - munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2); - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) { - snd_printk ("download alias failed.\n"); - return -(EIO); - } - - dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS); - - return (0); -} - -static int -wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header) -{ - int i; - int num_samples; - unsigned char *msample_hdr; - - msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL); - if (! msample_hdr) - return -ENOMEM; - - munge_int32 (header->number, &msample_hdr[0], 2); - - /* You'll recall at this point that the "number of samples" value - in a wavefront_multisample struct is actually the log2 of the - real number of samples. - */ - - num_samples = (1<<(header->hdr.ms.NumberOfSamples&7)); - msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples; - - DPRINT (WF_DEBUG_LOAD_PATCH, "multi %d with %d=%d samples\n", - header->number, - header->hdr.ms.NumberOfSamples, - num_samples); - - for (i = 0; i < num_samples; i++) { - DPRINT(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA, "sample[%d] = %d\n", - i, header->hdr.ms.SampleNumber[i]); - munge_int32 (header->hdr.ms.SampleNumber[i], - &msample_hdr[3+(i*2)], 2); - } - - /* Need a hack here to pass in the number of bytes - to be written to the synth. This is ugly, and perhaps - one day, I'll fix it. - */ - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE, - (unsigned char *) (long) ((num_samples*2)+3), - msample_hdr)) { - snd_printk ("download of multisample failed.\n"); - kfree(msample_hdr); - return -(EIO); - } - - dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE); - - kfree(msample_hdr); - return (0); -} - -static int -wavefront_fetch_multisample (snd_wavefront_t *dev, - wavefront_patch_info *header) -{ - int i; - unsigned char log_ns[1]; - unsigned char number[2]; - int num_samples; - - munge_int32 (header->number, number, 2); - - if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) { - snd_printk ("upload multisample failed.\n"); - return -(EIO); - } - - DPRINT (WF_DEBUG_DATA, "msample %d has %d samples\n", - header->number, log_ns[0]); - - header->hdr.ms.NumberOfSamples = log_ns[0]; - - /* get the number of samples ... */ - - num_samples = (1 << log_ns[0]); - - for (i = 0; i < num_samples; i++) { - char d[2]; - int val; - - if ((val = wavefront_read (dev)) == -1) { - snd_printk ("upload multisample failed " - "during sample loop.\n"); - return -(EIO); - } - d[0] = val; - - if ((val = wavefront_read (dev)) == -1) { - snd_printk ("upload multisample failed " - "during sample loop.\n"); - return -(EIO); - } - d[1] = val; - - header->hdr.ms.SampleNumber[i] = - demunge_int32 ((unsigned char *) d, 2); - - DPRINT (WF_DEBUG_DATA, "msample sample[%d] = %d\n", - i, header->hdr.ms.SampleNumber[i]); - } - - return (0); -} - - -static int -wavefront_send_drum (snd_wavefront_t *dev, wavefront_patch_info *header) - -{ - unsigned char drumbuf[WF_DRUM_BYTES]; - wavefront_drum *drum = &header->hdr.d; - int i; - - DPRINT (WF_DEBUG_LOAD_PATCH, "downloading edrum for MIDI " - "note %d, patch = %d\n", - header->number, drum->PatchNumber); - - drumbuf[0] = header->number & 0x7f; - - for (i = 0; i < 4; i++) { - munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2); - } - - if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) { - snd_printk ("download drum failed.\n"); - return -(EIO); - } - - return (0); -} - -static int -wavefront_find_free_sample (snd_wavefront_t *dev) - -{ - int i; - - for (i = 0; i < WF_MAX_SAMPLE; i++) { - if (!(dev->sample_status[i] & WF_SLOT_FILLED)) { - return i; - } - } - snd_printk ("no free sample slots!\n"); - return -1; -} - -#if 0 -static int -wavefront_find_free_patch (snd_wavefront_t *dev) - -{ - int i; - - for (i = 0; i < WF_MAX_PATCH; i++) { - if (!(dev->patch_status[i] & WF_SLOT_FILLED)) { - return i; - } - } - snd_printk ("no free patch slots!\n"); - return -1; -} -#endif - -static int -wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr) -{ - wavefront_patch_info *header; - int err; - - header = kmalloc(sizeof(*header), GFP_KERNEL); - if (! header) - return -ENOMEM; - - if (copy_from_user (header, addr, sizeof(wavefront_patch_info) - - sizeof(wavefront_any))) { - snd_printk ("bad address for load patch.\n"); - err = -EFAULT; - goto __error; - } - - DPRINT (WF_DEBUG_LOAD_PATCH, "download " - "Sample type: %d " - "Sample number: %d " - "Sample size: %d\n", - header->subkey, - header->number, - header->size); - - switch (header->subkey) { - case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */ - - if (copy_from_user (&header->hdr.s, header->hdrptr, - sizeof (wavefront_sample))) { - err = -EFAULT; - break; - } - - err = wavefront_send_sample (dev, header, header->dataptr, 0); - break; - - case WF_ST_MULTISAMPLE: - - if (copy_from_user (&header->hdr.s, header->hdrptr, - sizeof (wavefront_multisample))) { - err = -EFAULT; - break; - } - - err = wavefront_send_multisample (dev, header); - break; - - case WF_ST_ALIAS: - - if (copy_from_user (&header->hdr.a, header->hdrptr, - sizeof (wavefront_alias))) { - err = -EFAULT; - break; - } - - err = wavefront_send_alias (dev, header); - break; - - case WF_ST_DRUM: - if (copy_from_user (&header->hdr.d, header->hdrptr, - sizeof (wavefront_drum))) { - err = -EFAULT; - break; - } - - err = wavefront_send_drum (dev, header); - break; - - case WF_ST_PATCH: - if (copy_from_user (&header->hdr.p, header->hdrptr, - sizeof (wavefront_patch))) { - err = -EFAULT; - break; - } - - err = wavefront_send_patch (dev, header); - break; - - case WF_ST_PROGRAM: - if (copy_from_user (&header->hdr.pr, header->hdrptr, - sizeof (wavefront_program))) { - err = -EFAULT; - break; - } - - err = wavefront_send_program (dev, header); - break; - - default: - snd_printk ("unknown patch type %d.\n", - header->subkey); - err = -EINVAL; - break; - } - - __error: - kfree(header); - return err; -} - -/*********************************************************************** -WaveFront: hardware-dependent interface -***********************************************************************/ - -static void -process_sample_hdr (u8 *buf) - -{ - wavefront_sample s; - u8 *ptr; - - ptr = buf; - - /* The board doesn't send us an exact copy of a "wavefront_sample" - in response to an Upload Sample Header command. Instead, we - have to convert the data format back into our data structure, - just as in the Download Sample command, where we have to do - something very similar in the reverse direction. - */ - - *((u32 *) &s.sampleStartOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.loopStartOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.loopEndOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.sampleEndOffset) = demunge_int32 (ptr, 4); ptr += 4; - *((u32 *) &s.FrequencyBias) = demunge_int32 (ptr, 3); ptr += 3; - - s.SampleResolution = *ptr & 0x3; - s.Loop = *ptr & 0x8; - s.Bidirectional = *ptr & 0x10; - s.Reverse = *ptr & 0x40; - - /* Now copy it back to where it came from */ - - memcpy (buf, (unsigned char *) &s, sizeof (wavefront_sample)); -} - -static int -wavefront_synth_control (snd_wavefront_card_t *acard, - wavefront_control *wc) - -{ - snd_wavefront_t *dev = &acard->wavefront; - unsigned char patchnumbuf[2]; - int i; - - DPRINT (WF_DEBUG_CMD, "synth control with " - "cmd 0x%x\n", wc->cmd); - - /* Pre-handling of or for various commands */ - - switch (wc->cmd) { - - case WFC_DISABLE_INTERRUPTS: - snd_printk ("interrupts disabled.\n"); - outb (0x80|0x20, dev->control_port); - dev->interrupts_are_midi = 1; - return 0; - - case WFC_ENABLE_INTERRUPTS: - snd_printk ("interrupts enabled.\n"); - outb (0x80|0x40|0x20, dev->control_port); - dev->interrupts_are_midi = 1; - return 0; - - case WFC_INTERRUPT_STATUS: - wc->rbuf[0] = dev->interrupts_are_midi; - return 0; - - case WFC_ROMSAMPLES_RDONLY: - dev->rom_samples_rdonly = wc->wbuf[0]; - wc->status = 0; - return 0; - - case WFC_IDENTIFY_SLOT_TYPE: - i = wc->wbuf[0] | (wc->wbuf[1] << 7); - if (i <0 || i >= WF_MAX_SAMPLE) { - snd_printk ("invalid slot ID %d\n", - i); - wc->status = EINVAL; - return -EINVAL; - } - wc->rbuf[0] = dev->sample_status[i]; - wc->status = 0; - return 0; - - case WFC_DEBUG_DRIVER: - dev->debug = wc->wbuf[0]; - snd_printk ("debug = 0x%x\n", dev->debug); - return 0; - - case WFC_UPLOAD_PATCH: - munge_int32 (*((u32 *) wc->wbuf), patchnumbuf, 2); - memcpy (wc->wbuf, patchnumbuf, 2); - break; - - case WFC_UPLOAD_MULTISAMPLE: - /* multisamples have to be handled differently, and - cannot be dealt with properly by snd_wavefront_cmd() alone. - */ - wc->status = wavefront_fetch_multisample - (dev, (wavefront_patch_info *) wc->rbuf); - return 0; - - case WFC_UPLOAD_SAMPLE_ALIAS: - snd_printk ("support for sample alias upload " - "being considered.\n"); - wc->status = EINVAL; - return -EINVAL; - } - - wc->status = snd_wavefront_cmd (dev, wc->cmd, wc->rbuf, wc->wbuf); - - /* Post-handling of certain commands. - - In particular, if the command was an upload, demunge the data - so that the user-level doesn't have to think about it. - */ - - if (wc->status == 0) { - switch (wc->cmd) { - /* intercept any freemem requests so that we know - we are always current with the user-level view - of things. - */ - - case WFC_REPORT_FREE_MEMORY: - dev->freemem = demunge_int32 (wc->rbuf, 4); - break; - - case WFC_UPLOAD_PATCH: - demunge_buf (wc->rbuf, wc->rbuf, WF_PATCH_BYTES); - break; - - case WFC_UPLOAD_PROGRAM: - demunge_buf (wc->rbuf, wc->rbuf, WF_PROGRAM_BYTES); - break; - - case WFC_UPLOAD_EDRUM_PROGRAM: - demunge_buf (wc->rbuf, wc->rbuf, WF_DRUM_BYTES - 1); - break; - - case WFC_UPLOAD_SAMPLE_HEADER: - process_sample_hdr (wc->rbuf); - break; - - case WFC_UPLOAD_SAMPLE_ALIAS: - snd_printk ("support for " - "sample aliases still " - "being considered.\n"); - break; - - case WFC_VMIDI_OFF: - snd_wavefront_midi_disable_virtual (acard); - break; - - case WFC_VMIDI_ON: - snd_wavefront_midi_enable_virtual (acard); - break; - } - } - - return 0; -} - -int -snd_wavefront_synth_open (struct snd_hwdep *hw, struct file *file) - -{ - if (!try_module_get(hw->card->module)) - return -EFAULT; - file->private_data = hw; - return 0; -} - -int -snd_wavefront_synth_release (struct snd_hwdep *hw, struct file *file) - -{ - module_put(hw->card->module); - return 0; -} - -int -snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file, - unsigned int cmd, unsigned long arg) - -{ - struct snd_card *card; - snd_wavefront_t *dev; - snd_wavefront_card_t *acard; - wavefront_control *wc; - void __user *argp = (void __user *)arg; - int err; - - card = (struct snd_card *) hw->card; - - if (snd_BUG_ON(!card)) - return -ENODEV; - if (snd_BUG_ON(!card->private_data)) - return -ENODEV; - - acard = card->private_data; - dev = &acard->wavefront; - - switch (cmd) { - case WFCTL_LOAD_SPP: - if (wavefront_load_patch (dev, argp) != 0) { - return -EIO; - } - break; - - case WFCTL_WFCMD: - wc = memdup_user(argp, sizeof(*wc)); - if (IS_ERR(wc)) - return PTR_ERR(wc); - - if (wavefront_synth_control (acard, wc) < 0) - err = -EIO; - else if (copy_to_user (argp, wc, sizeof (*wc))) - err = -EFAULT; - else - err = 0; - kfree(wc); - return err; - - default: - return -EINVAL; - } - - return 0; -} - - -/***********************************************************************/ -/* WaveFront: interface for card-level wavefront module */ -/***********************************************************************/ - -void -snd_wavefront_internal_interrupt (snd_wavefront_card_t *card) -{ - snd_wavefront_t *dev = &card->wavefront; - - /* - Some comments on interrupts. I attempted a version of this - driver that used interrupts throughout the code instead of - doing busy and/or sleep-waiting. Alas, it appears that once - the Motorola firmware is downloaded, the card *never* - generates an RX interrupt. These are successfully generated - during firmware loading, and after that wavefront_status() - reports that an interrupt is pending on the card from time - to time, but it never seems to be delivered to this - driver. Note also that wavefront_status() continues to - report that RX interrupts are enabled, suggesting that I - didn't goof up and disable them by mistake. - - Thus, I stepped back to a prior version of - wavefront_wait(), the only place where this really - matters. Its sad, but I've looked through the code to check - on things, and I really feel certain that the Motorola - firmware prevents RX-ready interrupts. - */ - - if ((wavefront_status(dev) & (STAT_INTR_READ|STAT_INTR_WRITE)) == 0) { - return; - } - - spin_lock(&dev->irq_lock); - dev->irq_ok = 1; - dev->irq_cnt++; - spin_unlock(&dev->irq_lock); - wake_up(&dev->interrupt_sleeper); -} - -/* STATUS REGISTER - -0 Host Rx Interrupt Enable (1=Enabled) -1 Host Rx Register Full (1=Full) -2 Host Rx Interrupt Pending (1=Interrupt) -3 Unused -4 Host Tx Interrupt (1=Enabled) -5 Host Tx Register empty (1=Empty) -6 Host Tx Interrupt Pending (1=Interrupt) -7 Unused -*/ - -static int __devinit -snd_wavefront_interrupt_bits (int irq) - -{ - int bits; - - switch (irq) { - case 9: - bits = 0x00; - break; - case 5: - bits = 0x08; - break; - case 12: - bits = 0x10; - break; - case 15: - bits = 0x18; - break; - - default: - snd_printk ("invalid IRQ %d\n", irq); - bits = -1; - } - - return bits; -} - -static void __devinit -wavefront_should_cause_interrupt (snd_wavefront_t *dev, - int val, int port, unsigned long timeout) - -{ - wait_queue_t wait; - - init_waitqueue_entry(&wait, current); - spin_lock_irq(&dev->irq_lock); - add_wait_queue(&dev->interrupt_sleeper, &wait); - dev->irq_ok = 0; - outb (val,port); - spin_unlock_irq(&dev->irq_lock); - while (!dev->irq_ok && time_before(jiffies, timeout)) { - schedule_timeout_uninterruptible(1); - barrier(); - } -} - -static int __devinit -wavefront_reset_to_cleanliness (snd_wavefront_t *dev) - -{ - int bits; - int hwv[2]; - - /* IRQ already checked */ - - bits = snd_wavefront_interrupt_bits (dev->irq); - - /* try reset of port */ - - outb (0x0, dev->control_port); - - /* At this point, the board is in reset, and the H/W initialization - register is accessed at the same address as the data port. - - Bit 7 - Enable IRQ Driver - 0 - Tri-state the Wave-Board drivers for the PC Bus IRQs - 1 - Enable IRQ selected by bits 5:3 to be driven onto the PC Bus. - - Bit 6 - MIDI Interface Select - - 0 - Use the MIDI Input from the 26-pin WaveBlaster - compatible header as the serial MIDI source - 1 - Use the MIDI Input from the 9-pin D connector as the - serial MIDI source. - - Bits 5:3 - IRQ Selection - 0 0 0 - IRQ 2/9 - 0 0 1 - IRQ 5 - 0 1 0 - IRQ 12 - 0 1 1 - IRQ 15 - 1 0 0 - Reserved - 1 0 1 - Reserved - 1 1 0 - Reserved - 1 1 1 - Reserved - - Bits 2:1 - Reserved - Bit 0 - Disable Boot ROM - 0 - memory accesses to 03FC30-03FFFFH utilize the internal Boot ROM - 1 - memory accesses to 03FC30-03FFFFH are directed to external - storage. - - */ - - /* configure hardware: IRQ, enable interrupts, - plus external 9-pin MIDI interface selected - */ - - outb (0x80 | 0x40 | bits, dev->data_port); - - /* CONTROL REGISTER - - 0 Host Rx Interrupt Enable (1=Enabled) 0x1 - 1 Unused 0x2 - 2 Unused 0x4 - 3 Unused 0x8 - 4 Host Tx Interrupt Enable 0x10 - 5 Mute (0=Mute; 1=Play) 0x20 - 6 Master Interrupt Enable (1=Enabled) 0x40 - 7 Master Reset (0=Reset; 1=Run) 0x80 - - Take us out of reset, mute output, master + TX + RX interrupts on. - - We'll get an interrupt presumably to tell us that the TX - register is clear. - */ - - wavefront_should_cause_interrupt(dev, 0x80|0x40|0x10|0x1, - dev->control_port, - (reset_time*HZ)/100); - - /* Note: data port is now the data port, not the h/w initialization - port. - */ - - if (!dev->irq_ok) { - snd_printk ("intr not received after h/w un-reset.\n"); - goto gone_bad; - } - - /* Note: data port is now the data port, not the h/w initialization - port. - - At this point, only "HW VERSION" or "DOWNLOAD OS" commands - will work. So, issue one of them, and wait for TX - interrupt. This can take a *long* time after a cold boot, - while the ISC ROM does its RAM test. The SDK says up to 4 - seconds - with 12MB of RAM on a Tropez+, it takes a lot - longer than that (~16secs). Note that the card understands - the difference between a warm and a cold boot, so - subsequent ISC2115 reboots (say, caused by module - reloading) will get through this much faster. - - XXX Interesting question: why is no RX interrupt received first ? - */ - - wavefront_should_cause_interrupt(dev, WFC_HARDWARE_VERSION, - dev->data_port, ramcheck_time*HZ); - - if (!dev->irq_ok) { - snd_printk ("post-RAM-check interrupt not received.\n"); - goto gone_bad; - } - - if (!wavefront_wait (dev, STAT_CAN_READ)) { - snd_printk ("no response to HW version cmd.\n"); - goto gone_bad; - } - - if ((hwv[0] = wavefront_read (dev)) == -1) { - snd_printk ("board not responding correctly.\n"); - goto gone_bad; - } - - if (hwv[0] == 0xFF) { /* NAK */ - - /* Board's RAM test failed. Try to read error code, - and tell us about it either way. - */ - - if ((hwv[0] = wavefront_read (dev)) == -1) { - snd_printk ("on-board RAM test failed " - "(bad error code).\n"); - } else { - snd_printk ("on-board RAM test failed " - "(error code: 0x%x).\n", - hwv[0]); - } - goto gone_bad; - } - - /* We're OK, just get the next byte of the HW version response */ - - if ((hwv[1] = wavefront_read (dev)) == -1) { - snd_printk ("incorrect h/w response.\n"); - goto gone_bad; - } - - snd_printk ("hardware version %d.%d\n", - hwv[0], hwv[1]); - - return 0; - - - gone_bad: - return (1); -} - -static int __devinit -wavefront_download_firmware (snd_wavefront_t *dev, char *path) - -{ - const unsigned char *buf; - int len, err; - int section_cnt_downloaded = 0; - const struct firmware *firmware; - - err = request_firmware(&firmware, path, dev->card->dev); - if (err < 0) { - snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path); - return 1; - } - - len = 0; - buf = firmware->data; - for (;;) { - int section_length = *(signed char *)buf; - if (section_length == 0) - break; - if (section_length < 0 || section_length > WF_SECTION_MAX) { - snd_printk(KERN_ERR - "invalid firmware section length %d\n", - section_length); - goto failure; - } - buf++; - len++; - - if (firmware->size < len + section_length) { - snd_printk(KERN_ERR "firmware section read error.\n"); - goto failure; - } - - /* Send command */ - if (wavefront_write(dev, WFC_DOWNLOAD_OS)) - goto failure; - - for (; section_length; section_length--) { - if (wavefront_write(dev, *buf)) - goto failure; - buf++; - len++; - } - - /* get ACK */ - if (!wavefront_wait(dev, STAT_CAN_READ)) { - snd_printk(KERN_ERR "time out for firmware ACK.\n"); - goto failure; - } - err = inb(dev->data_port); - if (err != WF_ACK) { - snd_printk(KERN_ERR - "download of section #%d not " - "acknowledged, ack = 0x%x\n", - section_cnt_downloaded + 1, err); - goto failure; - } - - section_cnt_downloaded++; - } - - release_firmware(firmware); - return 0; - - failure: - release_firmware(firmware); - snd_printk(KERN_ERR "firmware download failed!!!\n"); - return 1; -} - - -static int __devinit -wavefront_do_reset (snd_wavefront_t *dev) - -{ - char voices[1]; - - if (wavefront_reset_to_cleanliness (dev)) { - snd_printk ("hw reset failed.\n"); - goto gone_bad; - } - - if (dev->israw) { - if (wavefront_download_firmware (dev, ospath)) { - goto gone_bad; - } - - dev->israw = 0; - - /* Wait for the OS to get running. The protocol for - this is non-obvious, and was determined by - using port-IO tracing in DOSemu and some - experimentation here. - - Rather than using timed waits, use interrupts creatively. - */ - - wavefront_should_cause_interrupt (dev, WFC_NOOP, - dev->data_port, - (osrun_time*HZ)); - - if (!dev->irq_ok) { - snd_printk ("no post-OS interrupt.\n"); - goto gone_bad; - } - - /* Now, do it again ! */ - - wavefront_should_cause_interrupt (dev, WFC_NOOP, - dev->data_port, (10*HZ)); - - if (!dev->irq_ok) { - snd_printk ("no post-OS interrupt(2).\n"); - goto gone_bad; - } - - /* OK, no (RX/TX) interrupts any more, but leave mute - in effect. - */ - - outb (0x80|0x40, dev->control_port); - } - - /* SETUPSND.EXE asks for sample memory config here, but since i - have no idea how to interpret the result, we'll forget - about it. - */ - - if ((dev->freemem = wavefront_freemem (dev)) < 0) { - goto gone_bad; - } - - snd_printk ("available DRAM %dk\n", dev->freemem / 1024); - - if (wavefront_write (dev, 0xf0) || - wavefront_write (dev, 1) || - (wavefront_read (dev) < 0)) { - dev->debug = 0; - snd_printk ("MPU emulation mode not set.\n"); - goto gone_bad; - } - - voices[0] = 32; - - if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) { - snd_printk ("cannot set number of voices to 32.\n"); - goto gone_bad; - } - - - return 0; - - gone_bad: - /* reset that sucker so that it doesn't bother us. */ - - outb (0x0, dev->control_port); - dev->interrupts_are_midi = 0; - return 1; -} - -int __devinit -snd_wavefront_start (snd_wavefront_t *dev) - -{ - int samples_are_from_rom; - - /* IMPORTANT: assumes that snd_wavefront_detect() and/or - wavefront_reset_to_cleanliness() has already been called - */ - - if (dev->israw) { - samples_are_from_rom = 1; - } else { - /* XXX is this always true ? */ - samples_are_from_rom = 0; - } - - if (dev->israw || fx_raw) { - if (wavefront_do_reset (dev)) { - return -1; - } - } - /* Check for FX device, present only on Tropez+ */ - - dev->has_fx = (snd_wavefront_fx_detect (dev) == 0); - - if (dev->has_fx && fx_raw) { - snd_wavefront_fx_start (dev); - } - - wavefront_get_sample_status (dev, samples_are_from_rom); - wavefront_get_program_status (dev); - wavefront_get_patch_status (dev); - - /* Start normal operation: unreset, master interrupt enabled, no mute - */ - - outb (0x80|0x40|0x20, dev->control_port); - - return (0); -} - -int __devinit -snd_wavefront_detect (snd_wavefront_card_t *card) - -{ - unsigned char rbuf[4], wbuf[4]; - snd_wavefront_t *dev = &card->wavefront; - - /* returns zero if a WaveFront card is successfully detected. - negative otherwise. - */ - - dev->israw = 0; - dev->has_fx = 0; - dev->debug = debug_default; - dev->interrupts_are_midi = 0; - dev->irq_cnt = 0; - dev->rom_samples_rdonly = 1; - - if (snd_wavefront_cmd (dev, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) { - - dev->fw_version[0] = rbuf[0]; - dev->fw_version[1] = rbuf[1]; - - snd_printk ("firmware %d.%d already loaded.\n", - rbuf[0], rbuf[1]); - - /* check that a command actually works */ - - if (snd_wavefront_cmd (dev, WFC_HARDWARE_VERSION, - rbuf, wbuf) == 0) { - dev->hw_version[0] = rbuf[0]; - dev->hw_version[1] = rbuf[1]; - } else { - snd_printk ("not raw, but no " - "hardware version!\n"); - return -1; - } - - if (!wf_raw) { - return 0; - } else { - snd_printk ("reloading firmware as you requested.\n"); - dev->israw = 1; - } - - } else { - - dev->israw = 1; - snd_printk ("no response to firmware probe, assume raw.\n"); - - } - - return 0; -} - -MODULE_FIRMWARE(DEFAULT_OSPATH); diff --git a/ANDROID_3.4.5/sound/isa/wss/Makefile b/ANDROID_3.4.5/sound/isa/wss/Makefile deleted file mode 100644 index 454fee76..00000000 --- a/ANDROID_3.4.5/sound/isa/wss/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for ALSA -# Copyright (c) 2008 by Jaroslav Kysela <perex@perex.cz> -# - -snd-wss-lib-objs := wss_lib.o - -# Toplevel Module Dependency -obj-$(CONFIG_SND_WSS_LIB) += snd-wss-lib.o - diff --git a/ANDROID_3.4.5/sound/isa/wss/wss_lib.c b/ANDROID_3.4.5/sound/isa/wss/wss_lib.c deleted file mode 100644 index 49c8a0c2..00000000 --- a/ANDROID_3.4.5/sound/isa/wss/wss_lib.c +++ /dev/null @@ -1,2304 +0,0 @@ -/* - * Copyright (c) by Jaroslav Kysela <perex@perex.cz> - * Routines for control of CS4231(A)/CS4232/InterWave & compatible chips - * - * Bugs: - * - sometimes record brokes playback with WSS portion of - * Yamaha OPL3-SA3 chip - * - CS4231 (GUS MAX) - still trouble with occasional noises - * - broken initialization? - * - * 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/pm.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/wss.h> -#include <sound/pcm_params.h> -#include <sound/tlv.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/irq.h> - -MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); -MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips"); -MODULE_LICENSE("GPL"); - -#if 0 -#define SNDRV_DEBUG_MCE -#endif - -/* - * Some variables - */ - -static unsigned char freq_bits[14] = { - /* 5510 */ 0x00 | CS4231_XTAL2, - /* 6620 */ 0x0E | CS4231_XTAL2, - /* 8000 */ 0x00 | CS4231_XTAL1, - /* 9600 */ 0x0E | CS4231_XTAL1, - /* 11025 */ 0x02 | CS4231_XTAL2, - /* 16000 */ 0x02 | CS4231_XTAL1, - /* 18900 */ 0x04 | CS4231_XTAL2, - /* 22050 */ 0x06 | CS4231_XTAL2, - /* 27042 */ 0x04 | CS4231_XTAL1, - /* 32000 */ 0x06 | CS4231_XTAL1, - /* 33075 */ 0x0C | CS4231_XTAL2, - /* 37800 */ 0x08 | CS4231_XTAL2, - /* 44100 */ 0x0A | CS4231_XTAL2, - /* 48000 */ 0x0C | CS4231_XTAL1 -}; - -static unsigned int rates[14] = { - 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, - 27042, 32000, 33075, 37800, 44100, 48000 -}; - -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static int snd_wss_xrate(struct snd_pcm_runtime *runtime) -{ - return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates); -} - -static unsigned char snd_wss_original_image[32] = -{ - 0x00, /* 00/00 - lic */ - 0x00, /* 01/01 - ric */ - 0x9f, /* 02/02 - la1ic */ - 0x9f, /* 03/03 - ra1ic */ - 0x9f, /* 04/04 - la2ic */ - 0x9f, /* 05/05 - ra2ic */ - 0xbf, /* 06/06 - loc */ - 0xbf, /* 07/07 - roc */ - 0x20, /* 08/08 - pdfr */ - CS4231_AUTOCALIB, /* 09/09 - ic */ - 0x00, /* 0a/10 - pc */ - 0x00, /* 0b/11 - ti */ - CS4231_MODE2, /* 0c/12 - mi */ - 0xfc, /* 0d/13 - lbc */ - 0x00, /* 0e/14 - pbru */ - 0x00, /* 0f/15 - pbrl */ - 0x80, /* 10/16 - afei */ - 0x01, /* 11/17 - afeii */ - 0x9f, /* 12/18 - llic */ - 0x9f, /* 13/19 - rlic */ - 0x00, /* 14/20 - tlb */ - 0x00, /* 15/21 - thb */ - 0x00, /* 16/22 - la3mic/reserved */ - 0x00, /* 17/23 - ra3mic/reserved */ - 0x00, /* 18/24 - afs */ - 0x00, /* 19/25 - lamoc/version */ - 0xcf, /* 1a/26 - mioc */ - 0x00, /* 1b/27 - ramoc/reserved */ - 0x20, /* 1c/28 - cdfr */ - 0x00, /* 1d/29 - res4 */ - 0x00, /* 1e/30 - cbru */ - 0x00, /* 1f/31 - cbrl */ -}; - -static unsigned char snd_opti93x_original_image[32] = -{ - 0x00, /* 00/00 - l_mixout_outctrl */ - 0x00, /* 01/01 - r_mixout_outctrl */ - 0x88, /* 02/02 - l_cd_inctrl */ - 0x88, /* 03/03 - r_cd_inctrl */ - 0x88, /* 04/04 - l_a1/fm_inctrl */ - 0x88, /* 05/05 - r_a1/fm_inctrl */ - 0x80, /* 06/06 - l_dac_inctrl */ - 0x80, /* 07/07 - r_dac_inctrl */ - 0x00, /* 08/08 - ply_dataform_reg */ - 0x00, /* 09/09 - if_conf */ - 0x00, /* 0a/10 - pin_ctrl */ - 0x00, /* 0b/11 - err_init_reg */ - 0x0a, /* 0c/12 - id_reg */ - 0x00, /* 0d/13 - reserved */ - 0x00, /* 0e/14 - ply_upcount_reg */ - 0x00, /* 0f/15 - ply_lowcount_reg */ - 0x88, /* 10/16 - reserved/l_a1_inctrl */ - 0x88, /* 11/17 - reserved/r_a1_inctrl */ - 0x88, /* 12/18 - l_line_inctrl */ - 0x88, /* 13/19 - r_line_inctrl */ - 0x88, /* 14/20 - l_mic_inctrl */ - 0x88, /* 15/21 - r_mic_inctrl */ - 0x80, /* 16/22 - l_out_outctrl */ - 0x80, /* 17/23 - r_out_outctrl */ - 0x00, /* 18/24 - reserved */ - 0x00, /* 19/25 - reserved */ - 0x00, /* 1a/26 - reserved */ - 0x00, /* 1b/27 - reserved */ - 0x00, /* 1c/28 - cap_dataform_reg */ - 0x00, /* 1d/29 - reserved */ - 0x00, /* 1e/30 - cap_upcount_reg */ - 0x00 /* 1f/31 - cap_lowcount_reg */ -}; - -/* - * Basic I/O functions - */ - -static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val) -{ - outb(val, chip->port + offset); -} - -static inline u8 wss_inb(struct snd_wss *chip, u8 offset) -{ - return inb(chip->port + offset); -} - -static void snd_wss_wait(struct snd_wss *chip) -{ - int timeout; - - for (timeout = 250; - timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); -} - -static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, - unsigned char value) -{ - int timeout; - - for (timeout = 250; - timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); - timeout--) - udelay(10); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - wss_outb(chip, CS4231P(REG), value); - mb(); -} - -void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value) -{ - snd_wss_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "out: auto calibration time out " - "- reg = 0x%x, value = 0x%x\n", reg, value); -#endif - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - wss_outb(chip, CS4231P(REG), value); - chip->image[reg] = value; - mb(); - snd_printdd("codec out - reg 0x%x = 0x%x\n", - chip->mce_bit | reg, value); -} -EXPORT_SYMBOL(snd_wss_out); - -unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg) -{ - snd_wss_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "in: auto calibration time out " - "- reg = 0x%x\n", reg); -#endif - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); - mb(); - return wss_inb(chip, CS4231P(REG)); -} -EXPORT_SYMBOL(snd_wss_in); - -void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg, - unsigned char val) -{ - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); - wss_outb(chip, CS4231P(REG), - reg | (chip->image[CS4236_EXT_REG] & 0x01)); - wss_outb(chip, CS4231P(REG), val); - chip->eimage[CS4236_REG(reg)] = val; -#if 0 - printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val); -#endif -} -EXPORT_SYMBOL(snd_cs4236_ext_out); - -unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg) -{ - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17); - wss_outb(chip, CS4231P(REG), - reg | (chip->image[CS4236_EXT_REG] & 0x01)); -#if 1 - return wss_inb(chip, CS4231P(REG)); -#else - { - unsigned char res; - res = wss_inb(chip, CS4231P(REG)); - printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n", - reg, res); - return res; - } -#endif -} -EXPORT_SYMBOL(snd_cs4236_ext_in); - -#if 0 - -static void snd_wss_debug(struct snd_wss *chip) -{ - printk(KERN_DEBUG - "CS4231 REGS: INDEX = 0x%02x " - " STATUS = 0x%02x\n", - wss_inb(chip, CS4231P(REGSEL)), - wss_inb(chip, CS4231P(STATUS))); - printk(KERN_DEBUG - " 0x00: left input = 0x%02x " - " 0x10: alt 1 (CFIG 2) = 0x%02x\n", - snd_wss_in(chip, 0x00), - snd_wss_in(chip, 0x10)); - printk(KERN_DEBUG - " 0x01: right input = 0x%02x " - " 0x11: alt 2 (CFIG 3) = 0x%02x\n", - snd_wss_in(chip, 0x01), - snd_wss_in(chip, 0x11)); - printk(KERN_DEBUG - " 0x02: GF1 left input = 0x%02x " - " 0x12: left line in = 0x%02x\n", - snd_wss_in(chip, 0x02), - snd_wss_in(chip, 0x12)); - printk(KERN_DEBUG - " 0x03: GF1 right input = 0x%02x " - " 0x13: right line in = 0x%02x\n", - snd_wss_in(chip, 0x03), - snd_wss_in(chip, 0x13)); - printk(KERN_DEBUG - " 0x04: CD left input = 0x%02x " - " 0x14: timer low = 0x%02x\n", - snd_wss_in(chip, 0x04), - snd_wss_in(chip, 0x14)); - printk(KERN_DEBUG - " 0x05: CD right input = 0x%02x " - " 0x15: timer high = 0x%02x\n", - snd_wss_in(chip, 0x05), - snd_wss_in(chip, 0x15)); - printk(KERN_DEBUG - " 0x06: left output = 0x%02x " - " 0x16: left MIC (PnP) = 0x%02x\n", - snd_wss_in(chip, 0x06), - snd_wss_in(chip, 0x16)); - printk(KERN_DEBUG - " 0x07: right output = 0x%02x " - " 0x17: right MIC (PnP) = 0x%02x\n", - snd_wss_in(chip, 0x07), - snd_wss_in(chip, 0x17)); - printk(KERN_DEBUG - " 0x08: playback format = 0x%02x " - " 0x18: IRQ status = 0x%02x\n", - snd_wss_in(chip, 0x08), - snd_wss_in(chip, 0x18)); - printk(KERN_DEBUG - " 0x09: iface (CFIG 1) = 0x%02x " - " 0x19: left line out = 0x%02x\n", - snd_wss_in(chip, 0x09), - snd_wss_in(chip, 0x19)); - printk(KERN_DEBUG - " 0x0a: pin control = 0x%02x " - " 0x1a: mono control = 0x%02x\n", - snd_wss_in(chip, 0x0a), - snd_wss_in(chip, 0x1a)); - printk(KERN_DEBUG - " 0x0b: init & status = 0x%02x " - " 0x1b: right line out = 0x%02x\n", - snd_wss_in(chip, 0x0b), - snd_wss_in(chip, 0x1b)); - printk(KERN_DEBUG - " 0x0c: revision & mode = 0x%02x " - " 0x1c: record format = 0x%02x\n", - snd_wss_in(chip, 0x0c), - snd_wss_in(chip, 0x1c)); - printk(KERN_DEBUG - " 0x0d: loopback = 0x%02x " - " 0x1d: var freq (PnP) = 0x%02x\n", - snd_wss_in(chip, 0x0d), - snd_wss_in(chip, 0x1d)); - printk(KERN_DEBUG - " 0x0e: ply upr count = 0x%02x " - " 0x1e: ply lwr count = 0x%02x\n", - snd_wss_in(chip, 0x0e), - snd_wss_in(chip, 0x1e)); - printk(KERN_DEBUG - " 0x0f: rec upr count = 0x%02x " - " 0x1f: rec lwr count = 0x%02x\n", - snd_wss_in(chip, 0x0f), - snd_wss_in(chip, 0x1f)); -} - -#endif - -/* - * CS4231 detection / MCE routines - */ - -static void snd_wss_busy_wait(struct snd_wss *chip) -{ - int timeout; - - /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ - for (timeout = 5; timeout > 0; timeout--) - wss_inb(chip, CS4231P(REGSEL)); - /* end of cleanup sequence */ - for (timeout = 25000; - timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); - timeout--) - udelay(10); -} - -void snd_wss_mce_up(struct snd_wss *chip) -{ - unsigned long flags; - int timeout; - - snd_wss_wait(chip); -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG - "mce_up - auto calibration time out (0)\n"); -#endif - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit |= CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - if (timeout == 0x80) - snd_printk(KERN_DEBUG "mce_up [0x%lx]: " - "serious init problem - codec still busy\n", - chip->port); - if (!(timeout & CS4231_MCE)) - wss_outb(chip, CS4231P(REGSEL), - chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); -} -EXPORT_SYMBOL(snd_wss_mce_up); - -void snd_wss_mce_down(struct snd_wss *chip) -{ - unsigned long flags; - unsigned long end_time; - int timeout; - int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848; - - snd_wss_busy_wait(chip); - -#ifdef CONFIG_SND_DEBUG - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk(KERN_DEBUG "mce_down [0x%lx] - " - "auto calibration time out (0)\n", - (long)CS4231P(REGSEL)); -#endif - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit &= ~CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (timeout == 0x80) - snd_printk(KERN_DEBUG "mce_down [0x%lx]: " - "serious init problem - codec still busy\n", - chip->port); - if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) - return; - - /* - * Wait for (possible -- during init auto-calibration may not be set) - * calibration process to start. Needs up to 5 sample periods on AD1848 - * which at the slowest possible rate of 5.5125 kHz means 907 us. - */ - msleep(1); - - snd_printdd("(1) jiffies = %lu\n", jiffies); - - /* check condition up to 250 ms */ - end_time = jiffies + msecs_to_jiffies(250); - while (snd_wss_in(chip, CS4231_TEST_INIT) & - CS4231_CALIB_IN_PROGRESS) { - - if (time_after(jiffies, end_time)) { - snd_printk(KERN_ERR "mce_down - " - "auto calibration time out (2)\n"); - return; - } - msleep(1); - } - - snd_printdd("(2) jiffies = %lu\n", jiffies); - - /* check condition up to 100 ms */ - end_time = jiffies + msecs_to_jiffies(100); - while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { - if (time_after(jiffies, end_time)) { - snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); - return; - } - msleep(1); - } - - snd_printdd("(3) jiffies = %lu\n", jiffies); - snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL))); -} -EXPORT_SYMBOL(snd_wss_mce_down); - -static unsigned int snd_wss_get_count(unsigned char format, unsigned int size) -{ - switch (format & 0xe0) { - case CS4231_LINEAR_16: - case CS4231_LINEAR_16_BIG: - size >>= 1; - break; - case CS4231_ADPCM_16: - return size >> 2; - } - if (format & CS4231_STEREO) - size >>= 1; - return size; -} - -static int snd_wss_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - int result = 0; - unsigned int what; - struct snd_pcm_substream *s; - int do_start; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - do_start = 1; break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - do_start = 0; break; - default: - return -EINVAL; - } - - what = 0; - snd_pcm_group_for_each_entry(s, substream) { - if (s == chip->playback_substream) { - what |= CS4231_PLAYBACK_ENABLE; - snd_pcm_trigger_done(s, substream); - } else if (s == chip->capture_substream) { - what |= CS4231_RECORD_ENABLE; - snd_pcm_trigger_done(s, substream); - } - } - spin_lock(&chip->reg_lock); - if (do_start) { - chip->image[CS4231_IFACE_CTRL] |= what; - if (chip->trigger) - chip->trigger(chip, what, 1); - } else { - chip->image[CS4231_IFACE_CTRL] &= ~what; - if (chip->trigger) - chip->trigger(chip, what, 0); - } - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock(&chip->reg_lock); -#if 0 - snd_wss_debug(chip); -#endif - return result; -} - -/* - * CODEC I/O - */ - -static unsigned char snd_wss_get_rate(unsigned int rate) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(rates); i++) - if (rate == rates[i]) - return freq_bits[i]; - // snd_BUG(); - return freq_bits[ARRAY_SIZE(rates) - 1]; -} - -static unsigned char snd_wss_get_format(struct snd_wss *chip, - int format, - int channels) -{ - unsigned char rformat; - - rformat = CS4231_LINEAR_8; - switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break; - case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break; - case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break; - case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break; - case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break; - } - if (channels > 1) - rformat |= CS4231_STEREO; -#if 0 - snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode); -#endif - return rformat; -} - -static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) -{ - unsigned long flags; - - mute = mute ? 0x80 : 0; - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->calibrate_mute == mute) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - return; - } - if (!mute) { - snd_wss_dout(chip, CS4231_LEFT_INPUT, - chip->image[CS4231_LEFT_INPUT]); - snd_wss_dout(chip, CS4231_RIGHT_INPUT, - chip->image[CS4231_RIGHT_INPUT]); - snd_wss_dout(chip, CS4231_LOOPBACK, - chip->image[CS4231_LOOPBACK]); - } else { - snd_wss_dout(chip, CS4231_LEFT_INPUT, - 0); - snd_wss_dout(chip, CS4231_RIGHT_INPUT, - 0); - snd_wss_dout(chip, CS4231_LOOPBACK, - 0xfd); - } - - snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, - mute | chip->image[CS4231_AUX1_LEFT_INPUT]); - snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, - mute | chip->image[CS4231_AUX1_RIGHT_INPUT]); - snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT, - mute | chip->image[CS4231_AUX2_LEFT_INPUT]); - snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT, - mute | chip->image[CS4231_AUX2_RIGHT_INPUT]); - snd_wss_dout(chip, CS4231_LEFT_OUTPUT, - mute | chip->image[CS4231_LEFT_OUTPUT]); - snd_wss_dout(chip, CS4231_RIGHT_OUTPUT, - mute | chip->image[CS4231_RIGHT_OUTPUT]); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) { - snd_wss_dout(chip, CS4231_LEFT_LINE_IN, - mute | chip->image[CS4231_LEFT_LINE_IN]); - snd_wss_dout(chip, CS4231_RIGHT_LINE_IN, - mute | chip->image[CS4231_RIGHT_LINE_IN]); - snd_wss_dout(chip, CS4231_MONO_CTRL, - mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); - } - if (chip->hardware == WSS_HW_INTERWAVE) { - snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT, - mute | chip->image[CS4231_LEFT_MIC_INPUT]); - snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT, - mute | chip->image[CS4231_RIGHT_MIC_INPUT]); - snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT, - mute | chip->image[CS4231_LINE_LEFT_OUTPUT]); - snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT, - mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]); - } - chip->calibrate_mute = mute; - spin_unlock_irqrestore(&chip->reg_lock, flags); -} - -static void snd_wss_playback_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char pdfr) -{ - unsigned long flags; - int full_calib = 1; - - mutex_lock(&chip->mce_mutex); - if (chip->hardware == WSS_HW_CS4231A || - (chip->hardware & WSS_HW_CS4232_MASK)) { - spin_lock_irqsave(&chip->reg_lock, flags); - if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) { /* rate is same? */ - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x10); - chip->image[CS4231_PLAYBK_FORMAT] = pdfr; - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - chip->image[CS4231_PLAYBK_FORMAT]); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] &= ~0x10); - udelay(100); /* Fixes audible clicks at least on GUS MAX */ - full_calib = 0; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - } else if (chip->hardware == WSS_HW_AD1845) { - unsigned rate = params_rate(params); - - /* - * Program the AD1845 correctly for the playback stream. - * Note that we do NOT need to toggle the MCE bit because - * the PLAYBACK_ENABLE bit of the Interface Configuration - * register is set. - * - * NOTE: We seem to need to write to the MSB before the LSB - * to get the correct sample frequency. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); - snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); - snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); - full_calib = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - if (full_calib) { - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) { - if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) - pdfr = (pdfr & 0xf0) | - (chip->image[CS4231_REC_FORMAT] & 0x0f); - } else { - chip->image[CS4231_PLAYBK_FORMAT] = pdfr; - } - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (chip->hardware == WSS_HW_OPL3SA2) - udelay(100); /* this seems to help */ - snd_wss_mce_down(chip); - } - mutex_unlock(&chip->mce_mutex); -} - -static void snd_wss_capture_format(struct snd_wss *chip, - struct snd_pcm_hw_params *params, - unsigned char cdfr) -{ - unsigned long flags; - int full_calib = 1; - - mutex_lock(&chip->mce_mutex); - if (chip->hardware == WSS_HW_CS4231A || - (chip->hardware & WSS_HW_CS4232_MASK)) { - spin_lock_irqsave(&chip->reg_lock, flags); - if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) || /* rate is same? */ - (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | 0x20); - snd_wss_out(chip, CS4231_REC_FORMAT, - chip->image[CS4231_REC_FORMAT] = cdfr); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] &= ~0x20); - full_calib = 0; - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - } else if (chip->hardware == WSS_HW_AD1845) { - unsigned rate = params_rate(params); - - /* - * Program the AD1845 correctly for the capture stream. - * Note that we do NOT need to toggle the MCE bit because - * the PLAYBACK_ENABLE bit of the Interface Configuration - * register is set. - * - * NOTE: We seem to need to write to the MSB before the LSB - * to get the correct sample frequency. - */ - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); - snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); - snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); - full_calib = 0; - spin_unlock_irqrestore(&chip->reg_lock, flags); - } - if (full_calib) { - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (chip->hardware != WSS_HW_INTERWAVE && - !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) { - if (chip->single_dma) - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr); - else - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) | - (cdfr & 0x0f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - } - if (chip->hardware & WSS_HW_AD1848_MASK) - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr); - else - snd_wss_out(chip, CS4231_REC_FORMAT, cdfr); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - } - mutex_unlock(&chip->mce_mutex); -} - -/* - * Timer interface - */ - -static unsigned long snd_wss_timer_resolution(struct snd_timer *timer) -{ - struct snd_wss *chip = snd_timer_chip(timer); - if (chip->hardware & WSS_HW_CS4236B_MASK) - return 14467; - else - return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920; -} - -static int snd_wss_timer_start(struct snd_timer *timer) -{ - unsigned long flags; - unsigned int ticks; - struct snd_wss *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); - ticks = timer->sticks; - if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 || - (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] || - (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) { - chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8); - snd_wss_out(chip, CS4231_TIMER_HIGH, - chip->image[CS4231_TIMER_HIGH]); - chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks; - snd_wss_out(chip, CS4231_TIMER_LOW, - chip->image[CS4231_TIMER_LOW]); - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | - CS4231_TIMER_ENABLE); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_wss_timer_stop(struct snd_timer *timer) -{ - unsigned long flags; - struct snd_wss *chip = snd_timer_chip(timer); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; - snd_wss_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static void snd_wss_init(struct snd_wss *chip) -{ - unsigned long flags; - - snd_wss_calibrate_mute(chip, 1); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (1)\n"); -#endif - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | - CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | - CS4231_RECORD_PIO | - CS4231_CALIB_MODE); - chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (2)\n"); -#endif - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; - snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); - snd_wss_out(chip, - CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n", - chip->image[CS4231_ALT_FEATURE_1]); -#endif - - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_ALT_FEATURE_2, - chip->image[CS4231_ALT_FEATURE_2]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_PLAYBK_FORMAT, - chip->image[CS4231_PLAYBK_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (4)\n"); -#endif - - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - snd_wss_out(chip, CS4231_REC_FORMAT, - chip->image[CS4231_REC_FORMAT]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - snd_wss_calibrate_mute(chip, 0); - -#ifdef SNDRV_DEBUG_MCE - snd_printk(KERN_DEBUG "init: (5)\n"); -#endif -} - -static int snd_wss_open(struct snd_wss *chip, unsigned int mode) -{ - unsigned long flags; - - mutex_lock(&chip->open_mutex); - if ((chip->mode & mode) || - ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) { - mutex_unlock(&chip->open_mutex); - return -EAGAIN; - } - if (chip->mode & WSS_MODE_OPEN) { - chip->mode |= mode; - mutex_unlock(&chip->open_mutex); - return 0; - } - /* ok. now enable and ack CODEC IRQ */ - spin_lock_irqsave(&chip->reg_lock, flags); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) { - snd_wss_out(chip, CS4231_IRQ_STATUS, - CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - } - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE; - snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) { - snd_wss_out(chip, CS4231_IRQ_STATUS, - CS4231_PLAYBACK_IRQ | - CS4231_RECORD_IRQ | - CS4231_TIMER_IRQ); - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - - chip->mode = mode; - mutex_unlock(&chip->open_mutex); - return 0; -} - -static void snd_wss_close(struct snd_wss *chip, unsigned int mode) -{ - unsigned long flags; - - mutex_lock(&chip->open_mutex); - chip->mode &= ~mode; - if (chip->mode & WSS_MODE_OPEN) { - mutex_unlock(&chip->open_mutex); - return; - } - /* disable IRQ */ - spin_lock_irqsave(&chip->reg_lock, flags); - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE; - snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); - - /* now disable record & playback */ - - if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) { - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_wss_out(chip, CS4231_IFACE_CTRL, - chip->image[CS4231_IFACE_CTRL]); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_down(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - } - - /* clear IRQ again */ - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - snd_wss_out(chip, CS4231_IRQ_STATUS, 0); - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ - spin_unlock_irqrestore(&chip->reg_lock, flags); - - chip->mode = 0; - mutex_unlock(&chip->open_mutex); -} - -/* - * timer open/close - */ - -static int snd_wss_timer_open(struct snd_timer *timer) -{ - struct snd_wss *chip = snd_timer_chip(timer); - snd_wss_open(chip, WSS_MODE_TIMER); - return 0; -} - -static int snd_wss_timer_close(struct snd_timer *timer) -{ - struct snd_wss *chip = snd_timer_chip(timer); - snd_wss_close(chip, WSS_MODE_TIMER); - return 0; -} - -static struct snd_timer_hardware snd_wss_timer_table = -{ - .flags = SNDRV_TIMER_HW_AUTO, - .resolution = 9945, - .ticks = 65535, - .open = snd_wss_timer_open, - .close = snd_wss_timer_close, - .c_resolution = snd_wss_timer_resolution, - .start = snd_wss_timer_start, - .stop = snd_wss_timer_stop, -}; - -/* - * ok.. exported functions.. - */ - -static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - unsigned char new_pdfr; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - new_pdfr = snd_wss_get_format(chip, params_format(hw_params), - params_channels(hw_params)) | - snd_wss_get_rate(params_rate(hw_params)); - chip->set_playback_format(chip, hw_params, new_pdfr); - return 0; -} - -static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_wss_playback_prepare(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - spin_lock_irqsave(&chip->reg_lock, flags); - chip->p_dma_size = size; - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO); - snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT); - count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1; - snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); - snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8)); - spin_unlock_irqrestore(&chip->reg_lock, flags); -#if 0 - snd_wss_debug(chip); -#endif - return 0; -} - -static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - unsigned char new_cdfr; - int err; - - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) - return err; - new_cdfr = snd_wss_get_format(chip, params_format(hw_params), - params_channels(hw_params)) | - snd_wss_get_rate(params_rate(hw_params)); - chip->set_capture_format(chip, hw_params, new_cdfr); - return 0; -} - -static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static int snd_wss_capture_prepare(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long flags; - unsigned int size = snd_pcm_lib_buffer_bytes(substream); - unsigned int count = snd_pcm_lib_period_bytes(substream); - - spin_lock_irqsave(&chip->reg_lock, flags); - chip->c_dma_size = size; - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); - if (chip->hardware & WSS_HW_AD1848_MASK) - count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], - count); - else - count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], - count); - count--; - if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { - snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); - snd_wss_out(chip, CS4231_PLY_UPR_CNT, - (unsigned char) (count >> 8)); - } else { - snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count); - snd_wss_out(chip, CS4231_REC_UPR_CNT, - (unsigned char) (count >> 8)); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -void snd_wss_overrange(struct snd_wss *chip) -{ - unsigned long flags; - unsigned char res; - - spin_lock_irqsave(&chip->reg_lock, flags); - res = snd_wss_in(chip, CS4231_TEST_INIT); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */ - chip->capture_substream->runtime->overrange++; -} -EXPORT_SYMBOL(snd_wss_overrange); - -irqreturn_t snd_wss_interrupt(int irq, void *dev_id) -{ - struct snd_wss *chip = dev_id; - unsigned char status; - - if (chip->hardware & WSS_HW_AD1848_MASK) - /* pretend it was the only possible irq for AD1848 */ - status = CS4231_PLAYBACK_IRQ; - else - status = snd_wss_in(chip, CS4231_IRQ_STATUS); - if (status & CS4231_TIMER_IRQ) { - if (chip->timer) - snd_timer_interrupt(chip->timer, chip->timer->sticks); - } - if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { - if (status & CS4231_PLAYBACK_IRQ) { - if (chip->mode & WSS_MODE_PLAY) { - if (chip->playback_substream) - snd_pcm_period_elapsed(chip->playback_substream); - } - if (chip->mode & WSS_MODE_RECORD) { - if (chip->capture_substream) { - snd_wss_overrange(chip); - snd_pcm_period_elapsed(chip->capture_substream); - } - } - } - } else { - if (status & CS4231_PLAYBACK_IRQ) { - if (chip->playback_substream) - snd_pcm_period_elapsed(chip->playback_substream); - } - if (status & CS4231_RECORD_IRQ) { - if (chip->capture_substream) { - snd_wss_overrange(chip); - snd_pcm_period_elapsed(chip->capture_substream); - } - } - } - - spin_lock(&chip->reg_lock); - status = ~CS4231_ALL_IRQS | ~status; - if (chip->hardware & WSS_HW_AD1848_MASK) - wss_outb(chip, CS4231P(STATUS), 0); - else - snd_wss_out(chip, CS4231_IRQ_STATUS, status); - spin_unlock(&chip->reg_lock); - return IRQ_HANDLED; -} -EXPORT_SYMBOL(snd_wss_interrupt); - -static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) - return 0; - ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - size_t ptr; - - if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) - return 0; - ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size); - return bytes_to_frames(substream->runtime, ptr); -} - -/* - - */ - -static int snd_ad1848_probe(struct snd_wss *chip) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - unsigned long flags; - unsigned char r; - unsigned short hardware = 0; - int err = 0; - int i; - - while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) { - if (time_after(jiffies, timeout)) - return -ENODEV; - cond_resched(); - } - spin_lock_irqsave(&chip->reg_lock, flags); - - /* set CS423x MODE 1 */ - snd_wss_dout(chip, CS4231_MISC_INFO, 0); - - snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */ - r = snd_wss_in(chip, CS4231_RIGHT_INPUT); - if (r != 0x45) { - /* RMGE always high on AD1847 */ - if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) { - err = -ENODEV; - goto out; - } - hardware = WSS_HW_AD1847; - } else { - snd_wss_dout(chip, CS4231_LEFT_INPUT, 0xaa); - r = snd_wss_in(chip, CS4231_LEFT_INPUT); - /* L/RMGE always low on AT2320 */ - if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) { - err = -ENODEV; - goto out; - } - } - - /* clear pending IRQ */ - wss_inb(chip, CS4231P(STATUS)); - wss_outb(chip, CS4231P(STATUS), 0); - mb(); - - if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT) - goto out; - - if (hardware) { - chip->hardware = hardware; - goto out; - } - - r = snd_wss_in(chip, CS4231_MISC_INFO); - - /* set CS423x MODE 2 */ - snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2); - for (i = 0; i < 16; i++) { - if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) { - /* we have more than 16 registers: check ID */ - if ((r & 0xf) != 0xa) - goto out_mode; - /* - * on CMI8330, CS4231_VERSION is volume control and - * can be set to 0 - */ - snd_wss_dout(chip, CS4231_VERSION, 0); - r = snd_wss_in(chip, CS4231_VERSION) & 0xe7; - if (!r) - chip->hardware = WSS_HW_CMI8330; - goto out_mode; - } - } - if (r & 0x80) - chip->hardware = WSS_HW_CS4248; - else - chip->hardware = WSS_HW_AD1848; -out_mode: - snd_wss_dout(chip, CS4231_MISC_INFO, 0); -out: - spin_unlock_irqrestore(&chip->reg_lock, flags); - return err; -} - -static int snd_wss_probe(struct snd_wss *chip) -{ - unsigned long flags; - int i, id, rev, regnum; - unsigned char *ptr; - unsigned int hw; - - id = snd_ad1848_probe(chip); - if (id < 0) - return id; - - hw = chip->hardware; - if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { - for (i = 0; i < 50; i++) { - mb(); - if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - msleep(2); - else { - spin_lock_irqsave(&chip->reg_lock, flags); - snd_wss_out(chip, CS4231_MISC_INFO, - CS4231_MODE2); - id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (id == 0x0a) - break; /* this is valid value */ - } - } - snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id); - if (id != 0x0a) - return -ENODEV; /* no valid device found */ - - rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7; - snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev); - if (rev == 0x80) { - unsigned char tmp = snd_wss_in(chip, 23); - snd_wss_out(chip, 23, ~tmp); - if (snd_wss_in(chip, 23) != tmp) - chip->hardware = WSS_HW_AD1845; - else - chip->hardware = WSS_HW_CS4231; - } else if (rev == 0xa0) { - chip->hardware = WSS_HW_CS4231A; - } else if (rev == 0xa2) { - chip->hardware = WSS_HW_CS4232; - } else if (rev == 0xb2) { - chip->hardware = WSS_HW_CS4232A; - } else if (rev == 0x83) { - chip->hardware = WSS_HW_CS4236; - } else if (rev == 0x03) { - chip->hardware = WSS_HW_CS4236B; - } else { - snd_printk(KERN_ERR - "unknown CS chip with version 0x%x\n", rev); - return -ENODEV; /* unknown CS4231 chip? */ - } - } - spin_lock_irqsave(&chip->reg_lock, flags); - wss_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */ - wss_outb(chip, CS4231P(STATUS), 0); - mb(); - spin_unlock_irqrestore(&chip->reg_lock, flags); - - if (!(chip->hardware & WSS_HW_AD1848_MASK)) - chip->image[CS4231_MISC_INFO] = CS4231_MODE2; - switch (chip->hardware) { - case WSS_HW_INTERWAVE: - chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3; - break; - case WSS_HW_CS4235: - case WSS_HW_CS4236B: - case WSS_HW_CS4237B: - case WSS_HW_CS4238B: - case WSS_HW_CS4239: - if (hw == WSS_HW_DETECT3) - chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3; - else - chip->hardware = WSS_HW_CS4236; - break; - } - - chip->image[CS4231_IFACE_CTRL] = - (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) | - (chip->single_dma ? CS4231_SINGLE_DMA : 0); - if (chip->hardware != WSS_HW_OPTI93X) { - chip->image[CS4231_ALT_FEATURE_1] = 0x80; - chip->image[CS4231_ALT_FEATURE_2] = - chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; - } - /* enable fine grained frequency selection */ - if (chip->hardware == WSS_HW_AD1845) - chip->image[AD1845_PWR_DOWN] = 8; - - ptr = (unsigned char *) &chip->image; - regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; - snd_wss_mce_down(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (i = 0; i < regnum; i++) /* ok.. fill all registers */ - snd_wss_out(chip, i, *ptr++); - spin_unlock_irqrestore(&chip->reg_lock, flags); - snd_wss_mce_up(chip); - snd_wss_mce_down(chip); - - mdelay(2); - - /* ok.. try check hardware version for CS4236+ chips */ - if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) { - if (chip->hardware == WSS_HW_CS4236B) { - rev = snd_cs4236_ext_in(chip, CS4236_VERSION); - snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff); - id = snd_cs4236_ext_in(chip, CS4236_VERSION); - snd_cs4236_ext_out(chip, CS4236_VERSION, rev); - snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id); - if ((id & 0x1f) == 0x1d) { /* CS4235 */ - chip->hardware = WSS_HW_CS4235; - switch (id >> 5) { - case 4: - case 5: - case 6: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4235 chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */ - switch (id >> 5) { - case 4: - case 5: - case 6: - case 7: - chip->hardware = WSS_HW_CS4236B; - break; - default: - snd_printk(KERN_WARNING - "unknown CS4236 chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x08) { /* CS4237B */ - chip->hardware = WSS_HW_CS4237B; - switch (id >> 5) { - case 4: - case 5: - case 6: - case 7: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4237B chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x09) { /* CS4238B */ - chip->hardware = WSS_HW_CS4238B; - switch (id >> 5) { - case 5: - case 6: - case 7: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4238B chip " - "(enhanced version = 0x%x)\n", - id); - } - } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ - chip->hardware = WSS_HW_CS4239; - switch (id >> 5) { - case 4: - case 5: - case 6: - break; - default: - snd_printk(KERN_WARNING - "unknown CS4239 chip " - "(enhanced version = 0x%x)\n", - id); - } - } else { - snd_printk(KERN_WARNING - "unknown CS4236/CS423xB chip " - "(enhanced version = 0x%x)\n", id); - } - } - } - return 0; /* all things are ok.. */ -} - -/* - - */ - -static struct snd_pcm_hardware snd_wss_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .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, -}; - -static struct snd_pcm_hardware snd_wss_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, - .rate_min = 5510, - .rate_max = 48000, - .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, -}; - -/* - - */ - -static int snd_wss_playback_open(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - runtime->hw = snd_wss_playback; - - /* hardware limitation of older chipsets */ - if (chip->hardware & WSS_HW_AD1848_MASK) - runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_S16_BE); - - /* hardware bug in InterWave chipset */ - if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3) - runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; - - /* hardware limitation of cheap chips */ - if (chip->hardware == WSS_HW_CS4235 || - chip->hardware == WSS_HW_CS4239) - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE; - - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); - - if (chip->claim_dma) { - if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0) - return err; - } - - err = snd_wss_open(chip, WSS_MODE_PLAY); - if (err < 0) { - if (chip->release_dma) - chip->release_dma(chip, chip->dma_private_data, chip->dma1); - snd_free_pages(runtime->dma_area, runtime->dma_bytes); - return err; - } - chip->playback_substream = substream; - snd_pcm_set_sync(substream); - chip->rate_constraint(runtime); - return 0; -} - -static int snd_wss_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - runtime->hw = snd_wss_capture; - - /* hardware limitation of older chipsets */ - if (chip->hardware & WSS_HW_AD1848_MASK) - runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_S16_BE); - - /* hardware limitation of cheap chips */ - if (chip->hardware == WSS_HW_CS4235 || - chip->hardware == WSS_HW_CS4239 || - chip->hardware == WSS_HW_OPTI93X) - runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE; - - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); - snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); - - if (chip->claim_dma) { - if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0) - return err; - } - - err = snd_wss_open(chip, WSS_MODE_RECORD); - if (err < 0) { - if (chip->release_dma) - chip->release_dma(chip, chip->dma_private_data, chip->dma2); - snd_free_pages(runtime->dma_area, runtime->dma_bytes); - return err; - } - chip->capture_substream = substream; - snd_pcm_set_sync(substream); - chip->rate_constraint(runtime); - return 0; -} - -static int snd_wss_playback_close(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - - chip->playback_substream = NULL; - snd_wss_close(chip, WSS_MODE_PLAY); - return 0; -} - -static int snd_wss_capture_close(struct snd_pcm_substream *substream) -{ - struct snd_wss *chip = snd_pcm_substream_chip(substream); - - chip->capture_substream = NULL; - snd_wss_close(chip, WSS_MODE_RECORD); - return 0; -} - -static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on) -{ - int tmp; - - if (!chip->thinkpad_flag) - return; - - outb(0x1c, AD1848_THINKPAD_CTL_PORT1); - tmp = inb(AD1848_THINKPAD_CTL_PORT2); - - if (on) - /* turn it on */ - tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT; - else - /* turn it off */ - tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT; - - outb(tmp, AD1848_THINKPAD_CTL_PORT2); -} - -#ifdef CONFIG_PM - -/* lowlevel suspend callback for CS4231 */ -static void snd_wss_suspend(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - - snd_pcm_suspend_all(chip->pcm); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) - chip->image[reg] = snd_wss_in(chip, reg); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (chip->thinkpad_flag) - snd_wss_thinkpad_twiddle(chip, 0); -} - -/* lowlevel resume callback for CS4231 */ -static void snd_wss_resume(struct snd_wss *chip) -{ - int reg; - unsigned long flags; - /* int timeout; */ - - if (chip->thinkpad_flag) - snd_wss_thinkpad_twiddle(chip, 1); - snd_wss_mce_up(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - for (reg = 0; reg < 32; reg++) { - switch (reg) { - case CS4231_VERSION: - break; - default: - snd_wss_out(chip, reg, chip->image[reg]); - break; - } - } - spin_unlock_irqrestore(&chip->reg_lock, flags); -#if 1 - snd_wss_mce_down(chip); -#else - /* The following is a workaround to avoid freeze after resume on TP600E. - This is the first half of copy of snd_wss_mce_down(), but doesn't - include rescheduling. -- iwai - */ - snd_wss_busy_wait(chip); - spin_lock_irqsave(&chip->reg_lock, flags); - chip->mce_bit &= ~CS4231_MCE; - timeout = wss_inb(chip, CS4231P(REGSEL)); - wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (timeout == 0x80) - snd_printk(KERN_ERR "down [0x%lx]: serious init problem " - "- codec still busy\n", chip->port); - if ((timeout & CS4231_MCE) == 0 || - !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { - return; - } - snd_wss_busy_wait(chip); -#endif -} -#endif /* CONFIG_PM */ - -static int snd_wss_free(struct snd_wss *chip) -{ - release_and_free_resource(chip->res_port); - release_and_free_resource(chip->res_cport); - if (chip->irq >= 0) { - disable_irq(chip->irq); - if (!(chip->hwshare & WSS_HWSHARE_IRQ)) - free_irq(chip->irq, (void *) chip); - } - if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) { - snd_dma_disable(chip->dma1); - free_dma(chip->dma1); - } - if (!(chip->hwshare & WSS_HWSHARE_DMA2) && - chip->dma2 >= 0 && chip->dma2 != chip->dma1) { - snd_dma_disable(chip->dma2); - free_dma(chip->dma2); - } - if (chip->timer) - snd_device_free(chip->card, chip->timer); - kfree(chip); - return 0; -} - -static int snd_wss_dev_free(struct snd_device *device) -{ - struct snd_wss *chip = device->device_data; - return snd_wss_free(chip); -} - -const char *snd_wss_chip_id(struct snd_wss *chip) -{ - switch (chip->hardware) { - case WSS_HW_CS4231: - return "CS4231"; - case WSS_HW_CS4231A: - return "CS4231A"; - case WSS_HW_CS4232: - return "CS4232"; - case WSS_HW_CS4232A: - return "CS4232A"; - case WSS_HW_CS4235: - return "CS4235"; - case WSS_HW_CS4236: - return "CS4236"; - case WSS_HW_CS4236B: - return "CS4236B"; - case WSS_HW_CS4237B: - return "CS4237B"; - case WSS_HW_CS4238B: - return "CS4238B"; - case WSS_HW_CS4239: - return "CS4239"; - case WSS_HW_INTERWAVE: - return "AMD InterWave"; - case WSS_HW_OPL3SA2: - return chip->card->shortname; - case WSS_HW_AD1845: - return "AD1845"; - case WSS_HW_OPTI93X: - return "OPTi 93x"; - case WSS_HW_AD1847: - return "AD1847"; - case WSS_HW_AD1848: - return "AD1848"; - case WSS_HW_CS4248: - return "CS4248"; - case WSS_HW_CMI8330: - return "CMI8330/C3D"; - default: - return "???"; - } -} -EXPORT_SYMBOL(snd_wss_chip_id); - -static int snd_wss_new(struct snd_card *card, - unsigned short hardware, - unsigned short hwshare, - struct snd_wss **rchip) -{ - struct snd_wss *chip; - - *rchip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - chip->hardware = hardware; - chip->hwshare = hwshare; - - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->mce_mutex); - mutex_init(&chip->open_mutex); - chip->card = card; - chip->rate_constraint = snd_wss_xrate; - chip->set_playback_format = snd_wss_playback_format; - chip->set_capture_format = snd_wss_capture_format; - if (chip->hardware == WSS_HW_OPTI93X) - memcpy(&chip->image, &snd_opti93x_original_image, - sizeof(snd_opti93x_original_image)); - else - memcpy(&chip->image, &snd_wss_original_image, - sizeof(snd_wss_original_image)); - if (chip->hardware & WSS_HW_AD1848_MASK) { - chip->image[CS4231_PIN_CTRL] = 0; - chip->image[CS4231_TEST_INIT] = 0; - } - - *rchip = chip; - return 0; -} - -int snd_wss_create(struct snd_card *card, - unsigned long port, - unsigned long cport, - int irq, int dma1, int dma2, - unsigned short hardware, - unsigned short hwshare, - struct snd_wss **rchip) -{ - static struct snd_device_ops ops = { - .dev_free = snd_wss_dev_free, - }; - struct snd_wss *chip; - int err; - - err = snd_wss_new(card, hardware, hwshare, &chip); - if (err < 0) - return err; - - chip->irq = -1; - chip->dma1 = -1; - chip->dma2 = -1; - - chip->res_port = request_region(port, 4, "WSS"); - if (!chip->res_port) { - snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port); - snd_wss_free(chip); - return -EBUSY; - } - chip->port = port; - if ((long)cport >= 0) { - chip->res_cport = request_region(cport, 8, "CS4232 Control"); - if (!chip->res_cport) { - snd_printk(KERN_ERR - "wss: can't grab control port 0x%lx\n", cport); - snd_wss_free(chip); - return -ENODEV; - } - } - chip->cport = cport; - if (!(hwshare & WSS_HWSHARE_IRQ)) - if (request_irq(irq, snd_wss_interrupt, 0, - "WSS", (void *) chip)) { - snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq); - snd_wss_free(chip); - return -EBUSY; - } - chip->irq = irq; - if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) { - snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1); - snd_wss_free(chip); - return -EBUSY; - } - chip->dma1 = dma1; - if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && - dma2 >= 0 && request_dma(dma2, "WSS - 2")) { - snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2); - snd_wss_free(chip); - return -EBUSY; - } - if (dma1 == dma2 || dma2 < 0) { - chip->single_dma = 1; - chip->dma2 = chip->dma1; - } else - chip->dma2 = dma2; - - if (hardware == WSS_HW_THINKPAD) { - chip->thinkpad_flag = 1; - chip->hardware = WSS_HW_DETECT; /* reset */ - snd_wss_thinkpad_twiddle(chip, 1); - } - - /* global setup */ - if (snd_wss_probe(chip) < 0) { - snd_wss_free(chip); - return -ENODEV; - } - snd_wss_init(chip); - -#if 0 - if (chip->hardware & WSS_HW_CS4232_MASK) { - if (chip->res_cport == NULL) - snd_printk(KERN_ERR "CS4232 control port features are " - "not accessible\n"); - } -#endif - - /* Register device */ - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); - if (err < 0) { - snd_wss_free(chip); - return err; - } - -#ifdef CONFIG_PM - /* Power Management */ - chip->suspend = snd_wss_suspend; - chip->resume = snd_wss_resume; -#endif - - *rchip = chip; - return 0; -} -EXPORT_SYMBOL(snd_wss_create); - -static struct snd_pcm_ops snd_wss_playback_ops = { - .open = snd_wss_playback_open, - .close = snd_wss_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_wss_playback_hw_params, - .hw_free = snd_wss_playback_hw_free, - .prepare = snd_wss_playback_prepare, - .trigger = snd_wss_trigger, - .pointer = snd_wss_playback_pointer, -}; - -static struct snd_pcm_ops snd_wss_capture_ops = { - .open = snd_wss_capture_open, - .close = snd_wss_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_wss_capture_hw_params, - .hw_free = snd_wss_capture_hw_free, - .prepare = snd_wss_capture_prepare, - .trigger = snd_wss_trigger, - .pointer = snd_wss_capture_pointer, -}; - -int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm) -{ - struct snd_pcm *pcm; - int err; - - err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm); - if (err < 0) - return err; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); - - /* global setup */ - pcm->private_data = chip; - pcm->info_flags = 0; - if (chip->single_dma) - pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX; - if (chip->hardware != WSS_HW_INTERWAVE) - pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX; - strcpy(pcm->name, snd_wss_chip_id(chip)); - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_isa_data(), - 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024); - - chip->pcm = pcm; - if (rpcm) - *rpcm = pcm; - return 0; -} -EXPORT_SYMBOL(snd_wss_pcm); - -static void snd_wss_timer_free(struct snd_timer *timer) -{ - struct snd_wss *chip = timer->private_data; - chip->timer = NULL; -} - -int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer) -{ - struct snd_timer *timer; - struct snd_timer_id tid; - int err; - - /* Timer initialization */ - tid.dev_class = SNDRV_TIMER_CLASS_CARD; - tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; - tid.device = device; - tid.subdevice = 0; - if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0) - return err; - strcpy(timer->name, snd_wss_chip_id(chip)); - timer->private_data = chip; - timer->private_free = snd_wss_timer_free; - timer->hw = snd_wss_timer_table; - chip->timer = timer; - if (rtimer) - *rtimer = timer; - return 0; -} -EXPORT_SYMBOL(snd_wss_timer); - -/* - * MIXER part - */ - -static int snd_wss_info_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = { - "Line", "Aux", "Mic", "Mix" - }; - static char *opl3sa_texts[4] = { - "Line", "CD", "Mic", "Mix" - }; - static char *gusmax_texts[4] = { - "Line", "Synth", "Mic", "Mix" - }; - char **ptexts = texts; - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - - if (snd_BUG_ON(!chip->card)) - return -EINVAL; - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - if (!strcmp(chip->card->driver, "GUS MAX")) - ptexts = gusmax_texts; - switch (chip->hardware) { - case WSS_HW_INTERWAVE: - ptexts = gusmax_texts; - break; - case WSS_HW_OPTI93X: - case WSS_HW_OPL3SA2: - ptexts = opl3sa_texts; - break; - } - strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_wss_get_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; - ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6; - spin_unlock_irqrestore(&chip->reg_lock, flags); - return 0; -} - -static int snd_wss_put_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - unsigned short left, right; - int change; - - if (ucontrol->value.enumerated.item[0] > 3 || - ucontrol->value.enumerated.item[1] > 3) - return -EINVAL; - left = ucontrol->value.enumerated.item[0] << 6; - right = ucontrol->value.enumerated.item[1] << 6; - spin_lock_irqsave(&chip->reg_lock, flags); - left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; - right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; - change = left != chip->image[CS4231_LEFT_INPUT] || - right != chip->image[CS4231_RIGHT_INPUT]; - snd_wss_out(chip, CS4231_LEFT_INPUT, left); - snd_wss_out(chip, CS4231_RIGHT_INPUT, right); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} - -int snd_wss_info_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 16) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} -EXPORT_SYMBOL(snd_wss_info_single); - -int snd_wss_get_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - return 0; -} -EXPORT_SYMBOL(snd_wss_get_single); - -int snd_wss_put_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; - int mask = (kcontrol->private_value >> 16) & 0xff; - int invert = (kcontrol->private_value >> 24) & 0xff; - int change; - unsigned short val; - - val = (ucontrol->value.integer.value[0] & mask); - if (invert) - val = mask - val; - val <<= shift; - spin_lock_irqsave(&chip->reg_lock, flags); - val = (chip->image[reg] & ~(mask << shift)) | val; - change = val != chip->image[reg]; - snd_wss_out(chip, reg, val); - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} -EXPORT_SYMBOL(snd_wss_put_single); - -int snd_wss_info_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = (kcontrol->private_value >> 24) & 0xff; - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} -EXPORT_SYMBOL(snd_wss_info_double); - -int snd_wss_get_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - - spin_lock_irqsave(&chip->reg_lock, flags); - ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; - spin_unlock_irqrestore(&chip->reg_lock, flags); - if (invert) { - ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; - } - return 0; -} -EXPORT_SYMBOL(snd_wss_get_double); - -int snd_wss_put_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_wss *chip = snd_kcontrol_chip(kcontrol); - unsigned long flags; - int left_reg = kcontrol->private_value & 0xff; - int right_reg = (kcontrol->private_value >> 8) & 0xff; - int shift_left = (kcontrol->private_value >> 16) & 0x07; - int shift_right = (kcontrol->private_value >> 19) & 0x07; - int mask = (kcontrol->private_value >> 24) & 0xff; - int invert = (kcontrol->private_value >> 22) & 1; - int change; - unsigned short val1, val2; - - val1 = ucontrol->value.integer.value[0] & mask; - val2 = ucontrol->value.integer.value[1] & mask; - if (invert) { - val1 = mask - val1; - val2 = mask - val2; - } - val1 <<= shift_left; - val2 <<= shift_right; - spin_lock_irqsave(&chip->reg_lock, flags); - if (left_reg != right_reg) { - val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; - val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || - val2 != chip->image[right_reg]; - snd_wss_out(chip, left_reg, val1); - snd_wss_out(chip, right_reg, val2); - } else { - mask = (mask << shift_left) | (mask << shift_right); - val1 = (chip->image[left_reg] & ~mask) | val1 | val2; - change = val1 != chip->image[left_reg]; - snd_wss_out(chip, left_reg, val1); - } - spin_unlock_irqrestore(&chip->reg_lock, flags); - return change; -} -EXPORT_SYMBOL(snd_wss_put_double); - -static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); -static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); - -static struct snd_kcontrol_new snd_wss_controls[] = { -WSS_DOUBLE("PCM Playback Switch", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("PCM Playback Volume", 0, - CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), -WSS_DOUBLE("Aux Playback Switch", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Aux Playback Volume", 0, - CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE("Aux Playback Switch", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Aux Playback Volume", 1, - CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, - 0, 0, 15, 0, db_scale_rec_gain), -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_wss_info_mux, - .get = snd_wss_get_mux, - .put = snd_wss_put_mux, -}, -WSS_DOUBLE("Mic Boost (+20dB)", 0, - CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), -WSS_SINGLE("Loopback Capture Switch", 0, - CS4231_LOOPBACK, 0, 1, 0), -WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1, - db_scale_6bit), -WSS_DOUBLE("Line Playback Switch", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -WSS_DOUBLE_TLV("Line Playback Volume", 0, - CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1, - db_scale_5bit_12db_max), -WSS_SINGLE("Beep Playback Switch", 0, - CS4231_MONO_CTRL, 7, 1, 1), -WSS_SINGLE_TLV("Beep Playback Volume", 0, - CS4231_MONO_CTRL, 0, 15, 1, - db_scale_4bit), -WSS_SINGLE("Mono Output Playback Switch", 0, - CS4231_MONO_CTRL, 6, 1, 1), -WSS_SINGLE("Beep Bypass Playback Switch", 0, - CS4231_MONO_CTRL, 5, 1, 0), -}; - -int snd_wss_mixer(struct snd_wss *chip) -{ - struct snd_card *card; - unsigned int idx; - int err; - int count = ARRAY_SIZE(snd_wss_controls); - - if (snd_BUG_ON(!chip || !chip->pcm)) - return -EINVAL; - - card = chip->card; - - strcpy(card->mixername, chip->pcm->name); - - /* Use only the first 11 entries on AD1848 */ - if (chip->hardware & WSS_HW_AD1848_MASK) - count = 11; - /* There is no loopback on OPTI93X */ - else if (chip->hardware == WSS_HW_OPTI93X) - count = 9; - - for (idx = 0; idx < count; idx++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_wss_controls[idx], - chip)); - if (err < 0) - return err; - } - return 0; -} -EXPORT_SYMBOL(snd_wss_mixer); - -const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction) -{ - return direction == SNDRV_PCM_STREAM_PLAYBACK ? - &snd_wss_playback_ops : &snd_wss_capture_ops; -} -EXPORT_SYMBOL(snd_wss_get_pcm_ops); - -/* - * INIT part - */ - -static int __init alsa_wss_init(void) -{ - return 0; -} - -static void __exit alsa_wss_exit(void) -{ -} - -module_init(alsa_wss_init); -module_exit(alsa_wss_exit); |