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

📄 sb_mixer.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (c) by Jaroslav Kysela <perex@suse.cz> *  Routines for Sound Blaster mixer control * * *   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 * */#define __NO_VERSION__#include <sound/driver.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/time.h>#include <sound/core.h>#include <sound/sb.h>#include <sound/control.h>#define chip_t sb_t#undef IO_DEBUGvoid snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data){	outb(reg, SBP(chip, MIXER_ADDR));	udelay(10);	outb(data, SBP(chip, MIXER_DATA));	udelay(10);#ifdef IO_DEBUG	snd_printk("mixer_write 0x%x 0x%x\n", reg, data);#endif}unsigned char snd_sbmixer_read(sb_t *chip, unsigned char reg){	unsigned char result;	outb(reg, SBP(chip, MIXER_ADDR));	udelay(10);	result = inb(SBP(chip, MIXER_DATA));	udelay(10);#ifdef IO_DEBUG	snd_printk("mixer_read 0x%x 0x%x\n", reg, result);#endif	return result;}/* * Single channel mixer element */#define SB_SINGLE(xname, reg, shift, mask) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, \  name: xname, \  info: snd_sbmixer_info_single, \  get: snd_sbmixer_get_single, put: snd_sbmixer_put_single, \  private_value: reg | (shift << 16) | (mask << 24) }static int snd_sbmixer_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	int mask = (kcontrol->private_value >> 24) & 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_sbmixer_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	sb_t *sb = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 16) & 0xff;	int mask = (kcontrol->private_value >> 24) & 0xff;	unsigned char val;	spin_lock_irqsave(&sb->mixer_lock, flags);	val = (snd_sbmixer_read(sb, reg) >> shift) & mask;	spin_unlock_irqrestore(&sb->mixer_lock, flags);	ucontrol->value.integer.value[0] = val;	return 0;}static int snd_sbmixer_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	sb_t *sb = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int reg = kcontrol->private_value & 0xff;	int shift = (kcontrol->private_value >> 16) & 0x07;	int mask = (kcontrol->private_value >> 24) & 0xff;	int change;	unsigned char val, oval;	val = (ucontrol->value.integer.value[0] & mask) << shift;	spin_lock_irqsave(&sb->mixer_lock, flags);	oval = snd_sbmixer_read(sb, reg);	val = (oval & ~(mask << shift)) | val;	change = val != oval;	if (change)		snd_sbmixer_write(sb, reg, val);	spin_unlock_irqrestore(&sb->mixer_lock, flags);	return change;}/* * Double channel mixer element */#define SB_DOUBLE(xname, left_reg, right_reg, left_shift, right_shift, mask) \{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, \  name: xname, \  info: snd_sbmixer_info_double, \  get: snd_sbmixer_get_double, put: snd_sbmixer_put_double, \  private_value: left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) }static int snd_sbmixer_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * 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_sbmixer_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	sb_t *sb = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int left_reg = kcontrol->private_value & 0xff;	int right_reg = (kcontrol->private_value >> 8) & 0xff;	int left_shift = (kcontrol->private_value >> 16) & 0x07;	int right_shift = (kcontrol->private_value >> 19) & 0x07;	int mask = (kcontrol->private_value >> 24) & 0xff;	unsigned char left, right;	spin_lock_irqsave(&sb->mixer_lock, flags);	left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask;	right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask;	spin_unlock_irqrestore(&sb->mixer_lock, flags);	ucontrol->value.integer.value[0] = left;	ucontrol->value.integer.value[1] = right;	return 0;}static int snd_sbmixer_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	sb_t *sb = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int left_reg = kcontrol->private_value & 0xff;	int right_reg = (kcontrol->private_value >> 8) & 0xff;	int left_shift = (kcontrol->private_value >> 16) & 0x07;	int right_shift = (kcontrol->private_value >> 19) & 0x07;	int mask = (kcontrol->private_value >> 24) & 0xff;	int change;	unsigned char left, right, oleft, oright;	left = (ucontrol->value.integer.value[0] & mask) << left_shift;	right = (ucontrol->value.integer.value[1] & mask) << right_shift;	spin_lock_irqsave(&sb->mixer_lock, flags);	if (left_reg == right_reg) {		oleft = snd_sbmixer_read(sb, left_reg);		left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right;		change = left != oleft;		if (change)			snd_sbmixer_write(sb, left_reg, left);	} else {		oleft = snd_sbmixer_read(sb, left_reg);		oright = snd_sbmixer_read(sb, right_reg);		left = (oleft & ~(mask << left_shift)) | left;		right = (oright & ~(mask << right_shift)) | right;		change = left != oleft || right != oright;		if (change) {			snd_sbmixer_write(sb, left_reg, left);			snd_sbmixer_write(sb, right_reg, right);		}	}	spin_unlock_irqrestore(&sb->mixer_lock, flags);	return change;}/* * SBPRO input multiplexer */static int snd_sb8mixer_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	static char *texts[3] = {		"Mic", "CD", "Line"	};	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 3;	if (uinfo->value.enumerated.item > 2)		uinfo->value.enumerated.item = 2;	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);	return 0;}static int snd_sb8mixer_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	sb_t *sb = snd_kcontrol_chip(kcontrol);	unsigned long flags;	unsigned char oval;		spin_lock_irqsave(&sb->mixer_lock, flags);	oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);	spin_unlock_irqrestore(&sb->mixer_lock, flags);	switch ((oval >> 0x01) & 0x03) {	case SB_DSP_MIXS_CD:		ucontrol->value.enumerated.item[0] = 1;		break;	case SB_DSP_MIXS_LINE:		ucontrol->value.enumerated.item[0] = 2;		break;	default:		ucontrol->value.enumerated.item[0] = 0;		break;	}	return 0;}static int snd_sb8mixer_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	sb_t *sb = snd_kcontrol_chip(kcontrol);	unsigned long flags;	int change;	unsigned char nval, oval;		if (ucontrol->value.enumerated.item[0] > 2)		return -EINVAL;	switch (ucontrol->value.enumerated.item[0]) {

⌨️ 快捷键说明

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