📄 interwave.c
字号:
/* * Driver for AMD InterWave soundcard * Copyright (c) by Jaroslav Kysela <perex@suse.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 <sound/driver.h>#include <asm/dma.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/slab.h>#ifndef LINUX_ISAPNP_H#include <linux/isapnp.h>#define isapnp_card pci_bus#define isapnp_dev pci_dev#endif#include <sound/core.h>#include <sound/gus.h>#include <sound/cs4231.h>#ifdef SNDRV_STB#include <sound/tea6330t.h>#endif#define SNDRV_LEGACY_AUTO_PROBE#define SNDRV_LEGACY_FIND_FREE_IRQ#define SNDRV_LEGACY_FIND_FREE_DMA#define SNDRV_GET_ID#include <sound/initval.h>EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");MODULE_CLASSES("{sound}");MODULE_LICENSE("GPL");#ifndef SNDRV_STBMODULE_DESCRIPTION("AMD InterWave");MODULE_DEVICES("{{Gravis,UltraSound Plug & Play}," "{STB,SoundRage32}," "{MED,MED3210}," "{Dynasonix,Dynasonix Pro}," "{Panasonic,PCA761AW}}");#elseMODULE_DESCRIPTION("AMD InterWave STB with TEA6330T");MODULE_DEVICES("{{AMD,InterWave STB with TEA6330T}}");#endifstatic int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */#ifdef __ISAPNP__static int snd_isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};#endifstatic long snd_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x210,0x220,0x230,0x240,0x250,0x260 */#ifdef SNDRV_STBstatic long snd_port_tc[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x350,0x360,0x370,0x380 */#endifstatic int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */static int snd_dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */static int snd_dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */static int snd_joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */static int snd_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};static int snd_pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};static int snd_effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_index, "Index value for InterWave soundcard.");MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");MODULE_PARM_DESC(snd_id, "ID string for InterWave soundcard.");MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_enable, "Enable InterWave soundcard.");MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);MODULE_PARM(snd_isapnp, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_isapnp, "ISA PnP detection for specified soundcard.");MODULE_PARM_SYNTAX(snd_isapnp, SNDRV_ISAPNP_DESC);MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");MODULE_PARM_DESC(snd_port, "Port # for InterWave driver.");MODULE_PARM_SYNTAX(snd_port, SNDRV_ENABLED ",allows:{{0x210,0x260,0x10}},dialog:list");#ifdef SNDRV_STBMODULE_PARM(snd_port_tc, "1-" __MODULE_STRING(SNDRV_CARDS) "l");MODULE_PARM_DESC(snd_port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver.");MODULE_PARM_SYNTAX(snd_port_tc, SNDRV_ENABLED ",allows:{{0x350,0x380,0x10}},dialog:list");#endifMODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_irq, "IRQ # for InterWave driver.");MODULE_PARM_SYNTAX(snd_irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");MODULE_PARM(snd_dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_dma1, "DMA1 # for InterWave driver.");MODULE_PARM_SYNTAX(snd_dma1, SNDRV_DMA_DESC);MODULE_PARM(snd_dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_dma2, "DMA2 # for InterWave driver.");MODULE_PARM_SYNTAX(snd_dma2, SNDRV_DMA_DESC);MODULE_PARM(snd_joystick_dac, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver.");MODULE_PARM_SYNTAX(snd_joystic_dac, SNDRV_ENABLED ",allows:{{0,31}}");MODULE_PARM(snd_midi, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_midi, "MIDI UART enable for InterWave driver.");MODULE_PARM_SYNTAX(snd_midi, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);MODULE_PARM(snd_pcm_channels, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_pcm_channels, "Reserved PCM channels for InterWave driver.");MODULE_PARM_SYNTAX(snd_pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");MODULE_PARM(snd_effect, "1-" __MODULE_STRING(SNDRV_CARDS) "i");MODULE_PARM_DESC(snd_effect, "Effects enable for InterWave driver.");MODULE_PARM_SYNTAX(snd_effect, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);struct snd_interwave { int irq; snd_card_t *card; snd_gus_card_t *gus; cs4231_t *cs4231;#ifdef SNDRV_STB struct resource *i2c_res;#endif unsigned short gus_status_reg; unsigned short pcm_status_reg;#ifdef __ISAPNP__ struct isapnp_dev *dev;#ifdef SNDRV_STB struct isapnp_dev *devtc;#endif#endif};static snd_card_t *snd_interwave_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;#ifdef __ISAPNP__static struct isapnp_card *snd_interwave_isapnp_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;static const struct isapnp_card_id *snd_interwave_isapnp_id[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;#define ISAPNP_INTERWAVE(_va, _vb, _vc, _device, _audio) \ { \ ISAPNP_CARD_ID(_va, _vb, _vc, _device), \ devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio), } \ }#define ISAPNP_INTERWAVE_STB(_va, _vb, _vc, _device, _audio, _tone) \ { \ ISAPNP_CARD_ID(_va, _vb, _vc, _device), \ devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio), \ ISAPNP_DEVICE_ID(_va, _vb, _vc, _tone), } \ }static struct isapnp_card_id snd_interwave_pnpids[] __devinitdata = {#ifndef SNDRV_STB /* Gravis UltraSound Plug & Play */ ISAPNP_INTERWAVE('G','R','V',0x0001,0x0000), /* STB SoundRage32 */ ISAPNP_INTERWAVE('S','T','B',0x011a,0x0010), /* MED3210 */ ISAPNP_INTERWAVE('D','X','P',0x3201,0x0010), /* Dynasonic Pro */ /* This device also have CDC1117:DynaSonix Pro Audio Effects Processor */ ISAPNP_INTERWAVE('C','D','C',0x1111,0x1112), /* Panasonic PCA761AW Audio Card */ ISAPNP_INTERWAVE('A','D','V',0x55ff,0x0010),#else /* InterWave STB with TEA6330T */ ISAPNP_INTERWAVE_STB('A','D','V',0x550a,0x0010,0x0015),#endif { ISAPNP_CARD_END, }};ISAPNP_CARD_TABLE(snd_interwave_pnpids);#endif /* __ISAPNP__ */#ifdef SNDRV_STBstatic void snd_interwave_i2c_setlines(snd_i2c_bus_t *bus, int ctrl, int data){ unsigned long port = bus->private_value;#if 0 printk("i2c_setlines - 0x%lx <- %i,%i\n", port, ctrl, data);#endif outb((data << 1) | ctrl, port); udelay(10);}static int snd_interwave_i2c_getclockline(snd_i2c_bus_t *bus){ unsigned long port = bus->private_value; unsigned char res; res = inb(port) & 1;#if 0 printk("i2c_getclockline - 0x%lx -> %i\n", port, res);#endif return res;}static int snd_interwave_i2c_getdataline(snd_i2c_bus_t *bus, int ack){ unsigned long port = bus->private_value; unsigned char res; if (ack) udelay(10); res = (inb(port) & 2) >> 1;#if 0 printk("i2c_getdataline - 0x%lx -> %i\n", port, res);#endif return res;}static snd_i2c_bit_ops_t snd_interwave_i2c_bit_ops = { setlines: snd_interwave_i2c_setlines, getclock: snd_interwave_i2c_getclockline, getdata: snd_interwave_i2c_getdataline,};static int __init snd_interwave_detect_stb(struct snd_interwave *iwcard, snd_gus_card_t * gus, int dev, snd_i2c_bus_t **rbus){ unsigned long port; snd_i2c_bus_t *bus; snd_card_t *card = iwcard->card; char name[32]; int err; *rbus = NULL; port = snd_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; } if (port > 0x380) return -ENODEV; } else { if ((iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)")) != NULL) 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;}#endifstatic int __init snd_interwave_detect(struct snd_interwave *iwcard, snd_gus_card_t * gus, int dev#ifdef SNDRV_STB , snd_i2c_bus_t **rbus#endif ){ unsigned long flags; unsigned char rev1, rev2; snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */#ifdef CONFIG_SND_DEBUG_DETECT { int d; if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { snd_printk("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } }#else if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 0) return -ENODEV;#endif udelay(160); snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ udelay(160);#ifdef CONFIG_SND_DEBUG_DETECT { int d; if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { snd_printk("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } }#else if ((snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET) & 0x07) != 1) return -ENODEV;#endif 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 void snd_interwave_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct snd_interwave *iwcard = (struct snd_interwave *) dev_id; int loop, max = 5; do { loop = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -