📄 ymf_sb.c
字号:
#endif dma = sb_data[cards].dma;#ifdef YMF_DEBUG printk(PFX "set DMA address at 0x%x\n",sb_data[cards].dma);#endif v = 0x0000 | ((dma & 0x03) << 6) | 0x003f; pci_write_config_word(pcidev, YMFSB_PCIR_LEGCTRL, v);#ifdef YMF_DEBUG printk(PFX "LEGCTRL: 0x%x\n",v);#endif switch( pcidev->device ) { case PCI_DEVICE_ID_YMF724: case PCI_DEVICE_ID_YMF740: case PCI_DEVICE_ID_YMF724F: case PCI_DEVICE_ID_YMF740C: v = 0x8800 | ((mpuio & 0x03) << 4) | ((sbio & 0x03) << 2) | (oplio & 0x03); pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);#ifdef YMF_DEBUG printk(PFX "ELEGCTRL: 0x%x\n",v);#endif break; case PCI_DEVICE_ID_YMF744: case PCI_DEVICE_ID_YMF754: v = 0x8800; pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);#ifdef YMF_DEBUG printk(PFX "ELEGCTRL: 0x%x\n",v);#endif pci_write_config_word(pcidev, YMFSB_PCIR_OPLADR, opl3_data[cards].io_base); pci_write_config_word(pcidev, YMFSB_PCIR_SBADR, sb_data[cards].io_base);#ifdef SUPPORT_UART401_MIDI pci_write_config_word(pcidev, YMFSB_PCIR_MPUADR, mpu_data[cards].io_base);#endif break; default: printk(KERN_ERR PFX "Invalid device ID: %d\n",pcidev->device); return -1; break; } return 0;}/* ---------------------------------------------------------------------- */static void enableDSP( void ){ writeRegDWord( YMFSB_CONFIG, 0x00000001 ); return;}static void disableDSP( void ){ int val; int i; val = readRegDWord( YMFSB_CONFIG ); if ( val ) { writeRegDWord( YMFSB_CONFIG, 0 ); } i=0; while( ++i < YMFSB_WORKBITTIMEOUT ) { val = readRegDWord(YMFSB_STATUS); if ( (val & 0x00000002) == 0x00000000 ) break; } return;}static int __init setupInstruction( struct pci_dev *pcidev ){ int i; int val; writeRegDWord( YMFSB_NATIVEDACOUTVOL, 0 ); /* mute dac */ disableDSP(); writeRegDWord( YMFSB_MODE, 0x00010000 ); /* DS-XG Software Reset */ writeRegDWord( YMFSB_MODE, 0x00000000 ); writeRegDWord( YMFSB_MAPOFREC, 0x00000000 ); writeRegDWord( YMFSB_MAPOFEFFECT, 0x00000000 ); writeRegDWord( YMFSB_PLAYCTRLBASE, 0x00000000 ); writeRegDWord( YMFSB_RECCTRLBASE, 0x00000000 ); writeRegDWord( YMFSB_EFFCTRLBASE, 0x00000000 ); val = readRegWord( YMFSB_GLOBALCTRL ); writeRegWord( YMFSB_GLOBALCTRL, (val&~0x0007) ); /* setup DSP instruction code */ for ( i=0 ; i<YMFSB_DSPLENGTH ; i+=4 ) { writeRegDWord( YMFSB_DSPINSTRAM+i, DspInst[i>>2] ); } switch( pcidev->device ) { case PCI_DEVICE_ID_YMF724: case PCI_DEVICE_ID_YMF740: /* setup Control instruction code */ for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) { writeRegDWord( YMFSB_CTRLINSTRAM+i, CntrlInst[i>>2] ); } break; case PCI_DEVICE_ID_YMF724F: case PCI_DEVICE_ID_YMF740C: case PCI_DEVICE_ID_YMF744: case PCI_DEVICE_ID_YMF754: /* setup Control instruction code */ for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) { writeRegDWord( YMFSB_CTRLINSTRAM+i, CntrlInst1E[i>>2] ); } break; default: return -1; } enableDSP(); return 0;}/* ---------------------------------------------------------------------- */static int __init ymf7xx_init(struct pci_dev *pcidev){ unsigned short v; /* Read hardware information */#ifdef YMF_DEBUG unsigned int dv; pci_read_config_word(pcidev, YMFSB_PCIR_VENDORID, &v); printk(KERN_INFO PFX "Vendor ID = 0x%x\n",v); pci_read_config_word(pcidev, YMFSB_PCIR_DEVICEID, &v); printk(KERN_INFO PFX "Device ID = 0x%x\n",v); pci_read_config_word(pcidev, YMFSB_PCIR_REVISIONID, &v); printk(KERN_INFO PFX "Revision ID = 0x%x\n",v&0xff); pci_read_config_dword(pcidev, YMFSB_PCIR_BASEADDR, &dv); printk(KERN_INFO PFX "Base address = 0x%x\n",dv); pci_read_config_word(pcidev, YMFSB_PCIR_IRQ, &v); printk(KERN_INFO PFX "IRQ line = 0x%x\n",v&0xff);#endif /* enables memory space access / bus mastering */ pci_read_config_word(pcidev, YMFSB_PCIR_CMD, &v); pci_write_config_word(pcidev, YMFSB_PCIR_CMD, v|0x06); /* check codec */#ifdef YMF_DEBUG printk(KERN_INFO PFX "check codec...\n");#endif if (checkCodec(pcidev)) return -1; /* setup legacy I/O */#ifdef YMF_DEBUG printk(KERN_INFO PFX "setup legacy I/O...\n");#endif if (setupLegacyIO(pcidev)) return -1; /* setup instruction code */ #ifdef YMF_DEBUG printk(KERN_INFO PFX "setup instructions...\n");#endif if (setupInstruction(pcidev)) return -1; /* AC'97 setup */ #ifdef YMF_DEBUG printk(KERN_INFO PFX "setup AC'97...\n");#endif if ( writeAc97(AC97_RESET ,0x0000) ) /* Reset */ return -1; if ( writeAc97(AC97_MASTER_VOL_STEREO,0x0000) ) /* Master Volume */ return -1; v = 31*(100-master_vol)/100; v = (v<<8 | v)&0x7fff; if ( writeAc97(AC97_PCMOUT_VOL ,v ) ) /* PCM out Volume */ return -1;#ifdef YMF_DEBUG printk(KERN_INFO PFX "setup Legacy Volume...\n");#endif /* Legacy Audio Output Volume L & R ch */ writeRegDWord( YMFSB_LEGACYOUTVOL, 0x3fff3fff );#ifdef YMF_DEBUG printk(KERN_INFO PFX "setup SPDIF output control...\n");#endif /* SPDIF Output control */ v = spdif_out != 0 ? 0x0001 : 0x0000; writeRegWord( YMFSB_SPDIFOUTCTRL, v ); /* no copyright protection, sample-rate converted, re-recorded software comercially available (the 1st generation), original */ writeRegWord( YMFSB_SPDIFOUTSTATUS, 0x9a04 ); return 0;}/* ---------------------------------------------------------------------- */static void __init ymf7xxsb_attach_sb(struct address_info *hw_config){ if(!sb_dsp_init(hw_config, THIS_MODULE)) hw_config->slots[0] = -1;}static int __init ymf7xxsb_probe_sb(struct address_info *hw_config){ if (check_region(hw_config->io_base, 16)) { printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n", hw_config->io_base); return 0; } return sb_dsp_detect(hw_config, SB_PCI_YAMAHA, 0, NULL);}static void ymf7xxsb_unload_sb(struct address_info *hw_config, int unload_mpu){ if(hw_config->slots[0]!=-1) sb_dsp_unload(hw_config, unload_mpu);}/* ---------------------------------------------------------------------- */enum chip_types { CH_YMF724 = 0, CH_YMF724F, CH_YMF740, CH_YMF740C, CH_YMF744, CH_YMF754,};/* directly indexed by chip_types enum above *//* note we keep this a struct to ease adding * other per-board or per-chip info here */struct { const char *devicename;} devicetable[] __initdata = { { "YMF724A-E" }, { "YMF724F" }, { "YMF740A-B" }, { "YMF740C" }, { "YMF744" }, { "YMF754" },};static struct pci_device_id ymf7xxsb_pci_tbl[] __initdata = { { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF724 }, { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF724F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF724F }, { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF740, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF740 }, { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF740C }, { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF744, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF744 }, { PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF754, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF754 }, { 0, }};MODULE_DEVICE_TABLE(pci, ymf7xxsb_pci_tbl);static int __init ymf7xxsb_init_one (struct pci_dev *pcidev, const struct pci_device_id *ent){ const char *devicename; unsigned long iobase; if (cards == MAX_CARDS) { printk (KERN_DEBUG PFX "maximum number of cards reached\n"); return -ENODEV; } if ( pcidev->irq == 0 ) return -ENODEV; iobase = pci_resource_start (pcidev, 0); if ( iobase == 0x00000000 ) return -ENODEV; devicename = devicetable[ent->driver_data].devicename; /* remap memory mapped I/O onto kernel virtual memory */ if ( (ymfbase[cards] = ioremap_nocache(iobase, YMFSB_REGSIZE)) == 0 ) { printk(KERN_ERR PFX "ioremap (0x%lx) returns zero\n", iobase); return -ENODEV; } printk(KERN_INFO PFX "found %s at 0x%lx\n", devicename, iobase);#ifdef YMF_DEBUG printk(KERN_INFO PFX "remappling to 0x%p\n", ymfbase[cards]);#endif memset (&sb_data[cards], 0, sizeof (struct address_info)); memset (&opl3_data[cards], 0, sizeof (struct address_info));#ifdef SUPPORT_UART401_MIDI memset (&mpu_data[cards], 0, sizeof (struct address_info));#endif sb_data[cards].name = YMFSB_CARD_NAME; opl3_data[cards].name = YMFSB_CARD_NAME;#ifdef SUPPORT_UART401_MIDI mpu_data[cards].name = YMFSB_CARD_NAME;#endif sb_data[cards].card_subtype = MDL_YMPCI; if ( io == 0 ) io = 0x220; sb_data[cards].io_base = io; sb_data[cards].irq = pcidev->irq; sb_data[cards].dma = dma; if ( synth_io == 0 ) synth_io = 0x388; opl3_data[cards].io_base = synth_io; opl3_data[cards].irq = -1;#ifdef SUPPORT_UART401_MIDI if ( mpu_io == 0 ) mpu_io = 0x330; mpu_data[cards].io_base = mpu_io; mpu_data[cards].irq = -1;#endif if ( ymf7xx_init(pcidev) ) { printk (KERN_ERR PFX "Cannot initialize %s, aborting\n", devicename); return -ENODEV; } /* register legacy SoundBlaster Pro */ if (!ymf7xxsb_probe_sb(&sb_data[cards])) { printk (KERN_ERR PFX "SB probe at 0x%X failed, aborting\n", io); return -ENODEV; } ymf7xxsb_attach_sb (&sb_data[cards]);#ifdef SUPPORT_UART401_MIDI /* register legacy MIDI */ if ( mpu_io > 0 && 0) { if (!ymf7xxsb_probe_midi (&mpu_data[cards], THIS_MODULE)) { printk (KERN_ERR PFX "MIDI probe @ 0x%X failed, aborting\n", mpu_io); ymf7xxsb_unload_sb (&sb_data[cards], 0); return -ENODEV; } }#endif /* register legacy OPL3 */ cards++; return 0;}static struct pci_driver ymf7xxsb_driver = { name: "ymf7xxsb", id_table: ymf7xxsb_pci_tbl, probe: ymf7xxsb_init_one,};static int __init init_ymf7xxsb_module(void){ int i; if ( master_vol < 0 ) master_vol = 50; if ( master_vol > 100 ) master_vol = 100; for (i=0 ; i<MAX_CARDS ; i++ ) ymfbase[i] = NULL; i = pci_module_init (&ymf7xxsb_driver); if (i < 0) return i; printk (KERN_INFO PFX YMFSB_CARD_NAME " loaded\n"); return 0;}static void __exit free_iomaps( void ){ int i; for ( i=0 ; i<MAX_CARDS ; i++ ) { if ( ymfbase[i]!=NULL ) iounmap(ymfbase[i]); } return;}static void __exit cleanup_ymf7xxsb_module(void){ int i; for (i = 0; i < cards; i++) {#ifdef SUPPORT_UART401_MIDI ymf7xxsb_unload_sb (&sb_data[i], 0); ymf7xxsb_unload_midi (&mpu_data[i]);#else ymf7xxsb_unload_sb (&sb_data[i], 1);#endif } free_iomaps(); pci_unregister_driver(&ymf7xxsb_driver);}MODULE_AUTHOR("Daisuke Nagano, breeze.nagano@nifty.ne.jp");MODULE_DESCRIPTION("YMF7xx Legacy Audio Driver");module_init(init_ymf7xxsb_module);module_exit(cleanup_ymf7xxsb_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -