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

📄 pcxhr_mixer.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 3 页
字号:
#define __NO_VERSION__/* * Driver for Digigram pcxhr compatible soundcards * * mixer callbacks * * Copyright (c) 2004 by Digigram <alsa@digigram.com> * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */#include <sound/driver.h>#include <linux/time.h>#include <linux/interrupt.h>#include <linux/init.h>#include <sound/core.h>#include "pcxhr.h"#include "pcxhr_hwdep.h"#include "pcxhr_core.h"#include <sound/control.h>#include <sound/asoundef.h>#include "pcxhr_mixer.h"#define PCXHR_ANALOG_CAPTURE_LEVEL_MIN   0	/* -96.0 dB */#define PCXHR_ANALOG_CAPTURE_LEVEL_MAX   255	/* +31.5 dB */#define PCXHR_ANALOG_CAPTURE_ZERO_LEVEL  224	/* +16.0 dB ( +31.5 dB - fix level +15.5 dB ) */#define PCXHR_ANALOG_PLAYBACK_LEVEL_MIN  0	/* -128.0 dB */#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX  128	/*    0.0 dB */#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104	/*  -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel){	int err, vol;	struct pcxhr_rmh rmh;	pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);	if (is_capture) {		rmh.cmd[0] |= IO_NUM_REG_IN_ANA_LEVEL;		rmh.cmd[2] = chip->analog_capture_volume[channel];	} else {		rmh.cmd[0] |= IO_NUM_REG_OUT_ANA_LEVEL;		if (chip->analog_playback_active[channel])			vol = chip->analog_playback_volume[channel];		else			vol = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN;		rmh.cmd[2] = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX - vol;	/* playback analog levels are inversed */	}	rmh.cmd[1]  = 1 << ((2 * chip->chip_idx) + channel);	/* audio mask */	rmh.cmd_len = 3;	err = pcxhr_send_msg(chip->mgr, &rmh);	if (err < 0) {		snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d) "			   "is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err);		return -EINVAL;	}	return 0;}/* * analog level control */static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,				 struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	if (kcontrol->private_value == 0) {	/* playback */		uinfo->value.integer.min = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN;	/* -128 dB */		uinfo->value.integer.max = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX;	/* 0 dB */	} else {				/* capture */		uinfo->value.integer.min = PCXHR_ANALOG_CAPTURE_LEVEL_MIN;	/* -96 dB */		uinfo->value.integer.max = PCXHR_ANALOG_CAPTURE_LEVEL_MAX;	/* 31.5 dB */	}	return 0;}static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,				struct snd_ctl_elem_value *ucontrol){	struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);	down(&chip->mgr->mixer_mutex);	if (kcontrol->private_value == 0) {	/* playback */		ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];		ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];	} else {				/* capture */		ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];		ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];	}	up(&chip->mgr->mixer_mutex);	return 0;}static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,				struct snd_ctl_elem_value *ucontrol){	struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);	int changed = 0;	int is_capture, i;	down(&chip->mgr->mixer_mutex);	is_capture = (kcontrol->private_value != 0);	for (i = 0; i < 2; i++) {		int  new_volume = ucontrol->value.integer.value[i];		int* stored_volume = is_capture ? &chip->analog_capture_volume[i] :			&chip->analog_playback_volume[i];		if (*stored_volume != new_volume) {			*stored_volume = new_volume;			changed = 1;			pcxhr_update_analog_audio_level(chip, is_capture, i);		}	}	up(&chip->mgr->mixer_mutex);	return changed;}static struct snd_kcontrol_new pcxhr_control_analog_level = {	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,	/* name will be filled later */	.info =		pcxhr_analog_vol_info,	.get =		pcxhr_analog_vol_get,	.put =		pcxhr_analog_vol_put,};/* shared */static int pcxhr_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 1;	return 0;}static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,			      struct snd_ctl_elem_value *ucontrol){	struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);	down(&chip->mgr->mixer_mutex);	ucontrol->value.integer.value[0] = chip->analog_playback_active[0];	ucontrol->value.integer.value[1] = chip->analog_playback_active[1];	up(&chip->mgr->mixer_mutex);	return 0;}static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,			      struct snd_ctl_elem_value *ucontrol){	struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);	int i, changed = 0;	down(&chip->mgr->mixer_mutex);	for(i = 0; i < 2; i++) {		if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) {			chip->analog_playback_active[i] = ucontrol->value.integer.value[i];			changed = 1;			pcxhr_update_analog_audio_level(chip, 0, i);	/* update playback levels */		}	}	up(&chip->mgr->mixer_mutex);	return changed;}static struct snd_kcontrol_new pcxhr_control_output_switch = {	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,	.name =		"Master Playback Switch",	.info =		pcxhr_sw_info,		/* shared */	.get =		pcxhr_audio_sw_get,	.put =		pcxhr_audio_sw_put};#define PCXHR_DIGITAL_LEVEL_MIN		0x000	/* -110 dB */#define PCXHR_DIGITAL_LEVEL_MAX		0x1ff	/* +18 dB */#define PCXHR_DIGITAL_ZERO_LEVEL	0x1b7	/*  0 dB */#define MORE_THAN_ONE_STREAM_LEVEL	0x000001#define VALID_STREAM_PAN_LEVEL_MASK	0x800000#define VALID_STREAM_LEVEL_MASK		0x400000#define VALID_STREAM_LEVEL_1_MASK	0x200000#define VALID_STREAM_LEVEL_2_MASK	0x100000static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx){	int err;	struct pcxhr_rmh rmh;	struct pcxhr_pipe *pipe = &chip->playback_pipe;	int left, right;	if (chip->digital_playback_active[idx][0])		left = chip->digital_playback_volume[idx][0];	else		left = PCXHR_DIGITAL_LEVEL_MIN;	if (chip->digital_playback_active[idx][1])		right = chip->digital_playback_volume[idx][1];	else		right = PCXHR_DIGITAL_LEVEL_MIN;	pcxhr_init_rmh(&rmh, CMD_STREAM_OUT_LEVEL_ADJUST);	/* add pipe and stream mask */	pcxhr_set_pipe_cmd_params(&rmh, 0, pipe->first_audio, 0, 1<<idx);	/* volume left->left / right->right panoramic level */	rmh.cmd[0] |= MORE_THAN_ONE_STREAM_LEVEL;	rmh.cmd[2]  = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_1_MASK;	rmh.cmd[2] |= (left << 10);	rmh.cmd[3]  = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_2_MASK;	rmh.cmd[3] |= right;	rmh.cmd_len = 4;	err = pcxhr_send_msg(chip->mgr, &rmh);	if (err < 0) {		snd_printk(KERN_DEBUG "error update_playback_stream_level "			   "card(%d) err(%x)\n", chip->chip_idx, err);		return -EINVAL;	}	return 0;}#define AUDIO_IO_HAS_MUTE_LEVEL		0x400000#define AUDIO_IO_HAS_MUTE_MONITOR_1	0x200000#define VALID_AUDIO_IO_DIGITAL_LEVEL	0x000001#define VALID_AUDIO_IO_MONITOR_LEVEL	0x000002#define VALID_AUDIO_IO_MUTE_LEVEL	0x000004#define VALID_AUDIO_IO_MUTE_MONITOR_1	0x000008static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel){	int err;	struct pcxhr_rmh rmh;	struct pcxhr_pipe *pipe;	if (capture)		pipe = &chip->capture_pipe[0];	else		pipe = &chip->playback_pipe;	pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);	/* add channel mask */	pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio));	/* TODO : if mask (3 << pipe->first_audio) is used, left and right channel	 * will be programmed to the same params	 */	if (capture) {		rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;		/* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */		rmh.cmd[2] = chip->digital_capture_volume[channel];	} else {		rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1;		/* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet		 * handled (playback pipe level)		 */		rmh.cmd[2] = chip->monitoring_volume[channel] << 10;		if (chip->monitoring_active[channel] == 0)			rmh.cmd[2] |= AUDIO_IO_HAS_MUTE_MONITOR_1;	}	rmh.cmd_len = 3;	err = pcxhr_send_msg(chip->mgr, &rmh);	if(err<0) {		snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n",			   chip->chip_idx, err);		return -EINVAL;	}	return 0;}/* shared */static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol,				  struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = PCXHR_DIGITAL_LEVEL_MIN;   /* -109.5 dB */	uinfo->value.integer.max = PCXHR_DIGITAL_LEVEL_MAX;   /*   18.0 dB */	return 0;}static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,			     struct snd_ctl_elem_value *ucontrol){	struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);		/* index */	int *stored_volume;	int is_capture = kcontrol->private_value;	down(&chip->mgr->mixer_mutex);	if (is_capture)		stored_volume = chip->digital_capture_volume;		/* digital capture */	else		stored_volume = chip->digital_playback_volume[idx];	/* digital playback */	ucontrol->value.integer.value[0] = stored_volume[0];	ucontrol->value.integer.value[1] = stored_volume[1];	up(&chip->mgr->mixer_mutex);	return 0;}static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,			     struct snd_ctl_elem_value *ucontrol){	struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);	int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);		/* index */	int changed = 0;	int is_capture = kcontrol->private_value;	int *stored_volume;	int i;	down(&chip->mgr->mixer_mutex);	if (is_capture)		stored_volume = chip->digital_capture_volume;		/* digital capture */	else		stored_volume = chip->digital_playback_volume[idx];	/* digital playback */	for (i = 0; i < 2; i++) {		if (stored_volume[i] != ucontrol->value.integer.value[i]) {			stored_volume[i] = ucontrol->value.integer.value[i];			changed = 1;			if (is_capture)	/* update capture volume */				pcxhr_update_audio_pipe_level(chip, 1, i);		}	}	if (! is_capture && changed)		pcxhr_update_playback_stream_level(chip, idx);	/* update playback volume */	up(&chip->mgr->mixer_mutex);	return changed;}

⌨️ 快捷键说明

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