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>
This commit is contained in:
Ian Minett 2012-12-20 18:53:33 -08:00 committed by Takashi Iwai
parent cdc83c59e5
commit ef6b2eada3
1 changed files with 442 additions and 3 deletions

View File

@ -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
*/