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

📄 sb16_csp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (!(channels & p->acc_channels)) {		snd_printd("%s: Invalid number of channels\n", __FUNCTION__);		return -EINVAL;	}	/* Mute PCM volume */	spin_lock_irqsave(&p->chip->mixer_lock, flags);	mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);	mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);	spin_lock(&p->chip->reg_lock);	set_mode_register(p->chip, 0xc0);	/* c0 = STOP */	set_mode_register(p->chip, 0x70);	/* 70 = RUN */	s_type = 0x00;	if (channels == SNDRV_SB_CSP_MONO)		s_type = 0x11;	/* 000n 000n    (n = 1 if mono) */	if (sample_width == SNDRV_SB_CSP_SAMPLE_8BIT)		s_type |= 0x22;	/* 00dX 00dX    (d = 1 if 8 bit samples) */	if (set_codec_parameter(p->chip, 0x81, s_type)) {		snd_printd("%s: Set sample type command failed\n", __FUNCTION__);		goto __fail;	}	if (set_codec_parameter(p->chip, 0x80, 0x00)) {		snd_printd("%s: Codec start command failed\n", __FUNCTION__);		goto __fail;	}	p->run_width = sample_width;	p->run_channels = channels;	p->running |= SNDRV_SB_CSP_ST_RUNNING;	if (p->mode & SNDRV_SB_CSP_MODE_QSOUND) {		set_codec_parameter(p->chip, 0xe0, 0x01);		/* enable QSound decoder */		set_codec_parameter(p->chip, 0x00, 0xff);		set_codec_parameter(p->chip, 0x01, 0xff);		p->running |= SNDRV_SB_CSP_ST_QSOUND;		/* set QSound startup value */		snd_sb_csp_qsound_transfer(p);	}	result = 0;      __fail:	spin_unlock(&p->chip->reg_lock);	/* restore PCM volume */	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);	spin_unlock_irqrestore(&p->chip->mixer_lock, flags);	return result;}/* * stop CSP */static int snd_sb_csp_stop(snd_sb_csp_t * p){	int result;	unsigned char mixL, mixR;	unsigned long flags;	if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))		return 0;	/* Mute PCM volume */	spin_lock_irqsave(&p->chip->mixer_lock, flags);	mixL = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV);	mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);	spin_lock(&p->chip->reg_lock);	if (p->running & SNDRV_SB_CSP_ST_QSOUND) {		set_codec_parameter(p->chip, 0xe0, 0x01);		/* disable QSound decoder */		set_codec_parameter(p->chip, 0x00, 0x00);		set_codec_parameter(p->chip, 0x01, 0x00);		p->running &= ~SNDRV_SB_CSP_ST_QSOUND;	}	result = set_mode_register(p->chip, 0xc0);	/* c0 = STOP */	spin_unlock(&p->chip->reg_lock);	/* restore PCM volume */	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);	snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);	spin_unlock_irqrestore(&p->chip->mixer_lock, flags);	if (!(result))		p->running &= ~(SNDRV_SB_CSP_ST_PAUSED | SNDRV_SB_CSP_ST_RUNNING);	return result;}/* * pause CSP codec and hold DMA transfer */static int snd_sb_csp_pause(snd_sb_csp_t * p){	int result;	unsigned long flags;	if (!(p->running & SNDRV_SB_CSP_ST_RUNNING))		return -EBUSY;	spin_lock_irqsave(&p->chip->reg_lock, flags);	result = set_codec_parameter(p->chip, 0x80, 0xff);	spin_unlock_irqrestore(&p->chip->reg_lock, flags);	if (!(result))		p->running |= SNDRV_SB_CSP_ST_PAUSED;	return result;}/* * restart CSP codec and resume DMA transfer */static int snd_sb_csp_restart(snd_sb_csp_t * p){	int result;	unsigned long flags;	if (!(p->running & SNDRV_SB_CSP_ST_PAUSED))		return -EBUSY;	spin_lock_irqsave(&p->chip->reg_lock, flags);	result = set_codec_parameter(p->chip, 0x80, 0x00);	spin_unlock_irqrestore(&p->chip->reg_lock, flags);	if (!(result))		p->running &= ~SNDRV_SB_CSP_ST_PAUSED;	return result;}/* ------------------------------ *//* * QSound mixer control for PCM */static int snd_sb_qsound_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 1;	return 0;}static int snd_sb_qsound_switch_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);		ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0;	return 0;}static int snd_sb_qsound_switch_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int change;	unsigned char nval;		nval = ucontrol->value.integer.value[0] & 0x01;	spin_lock_irqsave(&p->q_lock, flags);	change = p->q_enabled != nval;	p->q_enabled = nval;	spin_unlock_irqrestore(&p->q_lock, flags);	return change;}static int snd_sb_qsound_space_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;	return 0;}static int snd_sb_qsound_space_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);	unsigned long flags;		spin_lock_irqsave(&p->q_lock, flags);	ucontrol->value.integer.value[0] = p->qpos_left;	ucontrol->value.integer.value[1] = p->qpos_right;	spin_unlock_irqrestore(&p->q_lock, flags);	return 0;}static int snd_sb_qsound_space_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int change;	unsigned char nval1, nval2;		nval1 = ucontrol->value.integer.value[0];	if (nval1 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)		nval1 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;	nval2 = ucontrol->value.integer.value[1];	if (nval2 > SNDRV_SB_CSP_QSOUND_MAX_RIGHT)		nval2 = SNDRV_SB_CSP_QSOUND_MAX_RIGHT;	spin_lock_irqsave(&p->q_lock, flags);	change = p->qpos_left != nval1 || p->qpos_right != nval2;	p->qpos_left = nval1;	p->qpos_right = nval2;	p->qpos_changed = change;	spin_unlock_irqrestore(&p->q_lock, flags);	return change;}static snd_kcontrol_new_t snd_sb_qsound_switch = {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "3D Control - Switch",	.info = snd_sb_qsound_switch_info,	.get = snd_sb_qsound_switch_get,	.put = snd_sb_qsound_switch_put};static snd_kcontrol_new_t snd_sb_qsound_space = {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.name = "3D Control - Space",	.info = snd_sb_qsound_space_info,	.get = snd_sb_qsound_space_get,	.put = snd_sb_qsound_space_put};static int snd_sb_qsound_build(snd_sb_csp_t * p){	snd_card_t * card;	int err;	snd_assert(p != NULL, return -EINVAL);	card = p->chip->card;	p->qpos_left = p->qpos_right = SNDRV_SB_CSP_QSOUND_MAX_RIGHT / 2;	p->qpos_changed = 0;	spin_lock_init(&p->q_lock);	if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0)		goto __error;	if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0)		goto __error;	return 0;     __error:	snd_sb_qsound_destroy(p);	return err;}static void snd_sb_qsound_destroy(snd_sb_csp_t * p){	snd_card_t * card;	unsigned long flags;	snd_assert(p != NULL, return);	card = p->chip->card;			down_write(&card->controls_rwsem);	if (p->qsound_switch)		snd_ctl_remove(card, p->qsound_switch);	if (p->qsound_space)		snd_ctl_remove(card, p->qsound_space);	up_write(&card->controls_rwsem);	/* cancel pending transfer of QSound parameters */	spin_lock_irqsave (&p->q_lock, flags);	p->qpos_changed = 0;	spin_unlock_irqrestore (&p->q_lock, flags);}/* * Transfer qsound parameters to CSP, * function should be called from interrupt routine */static int snd_sb_csp_qsound_transfer(snd_sb_csp_t * p){	int err = -ENXIO;	spin_lock(&p->q_lock);	if (p->running & SNDRV_SB_CSP_ST_QSOUND) {		set_codec_parameter(p->chip, 0xe0, 0x01);		/* left channel */		set_codec_parameter(p->chip, 0x00, p->qpos_left);		set_codec_parameter(p->chip, 0x02, 0x00);		/* right channel */		set_codec_parameter(p->chip, 0x00, p->qpos_right);		set_codec_parameter(p->chip, 0x03, 0x00);		err = 0;	}	p->qpos_changed = 0;	spin_unlock(&p->q_lock);	return err;}/* ------------------------------ *//* * proc interface */static int init_proc_entry(snd_sb_csp_t * p, int device){	char name[16];	snd_info_entry_t *entry;	sprintf(name, "cspD%d", device);	if (! snd_card_proc_new(p->chip->card, name, &entry))		snd_info_set_text_ops(entry, p, 1024, info_read);	return 0;}static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer){	snd_sb_csp_t *p = entry->private_data;	snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));	snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),		    ((p->running & SNDRV_SB_CSP_ST_PAUSED) ? 'P' : '-'),		    ((p->running & SNDRV_SB_CSP_ST_RUNNING) ? 'R' : '-'),		    ((p->running & SNDRV_SB_CSP_ST_LOADED) ? 'L' : '-'));	if (p->running & SNDRV_SB_CSP_ST_LOADED) {		snd_iprintf(buffer, "Codec: %s [func #%d]\n", p->codec_name, p->func_nr);		snd_iprintf(buffer, "Sample rates: ");		if (p->acc_rates == SNDRV_SB_CSP_RATE_ALL) {			snd_iprintf(buffer, "All\n");		} else {			snd_iprintf(buffer, "%s%s%s%s\n",				    ((p->acc_rates & SNDRV_SB_CSP_RATE_8000) ? "8000Hz " : ""),				    ((p->acc_rates & SNDRV_SB_CSP_RATE_11025) ? "11025Hz " : ""),				    ((p->acc_rates & SNDRV_SB_CSP_RATE_22050) ? "22050Hz " : ""),				    ((p->acc_rates & SNDRV_SB_CSP_RATE_44100) ? "44100Hz" : ""));		}		if (p->mode == SNDRV_SB_CSP_MODE_QSOUND) {			snd_iprintf(buffer, "QSound decoder %sabled\n",				    p->q_enabled ? "en" : "dis");		} else {			snd_iprintf(buffer, "PCM format ID: 0x%x (%s/%s) [%s/%s] [%s/%s]\n",				    p->acc_format,				    ((p->acc_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? "16bit" : "-"),				    ((p->acc_width & SNDRV_SB_CSP_SAMPLE_8BIT) ? "8bit" : "-"),				    ((p->acc_channels & SNDRV_SB_CSP_MONO) ? "mono" : "-"),				    ((p->acc_channels & SNDRV_SB_CSP_STEREO) ? "stereo" : "-"),				    ((p->mode & SNDRV_SB_CSP_MODE_DSP_WRITE) ? "playback" : "-"),				    ((p->mode & SNDRV_SB_CSP_MODE_DSP_READ) ? "capture" : "-"));		}	}	if (p->running & SNDRV_SB_CSP_ST_AUTO) {		snd_iprintf(buffer, "Autoloaded Mu-Law, A-Law or Ima-ADPCM hardware codec\n");	}	if (p->running & SNDRV_SB_CSP_ST_RUNNING) {		snd_iprintf(buffer, "Processing %dbit %s PCM samples\n",			    ((p->run_width & SNDRV_SB_CSP_SAMPLE_16BIT) ? 16 : 8),			    ((p->run_channels & SNDRV_SB_CSP_MONO) ? "mono" : "stereo"));	}	if (p->running & SNDRV_SB_CSP_ST_QSOUND) {		snd_iprintf(buffer, "Qsound position: left = 0x%x, right = 0x%x\n",			    p->qpos_left, p->qpos_right);	}}/* */EXPORT_SYMBOL(snd_sb_csp_new);/* * INIT part */static int __init alsa_sb_csp_init(void){	return 0;}static void __exit alsa_sb_csp_exit(void){}module_init(alsa_sb_csp_init)module_exit(alsa_sb_csp_exit)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -