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

📄 emumixer.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>, *                   Takashi Iwai <tiwai@suse.de> *                   Creative Labs, Inc. *  Routines for control of EMU10K1 chips / mixer routines *  Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> * *  Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> *  	Added EMU 1010 support. * *  BUGS: *    -- * *  TODO: *    -- * *   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/init.h>#include <sound/core.h>#include <sound/emu10k1.h>#include <linux/delay.h>#include <sound/tlv.h>#include "p17v.h"#define AC97_ID_STAC9758	0x83847658static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;	uinfo->count = 1;	return 0;}static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,                                 struct snd_ctl_elem_value *ucontrol){	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);	unsigned long flags;	/* Limit: emu->spdif_bits */	if (idx >= 3)		return -EINVAL;	spin_lock_irqsave(&emu->reg_lock, flags);	ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;	ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;	ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;	ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;	spin_unlock_irqrestore(&emu->reg_lock, flags);	return 0;}static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,				      struct snd_ctl_elem_value *ucontrol){	ucontrol->value.iec958.status[0] = 0xff;	ucontrol->value.iec958.status[1] = 0xff;	ucontrol->value.iec958.status[2] = 0xff;	ucontrol->value.iec958.status[3] = 0xff;	return 0;}/* * Items labels in enum mixer controls assigning source data to * each destination */static char *emu1010_src_texts[] = { 	"Silence",	"Dock Mic A",	"Dock Mic B",	"Dock ADC1 Left",	"Dock ADC1 Right",	"Dock ADC2 Left",	"Dock ADC2 Right",	"Dock ADC3 Left",	"Dock ADC3 Right",	"0202 ADC Left",	"0202 ADC Right",	"0202 SPDIF Left",	"0202 SPDIF Right",	"ADAT 0",	"ADAT 1",	"ADAT 2",	"ADAT 3",	"ADAT 4",	"ADAT 5",	"ADAT 6",	"ADAT 7",	"DSP 0",	"DSP 1",	"DSP 2",	"DSP 3",	"DSP 4",	"DSP 5",	"DSP 6",	"DSP 7",	"DSP 8",	"DSP 9",	"DSP 10",	"DSP 11",	"DSP 12",	"DSP 13",	"DSP 14",	"DSP 15",	"DSP 16",	"DSP 17",	"DSP 18",	"DSP 19",	"DSP 20",	"DSP 21",	"DSP 22",	"DSP 23",	"DSP 24",	"DSP 25",	"DSP 26",	"DSP 27",	"DSP 28",	"DSP 29",	"DSP 30",	"DSP 31",};/* * List of data sources available for each destination */static unsigned int emu1010_src_regs[] = {	EMU_SRC_SILENCE,/* 0 */	EMU_SRC_DOCK_MIC_A1, /* 1 */	EMU_SRC_DOCK_MIC_B1, /* 2 */	EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */	EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */	EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */	EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */	EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */	EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */	EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */	EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */	EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */	EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */	EMU_SRC_HANA_ADAT, /* 13 */	EMU_SRC_HANA_ADAT+1, /* 14 */	EMU_SRC_HANA_ADAT+2, /* 15 */	EMU_SRC_HANA_ADAT+3, /* 16 */	EMU_SRC_HANA_ADAT+4, /* 17 */	EMU_SRC_HANA_ADAT+5, /* 18 */	EMU_SRC_HANA_ADAT+6, /* 19 */	EMU_SRC_HANA_ADAT+7, /* 20 */	EMU_SRC_ALICE_EMU32A, /* 21 */	EMU_SRC_ALICE_EMU32A+1, /* 22 */	EMU_SRC_ALICE_EMU32A+2, /* 23 */	EMU_SRC_ALICE_EMU32A+3, /* 24 */	EMU_SRC_ALICE_EMU32A+4, /* 25 */	EMU_SRC_ALICE_EMU32A+5, /* 26 */	EMU_SRC_ALICE_EMU32A+6, /* 27 */	EMU_SRC_ALICE_EMU32A+7, /* 28 */	EMU_SRC_ALICE_EMU32A+8, /* 29 */	EMU_SRC_ALICE_EMU32A+9, /* 30 */	EMU_SRC_ALICE_EMU32A+0xa, /* 31 */	EMU_SRC_ALICE_EMU32A+0xb, /* 32 */	EMU_SRC_ALICE_EMU32A+0xc, /* 33 */	EMU_SRC_ALICE_EMU32A+0xd, /* 34 */	EMU_SRC_ALICE_EMU32A+0xe, /* 35 */	EMU_SRC_ALICE_EMU32A+0xf, /* 36 */	EMU_SRC_ALICE_EMU32B, /* 37 */	EMU_SRC_ALICE_EMU32B+1, /* 38 */	EMU_SRC_ALICE_EMU32B+2, /* 39 */	EMU_SRC_ALICE_EMU32B+3, /* 40 */	EMU_SRC_ALICE_EMU32B+4, /* 41 */	EMU_SRC_ALICE_EMU32B+5, /* 42 */	EMU_SRC_ALICE_EMU32B+6, /* 43 */	EMU_SRC_ALICE_EMU32B+7, /* 44 */	EMU_SRC_ALICE_EMU32B+8, /* 45 */	EMU_SRC_ALICE_EMU32B+9, /* 46 */	EMU_SRC_ALICE_EMU32B+0xa, /* 47 */	EMU_SRC_ALICE_EMU32B+0xb, /* 48 */	EMU_SRC_ALICE_EMU32B+0xc, /* 49 */	EMU_SRC_ALICE_EMU32B+0xd, /* 50 */	EMU_SRC_ALICE_EMU32B+0xe, /* 51 */	EMU_SRC_ALICE_EMU32B+0xf, /* 52 */};/* * Data destinations - physical EMU outputs. * Each destination has an enum mixer control to choose a data source */static unsigned int emu1010_output_dst[] = {	EMU_DST_DOCK_DAC1_LEFT1, /* 0 */	EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */	EMU_DST_DOCK_DAC2_LEFT1, /* 2 */	EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */	EMU_DST_DOCK_DAC3_LEFT1, /* 4 */	EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */	EMU_DST_DOCK_DAC4_LEFT1, /* 6 */	EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */	EMU_DST_DOCK_PHONES_LEFT1, /* 8 */	EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */	EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */	EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */	EMU_DST_HANA_SPDIF_LEFT1, /* 12 */	EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */	EMU_DST_HAMOA_DAC_LEFT1, /* 14 */	EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */	EMU_DST_HANA_ADAT, /* 16 */	EMU_DST_HANA_ADAT+1, /* 17 */	EMU_DST_HANA_ADAT+2, /* 18 */	EMU_DST_HANA_ADAT+3, /* 19 */	EMU_DST_HANA_ADAT+4, /* 20 */	EMU_DST_HANA_ADAT+5, /* 21 */	EMU_DST_HANA_ADAT+6, /* 22 */	EMU_DST_HANA_ADAT+7, /* 23 */};/* * Data destinations - HANA outputs going to Alice2 (audigy) for *   capture (EMU32 + I2S links) * Each destination has an enum mixer control to choose a data source */static unsigned int emu1010_input_dst[] = {	EMU_DST_ALICE2_EMU32_0,	EMU_DST_ALICE2_EMU32_1,	EMU_DST_ALICE2_EMU32_2,	EMU_DST_ALICE2_EMU32_3,	EMU_DST_ALICE2_EMU32_4,	EMU_DST_ALICE2_EMU32_5,	EMU_DST_ALICE2_EMU32_6,	EMU_DST_ALICE2_EMU32_7,	EMU_DST_ALICE2_EMU32_8,	EMU_DST_ALICE2_EMU32_9,	EMU_DST_ALICE2_EMU32_A,	EMU_DST_ALICE2_EMU32_B,	EMU_DST_ALICE2_EMU32_C,	EMU_DST_ALICE2_EMU32_D,	EMU_DST_ALICE2_EMU32_E,	EMU_DST_ALICE2_EMU32_F,	EMU_DST_ALICE_I2S0_LEFT,	EMU_DST_ALICE_I2S0_RIGHT,	EMU_DST_ALICE_I2S1_LEFT,	EMU_DST_ALICE_I2S1_RIGHT,	EMU_DST_ALICE_I2S2_LEFT,	EMU_DST_ALICE_I2S2_RIGHT,};static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 53;	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;	strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);	return 0;}static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,                                 struct snd_ctl_elem_value *ucontrol){	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);	unsigned int channel;	channel = (kcontrol->private_value) & 0xff;	/* Limit: emu1010_output_dst, emu->emu1010.output_source */	if (channel >= 24)		return -EINVAL;	ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];	return 0;}static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,                                 struct snd_ctl_elem_value *ucontrol){	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);	int change = 0;	unsigned int val;	unsigned int channel;	val = ucontrol->value.enumerated.item[0];	if (val >= 53)		return -EINVAL;	channel = (kcontrol->private_value) & 0xff;	/* Limit: emu1010_output_dst, emu->emu1010.output_source */	if (channel >= 24)		return -EINVAL;	if (emu->emu1010.output_source[channel] != val) {		emu->emu1010.output_source[channel] = val;		change = 1;		snd_emu1010_fpga_link_dst_src_write(emu,			emu1010_output_dst[channel], emu1010_src_regs[val]);	}	return change;}static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,                                 struct snd_ctl_elem_value *ucontrol){	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);	unsigned int channel;	channel = (kcontrol->private_value) & 0xff;	/* Limit: emu1010_input_dst, emu->emu1010.input_source */	if (channel >= 22)		return -EINVAL;	ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];	return 0;}static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,                                 struct snd_ctl_elem_value *ucontrol){	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);	int change = 0;	unsigned int val;	unsigned int channel;	val = ucontrol->value.enumerated.item[0];	if (val >= 53)		return -EINVAL;	channel = (kcontrol->private_value) & 0xff;	/* Limit: emu1010_input_dst, emu->emu1010.input_source */	if (channel >= 22)		return -EINVAL;	if (emu->emu1010.input_source[channel] != val) {		emu->emu1010.input_source[channel] = val;		change = 1;		snd_emu1010_fpga_link_dst_src_write(emu,			emu1010_input_dst[channel], emu1010_src_regs[val]);	}	return change;}#define EMU1010_SOURCE_OUTPUT(xname,chid) \{								\	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,		\	.info =  snd_emu1010_input_output_source_info,		\	.get =   snd_emu1010_output_source_get,			\	.put =   snd_emu1010_output_source_put,			\	.private_value = chid					\}static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {	EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),	EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),	EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),	EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),	EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),	EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),	EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),	EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),	EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),	EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),	EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),	EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),	EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),	EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),	EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),	EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),	EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),	EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),	EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),	EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),	EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),	EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),	EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),	EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),};#define EMU1010_SOURCE_INPUT(xname,chid) \{								\	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,		\	.info =  snd_emu1010_input_output_source_info,		\	.get =   snd_emu1010_input_source_get,			\	.put =   snd_emu1010_input_source_put,			\	.private_value = chid					\}static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {	EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),	EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),	EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),	EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),	EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),	EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),	EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),	EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),	EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),	EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),	EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),	EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),	EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),	EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),	EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),	EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),	EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),	EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),	EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),	EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),	EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),	EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),};#define snd_emu1010_adc_pads_info	snd_ctl_boolean_mono_infostatic int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);	unsigned int mask = kcontrol->private_value & 0xff;	ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;	return 0;}static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){	struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);	unsigned int mask = kcontrol->private_value & 0xff;	unsigned int val, cache;	val = ucontrol->value.integer.value[0];	cache = emu->emu1010.adc_pads;	if (val == 1) 		cache = cache | mask;	else		cache = cache & ~mask;	if (cache != emu->emu1010.adc_pads) {		snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );	        emu->emu1010.adc_pads = cache;	}	return 0;}#define EMU1010_ADC_PADS(xname,chid) \{								\	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,		\	.info =  snd_emu1010_adc_pads_info,			\	.get =   snd_emu1010_adc_pads_get,			\	.put =   snd_emu1010_adc_pads_put,			\	.private_value = chid					\}static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {	EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),	EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),

⌨️ 快捷键说明

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