📄 ymf_sb.c
字号:
/* Legacy audio driver for YMF724, 740, 744, 754 series. Copyright 2000 Daisuke Nagano <breeze.nagano@nifty.ne.jp> Based on the VIA 82Cxxx driver by Jeff Garzik <jgarzik@pobox.com> And ported to 2.3.x by Jeff Garzik too :) My it is a small world. Distribued under the GNU PUBLIC LICENSE (GPL) Version 2. See the "COPYING" file distributed with kernel source tree for more info. ------------------------------------------------------------------------- It only supports SBPro compatible function of YMF7xx series s.t. * 22.05kHz, 8-bit and stereo sample * OPL3-compatible FM synthesizer * MPU-401 compatible "external" MIDI interface ------------------------------------------------------------------------- Revision history Tue May 14 19:00:00 2000 0.0.1 * initial release Tue May 16 19:29:29 2000 0.0.2 * add a little delays for reset devices. * fixed addressing bug. Sun May 21 15:14:37 2000 0.0.3 * Add 'master_vol' module parameter to change 'PCM out Vol' of AC'97. * remove native UART401 support. External MIDI port should be supported by sb_midi driver. * add support for SPDIF OUT. Module parameter 'spdif_out' is now available. Wed May 31 00:13:57 2000 0.0.4 * remove entries in Hwmcode.h. Now YMF744 / YMF754 sets instructions in 724hwmcode.h. * fixed wrong legacy_io setting on YMF744/YMF754 . Thu Sep 21 05:32:51 BRT 2000 0.0.5 * got rid of attach_uart401 and attach_sbmpu Arnaldo Carvalho de Melo <acme@conectiva.com.br> */#include <linux/module.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ac97_codec.h>#include <asm/io.h>#include "sound_config.h"#include "sb.h"#include "724hwmcode.h"#undef YMF_DEBUG#define SUPPORT_UART401_MIDI 1/* ---------------------------------------------------------------------- */#ifndef PCI_VENDOR_ID_YAMAHA#define PCI_VENDOR_ID_YAMAHA 0x1073#endif#ifndef PCI_DEVICE_ID_YMF724#define PCI_DEVICE_ID_YMF724 0x0004#endif#ifndef PCI_DEVICE_ID_YMF740#define PCI_DEVICE_ID_YMF740 0x000A#endif#ifndef PCI_DEVICE_ID_YMF740C#define PCI_DEVICE_ID_YMF740C 0x000C#endif#ifndef PCI_DEVICE_ID_YMF724F#define PCI_DEVICE_ID_YMF724F 0x000D#endif#ifndef PCI_DEVICE_ID_YMF744#define PCI_DEVICE_ID_YMF744 0x0010#endif#ifndef PCI_DEVICE_ID_YMF754#define PCI_DEVICE_ID_YMF754 0x0012#endif/* ---------------------------------------------------------------------- */#define YMFSB_RESET_DELAY 5#define YMFSB_REGSIZE 0x8000#define YMFSB_AC97TIMEOUT 2000#define YMFSB_WORKBITTIMEOUT 250000#define YMFSB_DSPLENGTH 0x0080#define YMFSB_CTRLLENGTH 0x3000#define YMFSB_PCIR_VENDORID 0x00#define YMFSB_PCIR_DEVICEID 0x02#define YMFSB_PCIR_CMD 0x04#define YMFSB_PCIR_REVISIONID 0x08#define YMFSB_PCIR_BASEADDR 0x10#define YMFSB_PCIR_IRQ 0x3c#define YMFSB_PCIR_LEGCTRL 0x40#define YMFSB_PCIR_ELEGCTRL 0x42#define YMFSB_PCIR_DSXGCTRL 0x48#define YMFSB_PCIR_OPLADR 0x60#define YMFSB_PCIR_SBADR 0x62#define YMFSB_PCIR_MPUADR 0x64#define YMFSB_INTFLAG 0x0004#define YMFSB_ACTIVITY 0x0006#define YMFSB_GLOBALCTRL 0x0008#define YMFSB_ZVCTRL 0x000A#define YMFSB_TIMERCTRL 0x0010#define YMFSB_TIMERCOUNT 0x0012#define YMFSB_SPDIFOUTCTRL 0x0018#define YMFSB_SPDIFOUTSTATUS 0x001C#define YMFSB_EEPROMCTRL 0x0020#define YMFSB_SPDIFINCTRL 0x0034#define YMFSB_SPDIFINSTATUS 0x0038#define YMFSB_DSPPROGRAMDL 0x0048#define YMFSB_DLCNTRL 0x004C#define YMFSB_GPIOININTFLAG 0x0050#define YMFSB_GPIOININTENABLE 0x0052#define YMFSB_GPIOINSTATUS 0x0054#define YMFSB_GPIOOUTCTRL 0x0056#define YMFSB_GPIOFUNCENABLE 0x0058#define YMFSB_GPIOTYPECONFIG 0x005A#define YMFSB_AC97CMDDATA 0x0060#define YMFSB_AC97CMDADR 0x0062#define YMFSB_PRISTATUSDATA 0x0064#define YMFSB_PRISTATUSADR 0x0066#define YMFSB_SECSTATUSDATA 0x0068#define YMFSB_SECSTATUSADR 0x006A#define YMFSB_SECCONFIG 0x0070#define YMFSB_LEGACYOUTVOL 0x0080#define YMFSB_LEGACYOUTVOLL 0x0080#define YMFSB_LEGACYOUTVOLR 0x0082#define YMFSB_NATIVEDACOUTVOL 0x0084#define YMFSB_NATIVEDACOUTVOLL 0x0084#define YMFSB_NATIVEDACOUTVOLR 0x0086#define YMFSB_SPDIFOUTVOL 0x0088#define YMFSB_SPDIFOUTVOLL 0x0088#define YMFSB_SPDIFOUTVOLR 0x008A#define YMFSB_AC3OUTVOL 0x008C#define YMFSB_AC3OUTVOLL 0x008C#define YMFSB_AC3OUTVOLR 0x008E#define YMFSB_PRIADCOUTVOL 0x0090#define YMFSB_PRIADCOUTVOLL 0x0090#define YMFSB_PRIADCOUTVOLR 0x0092#define YMFSB_LEGACYLOOPVOL 0x0094#define YMFSB_LEGACYLOOPVOLL 0x0094#define YMFSB_LEGACYLOOPVOLR 0x0096#define YMFSB_NATIVEDACLOOPVOL 0x0098#define YMFSB_NATIVEDACLOOPVOLL 0x0098#define YMFSB_NATIVEDACLOOPVOLR 0x009A#define YMFSB_SPDIFLOOPVOL 0x009C#define YMFSB_SPDIFLOOPVOLL 0x009E#define YMFSB_SPDIFLOOPVOLR 0x009E#define YMFSB_AC3LOOPVOL 0x00A0#define YMFSB_AC3LOOPVOLL 0x00A0#define YMFSB_AC3LOOPVOLR 0x00A2#define YMFSB_PRIADCLOOPVOL 0x00A4#define YMFSB_PRIADCLOOPVOLL 0x00A4#define YMFSB_PRIADCLOOPVOLR 0x00A6#define YMFSB_NATIVEADCINVOL 0x00A8#define YMFSB_NATIVEADCINVOLL 0x00A8#define YMFSB_NATIVEADCINVOLR 0x00AA#define YMFSB_NATIVEDACINVOL 0x00AC#define YMFSB_NATIVEDACINVOLL 0x00AC#define YMFSB_NATIVEDACINVOLR 0x00AE#define YMFSB_BUF441OUTVOL 0x00B0#define YMFSB_BUF441OUTVOLL 0x00B0#define YMFSB_BUF441OUTVOLR 0x00B2#define YMFSB_BUF441LOOPVOL 0x00B4#define YMFSB_BUF441LOOPVOLL 0x00B4#define YMFSB_BUF441LOOPVOLR 0x00B6#define YMFSB_SPDIFOUTVOL2 0x00B8#define YMFSB_SPDIFOUTVOL2L 0x00B8#define YMFSB_SPDIFOUTVOL2R 0x00BA#define YMFSB_SPDIFLOOPVOL2 0x00BC#define YMFSB_SPDIFLOOPVOL2L 0x00BC#define YMFSB_SPDIFLOOPVOL2R 0x00BE#define YMFSB_ADCSLOTSR 0x00C0#define YMFSB_RECSLOTSR 0x00C4#define YMFSB_ADCFORMAT 0x00C8#define YMFSB_RECFORMAT 0x00CC#define YMFSB_P44SLOTSR 0x00D0#define YMFSB_STATUS 0x0100#define YMFSB_CTRLSELECT 0x0104#define YMFSB_MODE 0x0108#define YMFSB_SAMPLECOUNT 0x010C#define YMFSB_NUMOFSAMPLES 0x0110#define YMFSB_CONFIG 0x0114#define YMFSB_PLAYCTRLSIZE 0x0140#define YMFSB_RECCTRLSIZE 0x0144#define YMFSB_EFFCTRLSIZE 0x0148#define YMFSB_WORKSIZE 0x014C#define YMFSB_MAPOFREC 0x0150#define YMFSB_MAPOFEFFECT 0x0154#define YMFSB_PLAYCTRLBASE 0x0158#define YMFSB_RECCTRLBASE 0x015C#define YMFSB_EFFCTRLBASE 0x0160#define YMFSB_WORKBASE 0x0164#define YMFSB_DSPINSTRAM 0x1000#define YMFSB_CTRLINSTRAM 0x4000/* ---------------------------------------------------------------------- */#define MAX_CARDS 4#define PFX "ymf_sb: "#define YMFSB_VERSION "0.0.6"#define YMFSB_CARD_NAME "YMF7xx Legacy Audio driver " YMFSB_VERSION#ifdef SUPPORT_UART401_MIDI#if 0# define ymf7xxsb_probe_midi probe_uart401# define ymf7xxsb_unload_midi unload_uart401#else# define ymf7xxsb_probe_midi probe_sbmpu# define ymf7xxsb_unload_midi unload_sbmpu#endif#endif/* ---------------------------------------------------------------------- */static struct address_info sb_data[MAX_CARDS];static struct address_info opl3_data[MAX_CARDS];#ifdef SUPPORT_UART401_MIDIstatic struct address_info mpu_data[MAX_CARDS];#endifstatic unsigned cards = 0;static unsigned short *ymfbase[MAX_CARDS];/* ---------------------------------------------------------------------- */#ifdef MODULE#ifdef SUPPORT_UART401_MIDIstatic int mpu_io = 0;#endifstatic int synth_io = 0;static int io = 0;static int dma = 0;static int master_vol = -1;static int spdif_out = 0;#ifdef SUPPORT_UART401_MIDIMODULE_PARM(mpu_io, "i");#endifMODULE_PARM(synth_io, "i");MODULE_PARM(io,"i");MODULE_PARM(dma,"i");MODULE_PARM(master_vol,"i");MODULE_PARM(spdif_out,"i");#else#ifdef SUPPORT_UART401_MIDIstatic int mpu_io = 0x330;#endifstatic int synth_io = 0x388;static int io = 0x220;static int dma = 1;static int master_vol = 80;static int spdif_out = 0;#endif/* ---------------------------------------------------------------------- */static int readRegWord( int adr ) { if (ymfbase[cards]==NULL) return 0; return readw(ymfbase[cards]+adr/2);}static void writeRegWord( int adr, int val ) { if (ymfbase[cards]==NULL) return; writew((unsigned short)(val&0xffff), ymfbase[cards] + adr/2); return;}static int readRegDWord( int adr ) { if (ymfbase[cards]==NULL) return 0; return (readl(ymfbase[cards]+adr/2));}static void writeRegDWord( int adr, int val ) { if (ymfbase[cards]==NULL) return; writel((unsigned int)(val&0xffffffff), ymfbase[cards]+adr/2); return;}/* ---------------------------------------------------------------------- */static int checkPrimaryBusy( void ){ int timeout=0; while ( timeout++ < YMFSB_AC97TIMEOUT ) { if ( (readRegWord(YMFSB_PRISTATUSADR) & 0x8000) == 0x0000 ) return 0; } return -1;}static int writeAc97( int adr, unsigned short val ){ if ( adr > 0x7f || adr < 0x00 ) return -1; if ( checkPrimaryBusy() ) return -1;#ifdef YMF_DEBUG printk(KERN_INFO PFX "AC97 0x%0x = 0x%0x\n",adr,val);#endif writeRegWord( YMFSB_AC97CMDADR, 0x0000 | adr ); writeRegWord( YMFSB_AC97CMDDATA, val ); return 0;}static int __init checkCodec( struct pci_dev *pcidev ){ u8 tmp8; pci_read_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, &tmp8); if ( tmp8 & 0x03 ) { pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc); mdelay(YMFSB_RESET_DELAY); pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8|0x03); mdelay(YMFSB_RESET_DELAY); pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc); mdelay(YMFSB_RESET_DELAY); } if ( checkPrimaryBusy() ) return -1; return 0;}static int __init setupLegacyIO( struct pci_dev *pcidev ){ int v; int sbio=0,mpuio=0,oplio=0,dma=0; switch(sb_data[cards].io_base) { case 0x220: sbio = 0; break; case 0x240: sbio = 1; break; case 0x260: sbio = 2; break; case 0x280: sbio = 3; break; default: return -1; break; }#ifdef YMF_DEBUG printk(PFX "set SBPro I/O at 0x%x\n",sb_data[cards].io_base);#endif#ifdef SUPPORT_UART401_MIDI switch(mpu_data[cards].io_base) { case 0x330: mpuio = 0; break; case 0x300: mpuio = 1; break; case 0x332: mpuio = 2; break; case 0x334: mpuio = 3; break; default: mpuio = 0; break; }# ifdef YMF_DEBUG printk(PFX "set MPU401 I/O at 0x%x\n",mpu_data[cards].io_base);# endif#endif switch(opl3_data[cards].io_base) { case 0x388: oplio = 0; break; case 0x398: oplio = 1; break; case 0x3a0: oplio = 2; break; case 0x3a8: oplio = 3; break; default: return -1; break; }#ifdef YMF_DEBUG printk(PFX "set OPL3 I/O at 0x%x\n",opl3_data[cards].io_base);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -