📄 pss.c
字号:
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 int set_volume_mono(unsigned __user *p, int *aleft){ int left; unsigned volume; if (get_user(volume, p)) return -EFAULT; left = volume & 0xff; if (left > 100) left = 100; *aleft = left; return 0;}static int set_volume_stereo(unsigned __user *p, int *aleft, int *aright){ int left, right; unsigned volume; if (get_user(volume, p)) return -EFAULT; left = volume & 0xff; if (left > 100) left = 100; right = (volume >> 8) & 0xff; if (right > 100) right = 100; *aleft = left; *aright = right; return 0;}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, void __user *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, void __user *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 { int v; if (get_user(v, (int __user *)arg)) return -EFAULT; if (v != 0) return -EINVAL; return 0; } case SOUND_MIXER_VOLUME: if (set_volume_stereo(arg, &devc->mixer.volume_l, &devc->mixer.volume_r)) return -EFAULT; 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: if (set_volume_mono(arg, &devc->mixer.bass)) return -EFAULT; set_bass(devc, devc->mixer.bass); return ret_vol_mono(devc->mixer.bass); case SOUND_MIXER_TREBLE: if (set_volume_mono(arg, &devc->mixer.treble)) return -EFAULT; set_treble(devc, devc->mixer.treble); return ret_vol_mono(devc->mixer.treble); case SOUND_MIXER_SYNTH: if (set_volume_mono(arg, &devc->mixer.synth)) return -EFAULT; set_synth_volume(devc, devc->mixer.synth); return ret_vol_mono(devc->mixer.synth); default: return -EINVAL; } } else { int val, and_mask = 0, or_mask = 0; /* * Return parameters */ switch (cmdf) { case SOUND_MIXER_DEVMASK: if (call_ad_mixer(devc, cmd, arg) == -EINVAL) break; and_mask = ~0; or_mask = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH; break; case SOUND_MIXER_STEREODEVS: if (call_ad_mixer(devc, cmd, arg) == -EINVAL) break; and_mask = ~0; or_mask = SOUND_MASK_VOLUME; break; case SOUND_MIXER_RECMASK: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); break; case SOUND_MIXER_CAPS: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); or_mask = SOUND_CAP_EXCL_INPUT; break; case SOUND_MIXER_RECSRC: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); break; case SOUND_MIXER_VOLUME: or_mask = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r); break; case SOUND_MIXER_BASS: or_mask = ret_vol_mono(devc->mixer.bass); break; case SOUND_MIXER_TREBLE: or_mask = ret_vol_mono(devc->mixer.treble); break; case SOUND_MIXER_SYNTH: or_mask = ret_vol_mono(devc->mixer.synth); break; default: return -EINVAL; } if (get_user(val, (int __user *)arg)) return -EFAULT; val &= and_mask; val |= or_mask; if (put_user(val, (int __user *)arg)) return -EFAULT; return val; }}static struct mixer_operations pss_mixer_operations ={ .owner = THIS_MODULE, .id = "SOUNDPORT", .name = "PSS-AD1848", .ioctl = pss_mixer_ioctl};static 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));}static 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); }}static int __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 0; id = inw(REG(PSS_ID)) & 0x00ff; /* * Disable all emulations. Will be enabled later (if required). */ disable_all_emulations();#ifdef YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES if (sound_alloc_dma(hw_config->dma, "PSS")) { printk("pss.c: Can't allocate DMA channel.\n"); release_region(hw_config->io_base, 0x10); release_region(hw_config->io_base+0x10, 0x9); return 0; } if (!set_irq(devc, CONF_PSS, devc->irq)) { printk("PSS: IRQ allocation error.\n"); release_region(hw_config->io_base, 0x10); release_region(hw_config->io_base+0x10, 0x9); return 0; } if (!set_dma(devc, CONF_PSS, devc->dma)) { printk(KERN_ERR "PSS: DMA allocation error\n"); release_region(hw_config->io_base, 0x10); release_region(hw_config->io_base+0x10, 0x9); return 0; }#endif configure_nonsound_components(); pss_initialized = 1; sprintf(tmp, "ECHO-PSS Rev. %d", id); conf_printf(tmp, hw_config); return 1;}static int __init probe_pss_mpu(struct address_info *hw_config){ struct resource *ports; int timeout; if (!pss_initialized) return 0; ports = request_region(hw_config->io_base, 2, "mpu401"); if (!ports) { 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"); goto fail; } if (!set_irq(devc, CONF_MIDI, hw_config->irq)) { printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n"); goto fail; } if (!pss_synthLen) { printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n"); goto fail; } 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"); goto fail; } /* * 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 */ } if (!probe_mpu401(hw_config, ports)) goto fail; attach_mpu401(hw_config, THIS_MODULE); /* Slot 1 */ if (hw_config->slots[1] != -1) /* The MPU driver installed itself */ midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations; return 1;fail: release_region(hw_config->io_base, 2); return 0;}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: break; } 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -