⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pss.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -