Browse Source

ALSA: hda/ca0132: Add new definitions and structs for DSP

This patch adds definitions and structs used for configuring DSP effects,
virtual nodes, effect tuning controls, and mixer control helpers.
The effect structs are also initialized.

Signed-off-by: Ian Minett <ian_minett@creativelabs.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Ian Minett 12 years ago
parent
commit
ef6b2eada3
1 changed files with 442 additions and 3 deletions
  1. 442 3
      sound/pci/hda/patch_ca0132.c

+ 442 - 3
sound/pci/hda/patch_ca0132.c

@@ -35,6 +35,18 @@
 
 #include "ca0132_regs.h"
 
+/* Enable this to see controls for tuning purpose. */
+/*#define ENABLE_TUNING_CONTROLS*/
+
+#define FLOAT_ZERO	0x00000000
+#define FLOAT_ONE	0x3f800000
+#define FLOAT_TWO	0x40000000
+#define FLOAT_MINUS_5	0xc0a00000
+
+#define UNSOL_TAG_HP	0x10
+#define UNSOL_TAG_AMIC1	0x12
+#define UNSOL_TAG_DSP	0x16
+
 #define DSP_DMA_WRITE_BUFLEN_INIT (1UL<<18)
 #define DSP_DMA_WRITE_BUFLEN_OVLY (1UL<<15)
 
@@ -43,7 +55,8 @@
 #define DMA_OVERLAY_FRAME_SIZE_NWORDS		2
 
 #define MASTERCONTROL				0x80
-#define MASTERCONTROL_ALLOC_DMA_CHAN		9
+#define MASTERCONTROL_ALLOC_DMA_CHAN		10
+#define MASTERCONTROL_QUERY_SPEAKER_EQ_ADDRESS	60
 
 #define WIDGET_CHIP_CTRL      0x15
 #define WIDGET_DSP_CTRL       0x16
@@ -63,6 +76,394 @@
 
 MODULE_FIRMWARE(EFX_FILE);
 
+static char *dirstr[2] = { "Playback", "Capture" };
+
+enum {
+	SPEAKER_OUT,
+	HEADPHONE_OUT
+};
+
+enum {
+	DIGITAL_MIC,
+	LINE_MIC_IN
+};
+
+enum {
+#define VNODE_START_NID    0x80
+	VNID_SPK = VNODE_START_NID,			/* Speaker vnid */
+	VNID_MIC,
+	VNID_HP_SEL,
+	VNID_AMIC1_SEL,
+	VNID_HP_ASEL,
+	VNID_AMIC1_ASEL,
+	VNODE_END_NID,
+#define VNODES_COUNT  (VNODE_END_NID - VNODE_START_NID)
+
+#define EFFECT_START_NID    0x90
+#define OUT_EFFECT_START_NID    EFFECT_START_NID
+	SURROUND = OUT_EFFECT_START_NID,
+	CRYSTALIZER,
+	DIALOG_PLUS,
+	SMART_VOLUME,
+	X_BASS,
+	EQUALIZER,
+	OUT_EFFECT_END_NID,
+#define OUT_EFFECTS_COUNT  (OUT_EFFECT_END_NID - OUT_EFFECT_START_NID)
+
+#define IN_EFFECT_START_NID  OUT_EFFECT_END_NID
+	ECHO_CANCELLATION = IN_EFFECT_START_NID,
+	VOICE_FOCUS,
+	MIC_SVM,
+	NOISE_REDUCTION,
+	IN_EFFECT_END_NID,
+#define IN_EFFECTS_COUNT  (IN_EFFECT_END_NID - IN_EFFECT_START_NID)
+
+	VOICEFX = IN_EFFECT_END_NID,
+	PLAY_ENHANCEMENT,
+	CRYSTAL_VOICE,
+	EFFECT_END_NID
+#define EFFECTS_COUNT  (EFFECT_END_NID - EFFECT_START_NID)
+};
+
+/* Effects values size*/
+#define EFFECT_VALS_MAX_COUNT 12
+
+struct ct_effect {
+	char name[44];
+	hda_nid_t nid;
+	int mid; /*effect module ID*/
+	int reqs[EFFECT_VALS_MAX_COUNT]; /*effect module request*/
+	int direct; /* 0:output; 1:input*/
+	int params; /* number of default non-on/off params */
+	/*effect default values, 1st is on/off. */
+	unsigned int def_vals[EFFECT_VALS_MAX_COUNT];
+};
+
+#define EFX_DIR_OUT 0
+#define EFX_DIR_IN  1
+
+static struct ct_effect ca0132_effects[EFFECTS_COUNT] = {
+	{ .name = "Surround",
+	  .nid = SURROUND,
+	  .mid = 0x96,
+	  .reqs = {0, 1},
+	  .direct = EFX_DIR_OUT,
+	  .params = 1,
+	  .def_vals = {0x3F800000, 0x3F2B851F}
+	},
+	{ .name = "Crystalizer",
+	  .nid = CRYSTALIZER,
+	  .mid = 0x96,
+	  .reqs = {7, 8},
+	  .direct = EFX_DIR_OUT,
+	  .params = 1,
+	  .def_vals = {0x3F800000, 0x3F266666}
+	},
+	{ .name = "Dialog Plus",
+	  .nid = DIALOG_PLUS,
+	  .mid = 0x96,
+	  .reqs = {2, 3},
+	  .direct = EFX_DIR_OUT,
+	  .params = 1,
+	  .def_vals = {0x00000000, 0x3F000000}
+	},
+	{ .name = "Smart Volume",
+	  .nid = SMART_VOLUME,
+	  .mid = 0x96,
+	  .reqs = {4, 5, 6},
+	  .direct = EFX_DIR_OUT,
+	  .params = 2,
+	  .def_vals = {0x3F800000, 0x3F3D70A4, 0x00000000}
+	},
+	{ .name = "X-Bass",
+	  .nid = X_BASS,
+	  .mid = 0x96,
+	  .reqs = {24, 23, 25},
+	  .direct = EFX_DIR_OUT,
+	  .params = 2,
+	  .def_vals = {0x3F800000, 0x42A00000, 0x3F000000}
+	},
+	{ .name = "Equalizer",
+	  .nid = EQUALIZER,
+	  .mid = 0x96,
+	  .reqs = {9, 10, 11, 12, 13, 14,
+			15, 16, 17, 18, 19, 20},
+	  .direct = EFX_DIR_OUT,
+	  .params = 11,
+	  .def_vals = {0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+		       0x00000000, 0x00000000, 0x00000000, 0x00000000}
+	},
+	{ .name = "Echo Cancellation",
+	  .nid = ECHO_CANCELLATION,
+	  .mid = 0x95,
+	  .reqs = {0, 1, 2, 3},
+	  .direct = EFX_DIR_IN,
+	  .params = 3,
+	  .def_vals = {0x00000000, 0x3F3A9692, 0x00000000, 0x00000000}
+	},
+	{ .name = "Voice Focus",
+	  .nid = VOICE_FOCUS,
+	  .mid = 0x95,
+	  .reqs = {6, 7, 8, 9},
+	  .direct = EFX_DIR_IN,
+	  .params = 3,
+	  .def_vals = {0x3F800000, 0x3D7DF3B6, 0x41F00000, 0x41F00000}
+	},
+	{ .name = "Mic SVM",
+	  .nid = MIC_SVM,
+	  .mid = 0x95,
+	  .reqs = {44, 45},
+	  .direct = EFX_DIR_IN,
+	  .params = 1,
+	  .def_vals = {0x00000000, 0x3F3D70A4}
+	},
+	{ .name = "Noise Reduction",
+	  .nid = NOISE_REDUCTION,
+	  .mid = 0x95,
+	  .reqs = {4, 5},
+	  .direct = EFX_DIR_IN,
+	  .params = 1,
+	  .def_vals = {0x3F800000, 0x3F000000}
+	},
+	{ .name = "VoiceFX",
+	  .nid = VOICEFX,
+	  .mid = 0x95,
+	  .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18},
+	  .direct = EFX_DIR_IN,
+	  .params = 8,
+	  .def_vals = {0x00000000, 0x43C80000, 0x44AF0000, 0x44FA0000,
+		       0x3F800000, 0x3F800000, 0x3F800000, 0x00000000,
+		       0x00000000}
+	}
+};
+
+/* Tuning controls */
+#ifdef ENABLE_TUNING_CONTROLS
+
+enum {
+#define TUNING_CTL_START_NID  0xC0
+	WEDGE_ANGLE = TUNING_CTL_START_NID,
+	SVM_LEVEL,
+	EQUALIZER_BAND_0,
+	EQUALIZER_BAND_1,
+	EQUALIZER_BAND_2,
+	EQUALIZER_BAND_3,
+	EQUALIZER_BAND_4,
+	EQUALIZER_BAND_5,
+	EQUALIZER_BAND_6,
+	EQUALIZER_BAND_7,
+	EQUALIZER_BAND_8,
+	EQUALIZER_BAND_9,
+	TUNING_CTL_END_NID
+#define TUNING_CTLS_COUNT  (TUNING_CTL_END_NID - TUNING_CTL_START_NID)
+};
+
+struct ct_tuning_ctl {
+	char name[44];
+	hda_nid_t parent_nid;
+	hda_nid_t nid;
+	int mid; /*effect module ID*/
+	int req; /*effect module request*/
+	int direct; /* 0:output; 1:input*/
+	unsigned int def_val;/*effect default values*/
+};
+
+static struct ct_tuning_ctl ca0132_tuning_ctls[] = {
+	{ .name = "Wedge Angle",
+	  .parent_nid = VOICE_FOCUS,
+	  .nid = WEDGE_ANGLE,
+	  .mid = 0x95,
+	  .req = 8,
+	  .direct = EFX_DIR_IN,
+	  .def_val = 0x41F00000
+	},
+	{ .name = "SVM Level",
+	  .parent_nid = MIC_SVM,
+	  .nid = SVM_LEVEL,
+	  .mid = 0x95,
+	  .req = 45,
+	  .direct = EFX_DIR_IN,
+	  .def_val = 0x3F3D70A4
+	},
+	{ .name = "EQ Band0",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_0,
+	  .mid = 0x96,
+	  .req = 11,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band1",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_1,
+	  .mid = 0x96,
+	  .req = 12,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band2",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_2,
+	  .mid = 0x96,
+	  .req = 13,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band3",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_3,
+	  .mid = 0x96,
+	  .req = 14,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band4",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_4,
+	  .mid = 0x96,
+	  .req = 15,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band5",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_5,
+	  .mid = 0x96,
+	  .req = 16,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band6",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_6,
+	  .mid = 0x96,
+	  .req = 17,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band7",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_7,
+	  .mid = 0x96,
+	  .req = 18,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band8",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_8,
+	  .mid = 0x96,
+	  .req = 19,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	},
+	{ .name = "EQ Band9",
+	  .parent_nid = EQUALIZER,
+	  .nid = EQUALIZER_BAND_9,
+	  .mid = 0x96,
+	  .req = 20,
+	  .direct = EFX_DIR_OUT,
+	  .def_val = 0x00000000
+	}
+};
+#endif
+
+/* Voice FX Presets */
+#define VOICEFX_MAX_PARAM_COUNT 9
+
+struct ct_voicefx {
+	char *name;
+	hda_nid_t nid;
+	int mid;
+	int reqs[VOICEFX_MAX_PARAM_COUNT]; /*effect module request*/
+};
+
+struct ct_voicefx_preset {
+	char *name; /*preset name*/
+	unsigned int vals[VOICEFX_MAX_PARAM_COUNT];
+};
+
+struct ct_voicefx ca0132_voicefx = {
+	.name = "VoiceFX Capture Switch",
+	.nid = VOICEFX,
+	.mid = 0x95,
+	.reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18}
+};
+
+struct ct_voicefx_preset ca0132_voicefx_presets[] = {
+	{ .name = "Neutral",
+	  .vals = { 0x00000000, 0x43C80000, 0x44AF0000,
+		    0x44FA0000, 0x3F800000, 0x3F800000,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Female2Male",
+	  .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
+		    0x44FA0000, 0x3F19999A, 0x3F866666,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Male2Female",
+	  .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
+		    0x450AC000, 0x4017AE14, 0x3F6B851F,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "ScrappyKid",
+	  .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
+		    0x44FA0000, 0x40400000, 0x3F28F5C3,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Elderly",
+	  .vals = { 0x3F800000, 0x44324000, 0x44BB8000,
+		    0x44E10000, 0x3FB33333, 0x3FB9999A,
+		    0x3F800000, 0x3E3A2E43, 0x00000000 }
+	},
+	{ .name = "Orc",
+	  .vals = { 0x3F800000, 0x43EA0000, 0x44A52000,
+		    0x45098000, 0x3F266666, 0x3FC00000,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Elf",
+	  .vals = { 0x3F800000, 0x43C70000, 0x44AE6000,
+		    0x45193000, 0x3F8E147B, 0x3F75C28F,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Dwarf",
+	  .vals = { 0x3F800000, 0x43930000, 0x44BEE000,
+		    0x45007000, 0x3F451EB8, 0x3F7851EC,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "AlienBrute",
+	  .vals = { 0x3F800000, 0x43BFC5AC, 0x44B28FDF,
+		    0x451F6000, 0x3F266666, 0x3FA7D945,
+		    0x3F800000, 0x3CF5C28F, 0x00000000 }
+	},
+	{ .name = "Robot",
+	  .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
+		    0x44FA0000, 0x3FB2718B, 0x3F800000,
+		    0xBC07010E, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Marine",
+	  .vals = { 0x3F800000, 0x43C20000, 0x44906000,
+		    0x44E70000, 0x3F4CCCCD, 0x3F8A3D71,
+		    0x3F0A3D71, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Emo",
+	  .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
+		    0x44FA0000, 0x3F800000, 0x3F800000,
+		    0x3E4CCCCD, 0x00000000, 0x00000000 }
+	},
+	{ .name = "DeepVoice",
+	  .vals = { 0x3F800000, 0x43A9C5AC, 0x44AA4FDF,
+		    0x44FFC000, 0x3EDBB56F, 0x3F99C4CA,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	},
+	{ .name = "Munchkin",
+	  .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
+		    0x44FA0000, 0x3F800000, 0x3F1A043C,
+		    0x3F800000, 0x00000000, 0x00000000 }
+	}
+};
+
 enum hda_cmd_vendor_io {
 	/* for DspIO node */
 	VENDOR_DSPIO_SCP_WRITE_DATA_LOW      = 0x000,
@@ -184,8 +585,16 @@ enum control_flag_id {
  * Control parameter IDs
  */
 enum control_param_id {
+	/* 0: None, 1: Mic1In*/
+	CONTROL_PARAM_VIP_SOURCE               = 1,
 	/* 0: force HDA, 1: allow DSP if HDA Spdif1Out stream is idle */
 	CONTROL_PARAM_SPDIF1_SOURCE            = 2,
+	/* Port A output stage gain setting to use when 16 Ohm output
+	 * impedance is selected*/
+	CONTROL_PARAM_PORTA_160OHM_GAIN        = 8,
+	/* Port D output stage gain setting to use when 16 Ohm output
+	 * impedance is selected*/
+	CONTROL_PARAM_PORTD_160OHM_GAIN        = 10,
 
 	/* Stream Control */
 
@@ -304,8 +713,6 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
 				    AMP_IN_UNMUTE(0));
 }
 
-static char *dirstr[2] = { "Playback", "Capture" };
-
 static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
 		       int chan, int dir)
 {
@@ -2190,6 +2597,38 @@ static bool dspload_wait_loaded(struct hda_codec *codec)
 	return false;
 }
 
+
+/*
+ * Mixer controls helpers.
+ */
+#define CA0132_CODEC_VOL_MONO(xname, nid, channel, dir) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	  .name = xname, \
+	  .subdevice = HDA_SUBDEV_AMP_FLAG, \
+	  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+			SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+			SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
+	  .info = ca0132_volume_info, \
+	  .get = ca0132_volume_get, \
+	  .put = ca0132_volume_put, \
+	  .tlv = { .c = ca0132_volume_tlv }, \
+	  .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
+
+#define CA0132_CODEC_MUTE_MONO(xname, nid, channel, dir) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	  .name = xname, \
+	  .subdevice = HDA_SUBDEV_AMP_FLAG, \
+	  .info = snd_hda_mixer_amp_switch_info, \
+	  .get = ca0132_switch_get, \
+	  .put = ca0132_switch_put, \
+	  .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
+
+/* stereo */
+#define CA0132_CODEC_VOL(xname, nid, dir) \
+	CA0132_CODEC_VOL_MONO(xname, nid, 3, dir)
+#define CA0132_CODEC_MUTE(xname, nid, dir) \
+	CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir)
+
 /*
  * PCM callbacks
  */