📄 sb16.c
字号:
/* * Driver for SoundBlaster 16/AWE32/AWE64 soundcards * 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 * */#include <sound/driver.h>#include <asm/dma.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/pnp.h>#include <linux/moduleparam.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_AUTO_PROBE#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: "#endifMODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");MODULE_LICENSE("GPL");#ifndef SNDRV_SBAWEMODULE_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}}");#elseMODULE_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#endifstatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */#ifdef CONFIG_PNPstatic int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};#endifstatic 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_EMU8000static long awe_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;#endifstatic 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_CSPstatic int csp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};#endif#ifdef SNDRV_SBAWE_EMU8000static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};#endifmodule_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_PNPmodule_param_array(isapnp, bool, NULL, 0444);MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");#endifmodule_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_EMU8000module_param_array(awe_port, long, NULL, 0444);MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver.");#endifmodule_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_CSPmodule_param_array(csp, int, NULL, 0444);MODULE_PARM_DESC(csp, "ASP/CSP chip support.");#endif#ifdef SNDRV_SBAWE_EMU8000module_param_array(seq_ports, int, NULL, 0444);MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");#endifstruct snd_card_sb16 { struct resource *fm_res; /* used to block FM i/o region for legacy cards */#ifdef CONFIG_PNP int dev_no; struct pnp_dev *dev;#ifdef SNDRV_SBAWE_EMU8000 struct pnp_dev *devwt;#endif#endif};static snd_card_t *snd_sb16_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;#ifdef CONFIG_PNPstatic 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" } } },#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 */ /* Sound Blaster 16 PnP (Virtual PC 2004)*/ { .id = "tBA03b0", .devs = { { "PNPb003" } } }, { .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_PNPstatic 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; struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); int err; if (!cfg) return -ENOMEM; acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); if (acard->dev == NULL) { kfree(cfg); 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; pnp_init_resource_table(cfg); /* override resources */ if (port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->port_resource[0], port[dev], 16); if (mpu_port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->port_resource[1], mpu_port[dev], 2); if (fm_port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->port_resource[2], fm_port[dev], 4); if (dma8[dev] != SNDRV_AUTO_DMA) pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1); if (dma16[dev] != SNDRV_AUTO_DMA) pnp_resource_change(&cfg->dma_resource[1], dma16[dev], 1); if (irq[dev] != SNDRV_AUTO_IRQ) pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); if (pnp_manual_config_dev(pdev, cfg, 0) < 0) snd_printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n"); err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); kfree(cfg); 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) { pnp_init_resource_table(cfg); /* override resources */ if (awe_port[dev] != SNDRV_AUTO_PORT) { pnp_resource_change(&cfg->port_resource[0], awe_port[dev], 4); pnp_resource_change(&cfg->port_resource[1], awe_port[dev] + 0x400, 4); pnp_resource_change(&cfg->port_resource[2], awe_port[dev] + 0x800, 4); } if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0) snd_printk(KERN_ERR PFX "WaveTable the requested resources are invalid, using auto config\n"); 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%lx\n", 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -