📄 opl3sa2.c
字号:
case SOUND_MIXER_RECMASK: case SOUND_MIXER_RECSRC: case SOUND_MIXER_CAPS: break; default: return -EINVAL; } if(((cmd >> 8) & 0xff) != 'M') return -EINVAL; if(_SIOC_DIR (cmd) & _SIOC_WRITE) { switch (cmdf) { case SOUND_MIXER_VOLUME: arg_to_vol_stereo(*(unsigned int*)arg, &devc->volume_l, &devc->volume_r); opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r); *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r); return 0; case SOUND_MIXER_MIC: arg_to_vol_mono(*(unsigned int*)arg, &devc->mic); opl3sa2_set_mic(devc, devc->mic); *(int*)arg = ret_vol_mono(devc->mic); return 0; default: return -EINVAL; } } else { /* * Return parameters */ switch (cmdf) { case SOUND_MIXER_DEVMASK: *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC); return 0; case SOUND_MIXER_STEREODEVS: *(int*)arg = SOUND_MASK_VOLUME; return 0; case SOUND_MIXER_RECMASK: /* No recording devices */ return (*(int*)arg = 0); case SOUND_MIXER_CAPS: *(int*)arg = SOUND_CAP_EXCL_INPUT; return 0; case SOUND_MIXER_RECSRC: /* No recording source */ return (*(int*)arg = 0); case SOUND_MIXER_VOLUME: *(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r); return 0; case SOUND_MIXER_MIC: *(int*)arg = ret_vol_mono(devc->mic); return 0; default: return -EINVAL; } }}/* opl3sa2_mixer_ioctl end */static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg){ int cmdf = cmd & 0xff; opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc; switch(cmdf) { case SOUND_MIXER_BASS: case SOUND_MIXER_TREBLE: case SOUND_MIXER_DIGITAL1: case SOUND_MIXER_DEVMASK: case SOUND_MIXER_STEREODEVS: break; default: return opl3sa2_mixer_ioctl(dev, cmd, arg); } if(((cmd >> 8) & 0xff) != 'M') return -EINVAL; if(_SIOC_DIR (cmd) & _SIOC_WRITE) { switch (cmdf) { case SOUND_MIXER_BASS: arg_to_vol_stereo(*(unsigned int*)arg, &devc->bass_l, &devc->bass_r); opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r); *(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r); return 0; case SOUND_MIXER_TREBLE: arg_to_vol_stereo(*(unsigned int*)arg, &devc->treble_l, &devc->treble_r); opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r); *(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r); return 0; case SOUND_MIXER_DIGITAL1: arg_to_vol_stereo(*(unsigned int*)arg, &devc->wide_l, &devc->wide_r); opl3sa3_set_wide(devc, devc->wide_l, devc->wide_r); *(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r); return 0; default: return -EINVAL; } } else { /* * Return parameters */ switch (cmdf) { case SOUND_MIXER_DEVMASK: *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_DIGITAL1); return 0; case SOUND_MIXER_STEREODEVS: *(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_DIGITAL1); return 0; case SOUND_MIXER_BASS: *(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r); return 0; case SOUND_MIXER_TREBLE: *(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r); return 0; case SOUND_MIXER_DIGITAL1: *(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r); return 0; default: return -EINVAL; } }}/* opl3sa3_mixer_ioctl end */static struct mixer_operations opl3sa2_mixer_operations ={ owner: THIS_MODULE, id: "OPL3-SA2", name: "Yamaha OPL3-SA2", ioctl: opl3sa2_mixer_ioctl};static struct mixer_operations opl3sa3_mixer_operations ={ owner: THIS_MODULE, id: "OPL3-SA3", name: "Yamaha OPL3-SA3", ioctl: opl3sa3_mixer_ioctl};/* End of mixer-related stuff *//* * Component probe, attach, unload functions */static inline int __init probe_opl3sa2_mpu(struct address_info* hw_config){ return probe_mpu401(hw_config);}static inline void __init attach_opl3sa2_mpu(struct address_info* hw_config){ attach_mpu401(hw_config, THIS_MODULE);}static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config){ unload_mpu401(hw_config);}static inline int __init probe_opl3sa2_mss(struct address_info* hw_config){ return probe_ms_sound(hw_config);}static void __init attach_opl3sa2_mss(struct address_info* hw_config){ int initial_mixers; initial_mixers = num_mixers; attach_ms_sound(hw_config, THIS_MODULE); /* Slot 0 */ if(hw_config->slots[0] != -1) { /* Did the MSS driver install? */ if(num_mixers == (initial_mixers + 1)) { /* The MSS mixer is installed, reroute mixers appropiately */ AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD); AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH); AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); } else { printk(KERN_ERR "opl3sa2: MSS mixer not installed?\n"); } }}static inline void __exit unload_opl3sa2_mss(struct address_info* hw_config){ unload_ms_sound(hw_config);}static int __init probe_opl3sa2(struct address_info* hw_config, int card){ unsigned char misc; unsigned char tmp; unsigned char version; char tag; /* * Try and allocate our I/O port range. */ if(!request_region(hw_config->io_base, 2, OPL3SA2_MODULE_NAME)) { printk(KERN_ERR "opl3sa2: Control I/O port %#x not free\n", hw_config->io_base); return 0; } /* * Check if writing to the read-only version bits of the miscellaneous * register succeeds or not (it should not). */ opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc); opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc ^ 0x07); opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &tmp); if(tmp != misc) { printk(KERN_ERR "opl3sa2: Control I/O port %#x is not a YMF7xx chipset!\n", hw_config->io_base); return 0; } /* * Check if the MIC register is accessible. */ opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp); opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, 0x8a); opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp); if((tmp & 0x9f) != 0x8a) { printk(KERN_ERR "opl3sa2: Control I/O port %#x is not a YMF7xx chipset!\n", hw_config->io_base); return 0; } opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, tmp); /* * Determine chipset type (SA2 or SA3) * * This is done by looking at the chipset version in the lower 3 bits * of the miscellaneous register. */ version = misc & 0x07; printk(KERN_DEBUG "opl3sa2: chipset version = %#x\n", version); switch(version) { case 0: chipset[card] = CHIPSET_UNKNOWN; tag = '?'; /* silence compiler warning */ printk(KERN_ERR "opl3sa2: Unknown Yamaha audio controller version\n"); break; case VERSION_YMF711: chipset[card] = CHIPSET_OPL3SA2; tag = '2'; printk(KERN_INFO "opl3sa2: Found OPL3-SA2 (YMF711)\n"); break; case VERSION_YMF715: chipset[card] = CHIPSET_OPL3SA3; tag = '3'; printk(KERN_INFO "opl3sa2: Found OPL3-SA3 (YMF715 or YMF719)\n"); break; case VERSION_YMF715B: chipset[card] = CHIPSET_OPL3SA3; tag = '3'; printk(KERN_INFO "opl3sa2: Found OPL3-SA3 (YMF715B or YMF719B)\n"); break; case VERSION_YMF715E: default: chipset[card] = CHIPSET_OPL3SA3; tag = '3'; printk(KERN_INFO "opl3sa2: Found OPL3-SA3 (YMF715E or YMF719E)\n"); break; } if(chipset[card] != CHIPSET_UNKNOWN) { /* Generate a pretty name */ sprintf(chipset_name[card], "OPL3-SA%c", tag); return 1; } return 0;}static void __init attach_opl3sa2(struct address_info* hw_config, int card){ /* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */ opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d); /* Initialize DMA configuration */ if(hw_config->dma2 == hw_config->dma) { /* Want DMA configuration DMA-B: -, DMA-A: WSS-P+WSS-R */ opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x03); } else { /* Want DMA configuration DMA-B: WSS-R, DMA-A: WSS-P */ opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x21); }}static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card){ struct mixer_operations* mixer_operations; opl3sa2_mixerdata* devc; /* Install master mixer */ if(chipset[card] == CHIPSET_OPL3SA3) { mixer_operations = &opl3sa3_mixer_operations; } else { mixer_operations = &opl3sa2_mixer_operations; } if((devc = &opl3sa2_data[card])) { devc->cfg_port = hw_config->io_base; opl3sa2_mixer[card] = sound_install_mixer(MIXER_DRIVER_VERSION, mixer_operations->name, mixer_operations, sizeof(struct mixer_operations), devc); if(opl3sa2_mixer[card] < 0) { printk(KERN_ERR "opl3sa2: Could not install %s master mixer\n", mixer_operations->name); } else opl3sa2_mixer_reset(devc, card); }}static void __init opl3sa2_clear_slots(struct address_info* hw_config){ int i; for(i = 0; i < 6; i++) { hw_config->slots[i] = -1; }}static void __init opl3sa2_set_ymode(struct address_info* hw_config, int ymode){ /* * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and * it's supported. * * 0: Desktop (aka normal) 5-12 cm speakers * 1: Notebook PC mode 1 3 cm speakers * 2: Notebook PC mode 2 1.5 cm speakers * 3: Hi-fi 16-38 cm speakers */ if(ymode >= 0 && ymode <= 3) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -