📄 pss.c
字号:
int vol = ((0x8000*volume)/100L); pss_write(devc, 0x0080); pss_write(devc, vol); pss_write(devc, 0x0081); pss_write(devc, vol);}static void set_bass(pss_confdata *devc, int level){ int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0; pss_write(devc, 0x0010); pss_write(devc, vol | 0x0200);};static void set_treble(pss_confdata *devc, int level){ int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0; pss_write(devc, 0x0010); pss_write(devc, vol | 0x0300);};static void pss_mixer_reset(pss_confdata *devc){ set_master_volume(devc, 33, 33); set_bass(devc, 50); set_treble(devc, 50); set_synth_volume(devc, 30); pss_write (devc, 0x0010); pss_write (devc, 0x0800 | 0xce); /* Stereo */ if(pss_mixer) { devc->mixer.volume_l = devc->mixer.volume_r = 33; devc->mixer.bass = 50; devc->mixer.treble = 50; devc->mixer.synth = 30; }}static void arg_to_volume_mono(unsigned int volume, int *aleft){ int left; left = volume & 0x00ff; if (left > 100) left = 100; *aleft = left;}static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright){ arg_to_volume_mono(volume, aleft); arg_to_volume_mono(volume >> 8, aright);}static int ret_vol_mono(int left){ return ((left << 8) | left);}static int ret_vol_stereo(int left, int right){ return ((right << 8) | left);}static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, caddr_t arg){ if (devc->ad_mixer_dev != NO_WSS_MIXER) return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg); else return -EINVAL;}static int pss_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg){ pss_confdata *devc = mixer_devs[dev]->devc; int cmdf = cmd & 0xff; if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) && (cmdf != SOUND_MIXER_TREBLE) && (cmdf != SOUND_MIXER_SYNTH) && (cmdf != SOUND_MIXER_DEVMASK) && (cmdf != SOUND_MIXER_STEREODEVS) && (cmdf != SOUND_MIXER_RECMASK) && (cmdf != SOUND_MIXER_CAPS) && (cmdf != SOUND_MIXER_RECSRC)) { return call_ad_mixer(devc, cmd, arg); } if (((cmd >> 8) & 0xff) != 'M') return -EINVAL; if (_SIOC_DIR (cmd) & _SIOC_WRITE) { switch (cmdf) { case SOUND_MIXER_RECSRC: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); else { if (*(int *)arg != 0) return -EINVAL; return 0; } case SOUND_MIXER_VOLUME: arg_to_volume_stereo(*(unsigned int *)arg, &devc->mixer.volume_l, &devc->mixer.volume_r); set_master_volume(devc, devc->mixer.volume_l, devc->mixer.volume_r); return ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r); case SOUND_MIXER_BASS: arg_to_volume_mono(*(unsigned int *)arg, &devc->mixer.bass); set_bass(devc, devc->mixer.bass); return ret_vol_mono(devc->mixer.bass); case SOUND_MIXER_TREBLE: arg_to_volume_mono(*(unsigned int *)arg, &devc->mixer.treble); set_treble(devc, devc->mixer.treble); return ret_vol_mono(devc->mixer.treble); case SOUND_MIXER_SYNTH: arg_to_volume_mono(*(unsigned int *)arg, &devc->mixer.synth); set_synth_volume(devc, devc->mixer.synth); return ret_vol_mono(devc->mixer.synth); default: return -EINVAL; } } else { /* * Return parameters */ switch (cmdf) { case SOUND_MIXER_DEVMASK: if (call_ad_mixer(devc, cmd, arg) == -EINVAL) *(int *)arg = 0; /* no mixer devices */ return (*(int *)arg |= SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH); case SOUND_MIXER_STEREODEVS: if (call_ad_mixer(devc, cmd, arg) == -EINVAL) *(int *)arg = 0; /* no stereo devices */ return (*(int *)arg |= SOUND_MASK_VOLUME); case SOUND_MIXER_RECMASK: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); else return (*(int *)arg = 0); /* no record devices */ case SOUND_MIXER_CAPS: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); else return (*(int *)arg = SOUND_CAP_EXCL_INPUT); case SOUND_MIXER_RECSRC: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); else return (*(int *)arg = 0); /* no record source */ case SOUND_MIXER_VOLUME: return (*(int *)arg = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r)); case SOUND_MIXER_BASS: return (*(int *)arg = ret_vol_mono(devc->mixer.bass)); case SOUND_MIXER_TREBLE: return (*(int *)arg = ret_vol_mono(devc->mixer.treble)); case SOUND_MIXER_SYNTH: return (*(int *)arg = ret_vol_mono(devc->mixer.synth)); default: return -EINVAL; } }}static struct mixer_operations pss_mixer_operations ={ owner: THIS_MODULE, id: "SOUNDPORT", name: "PSS-AD1848", ioctl: pss_mixer_ioctl};void disable_all_emulations(void){ outw(0x0000, REG(CONF_PSS)); /* 0x0400 enables joystick */ outw(0x0000, REG(CONF_WSS)); outw(0x0000, REG(CONF_SB)); outw(0x0000, REG(CONF_MIDI)); outw(0x0000, REG(CONF_CDROM));}void configure_nonsound_components(void){ /* Configure Joystick port */ if(pss_enable_joystick) { outw(0x0400, REG(CONF_PSS)); /* 0x0400 enables joystick */ printk(KERN_INFO "PSS: joystick enabled.\n"); } else { printk(KERN_INFO "PSS: joystick port not enabled.\n"); } /* Configure CDROM port */ if(pss_cdrom_port == -1) /* If cdrom port enablation wasn't requested */ { printk(KERN_INFO "PSS: CDROM port not enabled.\n"); } else if(check_region(pss_cdrom_port, 2)) { printk(KERN_ERR "PSS: CDROM I/O port conflict.\n"); } else if(!set_io_base(devc, CONF_CDROM, pss_cdrom_port)) { printk(KERN_ERR "PSS: CDROM I/O port could not be set.\n"); } else /* CDROM port successfully configured */ { printk(KERN_INFO "PSS: CDROM I/O port set to 0x%x.\n", pss_cdrom_port); }}void __init attach_pss(struct address_info *hw_config){ unsigned short id; char tmp[100]; devc->base = hw_config->io_base; devc->irq = hw_config->irq; devc->dma = hw_config->dma; devc->osp = hw_config->osp; devc->ad_mixer_dev = NO_WSS_MIXER; if (!probe_pss(hw_config)) return; request_region(hw_config->io_base, 0x10, "PSS mixer, SB emulation"); request_region(hw_config->io_base + 0x10, 0x9, "PSS config"); id = inw(REG(PSS_ID)) & 0x00ff; /* * Disable all emulations. Will be enabled later (if required). */ disable_all_emulations();#if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES if (sound_alloc_dma(hw_config->dma, "PSS")) { printk("pss.c: Can't allocate DMA channel.\n"); return; } if (!set_irq(devc, CONF_PSS, devc->irq)) { printk("PSS: IRQ allocation error.\n"); return; } if (!set_dma(devc, CONF_PSS, devc->dma)) { printk(KERN_ERR "PSS: DMA allocation error\n"); return; }#endif configure_nonsound_components(); pss_initialized = 1; sprintf(tmp, "ECHO-PSS Rev. %d", id); conf_printf(tmp, hw_config);}int __init probe_pss_mpu(struct address_info *hw_config){ int timeout; if (!pss_initialized) return 0; if (check_region(hw_config->io_base, 2)) { printk(KERN_ERR "PSS: MPU I/O port conflict\n"); return 0; } if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) { printk(KERN_ERR "PSS: MIDI base could not be set.\n"); return 0; } if (!set_irq(devc, CONF_MIDI, hw_config->irq)) { printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n"); return 0; } if (!pss_synthLen) { printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n"); return 0; } if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) { printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); return 0; } /* * Finally wait until the DSP algorithm has initialized itself and * deactivates receive interrupt. */ for (timeout = 900000; timeout > 0; timeout--) { if ((inb(hw_config->io_base + 1) & 0x80) == 0) /* Input data avail */ inb(hw_config->io_base); /* Discard it */ else break; /* No more input */ } return probe_mpu401(hw_config);}static int pss_coproc_open(void *dev_info, int sub_device){ switch (sub_device) { case COPR_MIDI: if (pss_synthLen == 0) { printk(KERN_ERR "PSS: MIDI synth microcode not available.\n"); return -EIO; } if (nonstandard_microcode) if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) { printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); return -EIO; } nonstandard_microcode = 0; break; default: } return 0;}static void pss_coproc_close(void *dev_info, int sub_device){ return;}static void pss_coproc_reset(void *dev_info){ if (pss_synthLen) if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) { printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); } nonstandard_microcode = 0;}static int download_boot_block(void *dev_info, copr_buffer * buf){ if (buf->len <= 0 || buf->len > sizeof(buf->data)) return -EINVAL; if (!pss_download_boot(devc, buf->data, buf->len, buf->flags)) { printk(KERN_ERR "PSS: Unable to load microcode block to DSP.\n"); return -EIO; } nonstandard_microcode = 1; /* The MIDI microcode has been overwritten */ return 0;}static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, caddr_t arg, int local){ copr_buffer *buf; copr_msg *mbuf; copr_debug_buf dbuf; unsigned short tmp; unsigned long flags; unsigned short *data; int i, err; /* printk( "PSS coproc ioctl %x %x %d\n", cmd, arg, local); */ switch (cmd) { case SNDCTL_COPR_RESET: pss_coproc_reset(dev_info); return 0; case SNDCTL_COPR_LOAD: buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); if (buf == NULL) return -ENOSPC; if (copy_from_user(buf, arg, sizeof(copr_buffer))) { vfree(buf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -