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

📄 sonicvibes.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	.fifo_size =		0,};static struct snd_pcm_hardware snd_sonicvibes_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(128*1024),	.period_bytes_min =	32,	.period_bytes_max =	(128*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static int snd_sonicvibes_playback_open(struct snd_pcm_substream *substream){	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	sonic->mode |= SV_MODE_PLAY;	sonic->playback_substream = substream;	runtime->hw = snd_sonicvibes_playback;	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, snd_sonicvibes_hw_constraint_dac_rate, NULL, SNDRV_PCM_HW_PARAM_RATE, -1);	return 0;}static int snd_sonicvibes_capture_open(struct snd_pcm_substream *substream){	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	sonic->mode |= SV_MODE_CAPTURE;	sonic->capture_substream = substream;	runtime->hw = snd_sonicvibes_capture;	snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,				      &snd_sonicvibes_hw_constraints_adc_clock);	return 0;}static int snd_sonicvibes_playback_close(struct snd_pcm_substream *substream){	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);	sonic->playback_substream = NULL;	sonic->mode &= ~SV_MODE_PLAY;	return 0;}static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream){	struct sonicvibes *sonic = snd_pcm_substream_chip(substream);	sonic->capture_substream = NULL;	sonic->mode &= ~SV_MODE_CAPTURE;	return 0;}static struct snd_pcm_ops snd_sonicvibes_playback_ops = {	.open =		snd_sonicvibes_playback_open,	.close =	snd_sonicvibes_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_sonicvibes_hw_params,	.hw_free =	snd_sonicvibes_hw_free,	.prepare =	snd_sonicvibes_playback_prepare,	.trigger =	snd_sonicvibes_playback_trigger,	.pointer =	snd_sonicvibes_playback_pointer,};static struct snd_pcm_ops snd_sonicvibes_capture_ops = {	.open =		snd_sonicvibes_capture_open,	.close =	snd_sonicvibes_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_sonicvibes_hw_params,	.hw_free =	snd_sonicvibes_hw_free,	.prepare =	snd_sonicvibes_capture_prepare,	.trigger =	snd_sonicvibes_capture_trigger,	.pointer =	snd_sonicvibes_capture_pointer,};static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm){	struct snd_pcm *pcm;	int err;	if ((err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm)) < 0)		return err;	snd_assert(pcm != NULL, return -EINVAL);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sonicvibes_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sonicvibes_capture_ops);	pcm->private_data = sonic;	pcm->info_flags = 0;	strcpy(pcm->name, "S3 SonicVibes");	sonic->pcm = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(sonic->pci), 64*1024, 128*1024);	if (rpcm)		*rpcm = pcm;	return 0;}/* *  Mixer part */#define SONICVIBES_MUX(xname, xindex) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \  .info = snd_sonicvibes_info_mux, \  .get = snd_sonicvibes_get_mux, .put = snd_sonicvibes_put_mux }static int snd_sonicvibes_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){	static char *texts[7] = {		"CD", "PCM", "Aux1", "Line", "Aux0", "Mic", "Mix"	};	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 2;	uinfo->value.enumerated.items = 7;	if (uinfo->value.enumerated.item >= 7)		uinfo->value.enumerated.item = 6;	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);	return 0;}static int snd_sonicvibes_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);		spin_lock_irq(&sonic->reg_lock);	ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1;	ucontrol->value.enumerated.item[1] = ((snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC) & SV_RECSRC_OUT) >> 5) - 1;	spin_unlock_irq(&sonic->reg_lock);	return 0;}static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);	unsigned short left, right, oval1, oval2;	int change;		if (ucontrol->value.enumerated.item[0] >= 7 ||	    ucontrol->value.enumerated.item[1] >= 7)		return -EINVAL;	left = (ucontrol->value.enumerated.item[0] + 1) << 5;	right = (ucontrol->value.enumerated.item[1] + 1) << 5;	spin_lock_irq(&sonic->reg_lock);	oval1 = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC);	oval2 = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC);	left = (oval1 & ~SV_RECSRC_OUT) | left;	right = (oval2 & ~SV_RECSRC_OUT) | right;	change = left != oval1 || right != oval2;	snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ADC, left);	snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ADC, right);	spin_unlock_irq(&sonic->reg_lock);	return change;}#define SONICVIBES_SINGLE(xname, xindex, reg, shift, mask, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \  .info = snd_sonicvibes_info_single, \  .get = snd_sonicvibes_get_single, .put = snd_sonicvibes_put_single, \  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }static int snd_sonicvibes_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){	int mask = (kcontrol->private_value >> 16) & 0xff;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}static int snd_sonicvibes_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;		spin_lock_irq(&sonic->reg_lock);	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask;	spin_unlock_irq(&sonic->reg_lock);	if (invert)		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];	return 0;}static int snd_sonicvibes_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 8) & 0xff;	int mask = (kcontrol->private_value >> 16) & 0xff;	int invert = (kcontrol->private_value >> 24) & 0xff;	int change;	unsigned short val, oval;		val = (ucontrol->value.integer.value[0] & mask);	if (invert)		val = mask - val;	val <<= shift;	spin_lock_irq(&sonic->reg_lock);	oval = snd_sonicvibes_in1(sonic, reg);	val = (oval & ~(mask << shift)) | val;	change = val != oval;	snd_sonicvibes_out1(sonic, reg, val);	spin_unlock_irq(&sonic->reg_lock);	return change;}#define SONICVIBES_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \  .info = snd_sonicvibes_info_double, \  .get = snd_sonicvibes_get_double, .put = snd_sonicvibes_put_double, \  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }static int snd_sonicvibes_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){	int mask = (kcontrol->private_value >> 24) & 0xff;	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = mask;	return 0;}static int snd_sonicvibes_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);	int left_reg = kcontrol->private_value & 0xff;	int right_reg = (kcontrol->private_value >> 8) & 0xff;	int shift_left = (kcontrol->private_value >> 16) & 0x07;	int shift_right = (kcontrol->private_value >> 19) & 0x07;	int mask = (kcontrol->private_value >> 24) & 0xff;	int invert = (kcontrol->private_value >> 22) & 1;		spin_lock_irq(&sonic->reg_lock);	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask;	ucontrol->value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >> shift_right) & mask;	spin_unlock_irq(&sonic->reg_lock);	if (invert) {		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];	}	return 0;}static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);	int left_reg = kcontrol->private_value & 0xff;	int right_reg = (kcontrol->private_value >> 8) & 0xff;	int shift_left = (kcontrol->private_value >> 16) & 0x07;	int shift_right = (kcontrol->private_value >> 19) & 0x07;	int mask = (kcontrol->private_value >> 24) & 0xff;	int invert = (kcontrol->private_value >> 22) & 1;	int change;	unsigned short val1, val2, oval1, oval2;		val1 = ucontrol->value.integer.value[0] & mask;	val2 = ucontrol->value.integer.value[1] & mask;	if (invert) {		val1 = mask - val1;		val2 = mask - val2;	}	val1 <<= shift_left;	val2 <<= shift_right;	spin_lock_irq(&sonic->reg_lock);	oval1 = snd_sonicvibes_in1(sonic, left_reg);	oval2 = snd_sonicvibes_in1(sonic, right_reg);	val1 = (oval1 & ~(mask << shift_left)) | val1;	val2 = (oval2 & ~(mask << shift_right)) | val2;	change = val1 != oval1 || val2 != oval2;	snd_sonicvibes_out1(sonic, left_reg, val1);	snd_sonicvibes_out1(sonic, right_reg, val2);	spin_unlock_irq(&sonic->reg_lock);	return change;}static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = {SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),SONICVIBES_DOUBLE("CD Playback Switch", 0, SV_IREG_LEFT_CD, SV_IREG_RIGHT_CD, 7, 7, 1, 1),SONICVIBES_DOUBLE("CD Playback Volume", 0, SV_IREG_LEFT_CD, SV_IREG_RIGHT_CD, 0, 0, 31, 1),SONICVIBES_DOUBLE("Line Playback Switch", 0, SV_IREG_LEFT_LINE, SV_IREG_RIGHT_LINE, 7, 7, 1, 1),SONICVIBES_DOUBLE("Line Playback Volume", 0, SV_IREG_LEFT_LINE, SV_IREG_RIGHT_LINE, 0, 0, 31, 1),SONICVIBES_SINGLE("Mic Playback Switch", 0, SV_IREG_MIC, 7, 1, 1),SONICVIBES_SINGLE("Mic Playback Volume", 0, SV_IREG_MIC, 0, 15, 1),SONICVIBES_SINGLE("Mic Boost", 0, SV_IREG_LEFT_ADC, 4, 1, 0),SONICVIBES_DOUBLE("Synth Playback Switch", 0, SV_IREG_LEFT_SYNTH, SV_IREG_RIGHT_SYNTH, 7, 7, 1, 1),SONICVIBES_DOUBLE("Synth Playback Volume", 0, SV_IREG_LEFT_SYNTH, SV_IREG_RIGHT_SYNTH, 0, 0, 31, 1),SONICVIBES_DOUBLE("Aux Playback Switch", 1, SV_IREG_LEFT_AUX2, SV_IREG_RIGHT_AUX2, 7, 7, 1, 1),SONICVIBES_DOUBLE("Aux Playback Volume", 1, SV_IREG_LEFT_AUX2, SV_IREG_RIGHT_AUX2, 0, 0, 31, 1),SONICVIBES_DOUBLE("Master Playback Switch", 0, SV_IREG_LEFT_ANALOG, SV_IREG_RIGHT_ANALOG, 7, 7, 1, 1),SONICVIBES_DOUBLE("Master Playback Volume", 0, SV_IREG_LEFT_ANALOG, SV_IREG_RIGHT_ANALOG, 0, 0, 31, 1),SONICVIBES_DOUBLE("PCM Playback Switch", 0, SV_IREG_LEFT_PCM, SV_IREG_RIGHT_PCM, 7, 7, 1, 1),SONICVIBES_DOUBLE("PCM Playback Volume", 0, SV_IREG_LEFT_PCM, SV_IREG_RIGHT_PCM, 0, 0, 63, 1),SONICVIBES_SINGLE("Loopback Capture Switch", 0, SV_IREG_ADC_OUTPUT_CTRL, 0, 1, 0),SONICVIBES_SINGLE("Loopback Capture Volume", 0, SV_IREG_ADC_OUTPUT_CTRL, 2, 63, 1),SONICVIBES_MUX("Capture Source", 0)};static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol){	struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);	sonic->master_mute = NULL;	sonic->master_volume = NULL;}static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic){	struct snd_card *card;	struct snd_kcontrol *kctl;	unsigned int idx;	int err;	snd_assert(sonic != NULL && sonic->card != NULL, return -EINVAL);	card = sonic->card;	strcpy(card->mixername, "S3 SonicVibes");	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) {		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic))) < 0)			return err;		switch (idx) {		case 0:		case 1: kctl->private_free = snd_sonicvibes_master_free; break;		}	}	return 0;}/* */static void snd_sonicvibes_proc_read(struct snd_info_entry *entry, 				     struct snd_info_buffer *buffer){	struct sonicvibes *sonic = entry->private_data;	unsigned char tmp;	tmp = sonic->srs_space & 0x0f;	snd_iprintf(buffer, "SRS 3D           : %s\n",		    sonic->srs_space & 0x80 ? "off" : "on");	snd_iprintf(buffer, "SRS Space        : %s\n",		    tmp == 0x00 ? "100%" :		    tmp == 0x01 ? "75%" :		    tmp == 0x02 ? "50%" :		    tmp == 0x03 ? "25%" : "0%");	tmp = sonic->srs_center & 0x0f;	snd_iprintf(buffer, "SRS Center       : %s\n",		    tmp == 0x00 ? "100%" :		    tmp == 0x01 ? "75%" :		    tmp == 0x02 ? "50%" :		    tmp == 0x03 ? "25%" : "0%");	tmp = sonic->wave_source & 0x03;	snd_iprintf(buffer, "WaveTable Source : %s\n",		    tmp == 0x00 ? "on-board ROM" :		    tmp == 0x01 ? "PCI bus" : "on-board ROM + PCI bus");	tmp = sonic->mpu_switch;	snd_iprintf(buffer, "Onboard synth    : %s\n", tmp & 0x01 ? "on" : "off");

⌨️ 快捷键说明

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