diff options
author | Ian Minett <ian_minett@creativelabs.com> | 2012-12-21 02:53:33 (GMT) |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-15 15:57:42 (GMT) |
commit | ef6b2eada3b8c1b21f6479d7480ea7030183fe1d (patch) | |
tree | 632cc3a8fe117da92b7106adc52b0604ea4f0aba /sound/pci/hda/patch_ca0132.c | |
parent | cdc83c59e59d57b250be46c4b9d31e3b2b5ae589 (diff) | |
download | linux-ef6b2eada3b8c1b21f6479d7480ea7030183fe1d.tar.xz |
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>
Diffstat (limited to 'sound/pci/hda/patch_ca0132.c')
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 445 |
1 files changed, 442 insertions, 3 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 2fd3121..38ac07b 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/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 */ |