diff options
Diffstat (limited to 'sound/pci/hda/patch_ca0132.c')
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 2997 |
1 files changed, 2911 insertions, 86 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 768ea8651993..292e2c592c17 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/firmware.h> | 29 | #include <linux/firmware.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/types.h> | ||
32 | #include <linux/io.h> | ||
33 | #include <linux/pci.h> | ||
31 | #include <sound/core.h> | 34 | #include <sound/core.h> |
32 | #include "hda_codec.h" | 35 | #include "hda_codec.h" |
33 | #include "hda_local.h" | 36 | #include "hda_local.h" |
@@ -39,9 +42,15 @@ | |||
39 | /* Enable this to see controls for tuning purpose. */ | 42 | /* Enable this to see controls for tuning purpose. */ |
40 | /*#define ENABLE_TUNING_CONTROLS*/ | 43 | /*#define ENABLE_TUNING_CONTROLS*/ |
41 | 44 | ||
45 | #ifdef ENABLE_TUNING_CONTROLS | ||
46 | #include <sound/tlv.h> | ||
47 | #endif | ||
48 | |||
42 | #define FLOAT_ZERO 0x00000000 | 49 | #define FLOAT_ZERO 0x00000000 |
43 | #define FLOAT_ONE 0x3f800000 | 50 | #define FLOAT_ONE 0x3f800000 |
44 | #define FLOAT_TWO 0x40000000 | 51 | #define FLOAT_TWO 0x40000000 |
52 | #define FLOAT_THREE 0x40400000 | ||
53 | #define FLOAT_EIGHT 0x41000000 | ||
45 | #define FLOAT_MINUS_5 0xc0a00000 | 54 | #define FLOAT_MINUS_5 0xc0a00000 |
46 | 55 | ||
47 | #define UNSOL_TAG_DSP 0x16 | 56 | #define UNSOL_TAG_DSP 0x16 |
@@ -72,16 +81,22 @@ | |||
72 | #define SCP_GET 1 | 81 | #define SCP_GET 1 |
73 | 82 | ||
74 | #define EFX_FILE "ctefx.bin" | 83 | #define EFX_FILE "ctefx.bin" |
84 | #define SBZ_EFX_FILE "ctefx-sbz.bin" | ||
85 | #define R3DI_EFX_FILE "ctefx-r3di.bin" | ||
75 | 86 | ||
76 | #ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP | 87 | #ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP |
77 | MODULE_FIRMWARE(EFX_FILE); | 88 | MODULE_FIRMWARE(EFX_FILE); |
89 | MODULE_FIRMWARE(SBZ_EFX_FILE); | ||
90 | MODULE_FIRMWARE(R3DI_EFX_FILE); | ||
78 | #endif | 91 | #endif |
79 | 92 | ||
80 | static char *dirstr[2] = { "Playback", "Capture" }; | 93 | static const char *const dirstr[2] = { "Playback", "Capture" }; |
81 | 94 | ||
95 | #define NUM_OF_OUTPUTS 3 | ||
82 | enum { | 96 | enum { |
83 | SPEAKER_OUT, | 97 | SPEAKER_OUT, |
84 | HEADPHONE_OUT | 98 | HEADPHONE_OUT, |
99 | SURROUND_OUT | ||
85 | }; | 100 | }; |
86 | 101 | ||
87 | enum { | 102 | enum { |
@@ -89,6 +104,15 @@ enum { | |||
89 | LINE_MIC_IN | 104 | LINE_MIC_IN |
90 | }; | 105 | }; |
91 | 106 | ||
107 | /* Strings for Input Source Enum Control */ | ||
108 | static const char *const in_src_str[3] = {"Rear Mic", "Line", "Front Mic" }; | ||
109 | #define IN_SRC_NUM_OF_INPUTS 3 | ||
110 | enum { | ||
111 | REAR_MIC, | ||
112 | REAR_LINE_IN, | ||
113 | FRONT_MIC, | ||
114 | }; | ||
115 | |||
92 | enum { | 116 | enum { |
93 | #define VNODE_START_NID 0x80 | 117 | #define VNODE_START_NID 0x80 |
94 | VNID_SPK = VNODE_START_NID, /* Speaker vnid */ | 118 | VNID_SPK = VNODE_START_NID, /* Speaker vnid */ |
@@ -122,13 +146,28 @@ enum { | |||
122 | VOICEFX = IN_EFFECT_END_NID, | 146 | VOICEFX = IN_EFFECT_END_NID, |
123 | PLAY_ENHANCEMENT, | 147 | PLAY_ENHANCEMENT, |
124 | CRYSTAL_VOICE, | 148 | CRYSTAL_VOICE, |
125 | EFFECT_END_NID | 149 | EFFECT_END_NID, |
150 | OUTPUT_SOURCE_ENUM, | ||
151 | INPUT_SOURCE_ENUM, | ||
152 | XBASS_XOVER, | ||
153 | EQ_PRESET_ENUM, | ||
154 | SMART_VOLUME_ENUM, | ||
155 | MIC_BOOST_ENUM | ||
126 | #define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID) | 156 | #define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID) |
127 | }; | 157 | }; |
128 | 158 | ||
129 | /* Effects values size*/ | 159 | /* Effects values size*/ |
130 | #define EFFECT_VALS_MAX_COUNT 12 | 160 | #define EFFECT_VALS_MAX_COUNT 12 |
131 | 161 | ||
162 | /* | ||
163 | * Default values for the effect slider controls, they are in order of their | ||
164 | * effect NID's. Surround, Crystalizer, Dialog Plus, Smart Volume, and then | ||
165 | * X-bass. | ||
166 | */ | ||
167 | static const unsigned int effect_slider_defaults[] = {67, 65, 50, 74, 50}; | ||
168 | /* Amount of effect level sliders for ca0132_alt controls. */ | ||
169 | #define EFFECT_LEVEL_SLIDERS 5 | ||
170 | |||
132 | /* Latency introduced by DSP blocks in milliseconds. */ | 171 | /* Latency introduced by DSP blocks in milliseconds. */ |
133 | #define DSP_CAPTURE_INIT_LATENCY 0 | 172 | #define DSP_CAPTURE_INIT_LATENCY 0 |
134 | #define DSP_CRYSTAL_VOICE_LATENCY 124 | 173 | #define DSP_CRYSTAL_VOICE_LATENCY 124 |
@@ -150,7 +189,7 @@ struct ct_effect { | |||
150 | #define EFX_DIR_OUT 0 | 189 | #define EFX_DIR_OUT 0 |
151 | #define EFX_DIR_IN 1 | 190 | #define EFX_DIR_IN 1 |
152 | 191 | ||
153 | static struct ct_effect ca0132_effects[EFFECTS_COUNT] = { | 192 | static const struct ct_effect ca0132_effects[EFFECTS_COUNT] = { |
154 | { .name = "Surround", | 193 | { .name = "Surround", |
155 | .nid = SURROUND, | 194 | .nid = SURROUND, |
156 | .mid = 0x96, | 195 | .mid = 0x96, |
@@ -277,7 +316,7 @@ struct ct_tuning_ctl { | |||
277 | unsigned int def_val;/*effect default values*/ | 316 | unsigned int def_val;/*effect default values*/ |
278 | }; | 317 | }; |
279 | 318 | ||
280 | static struct ct_tuning_ctl ca0132_tuning_ctls[] = { | 319 | static const struct ct_tuning_ctl ca0132_tuning_ctls[] = { |
281 | { .name = "Wedge Angle", | 320 | { .name = "Wedge Angle", |
282 | .parent_nid = VOICE_FOCUS, | 321 | .parent_nid = VOICE_FOCUS, |
283 | .nid = WEDGE_ANGLE, | 322 | .nid = WEDGE_ANGLE, |
@@ -392,14 +431,14 @@ struct ct_voicefx_preset { | |||
392 | unsigned int vals[VOICEFX_MAX_PARAM_COUNT]; | 431 | unsigned int vals[VOICEFX_MAX_PARAM_COUNT]; |
393 | }; | 432 | }; |
394 | 433 | ||
395 | static struct ct_voicefx ca0132_voicefx = { | 434 | static const struct ct_voicefx ca0132_voicefx = { |
396 | .name = "VoiceFX Capture Switch", | 435 | .name = "VoiceFX Capture Switch", |
397 | .nid = VOICEFX, | 436 | .nid = VOICEFX, |
398 | .mid = 0x95, | 437 | .mid = 0x95, |
399 | .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18} | 438 | .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18} |
400 | }; | 439 | }; |
401 | 440 | ||
402 | static struct ct_voicefx_preset ca0132_voicefx_presets[] = { | 441 | static const struct ct_voicefx_preset ca0132_voicefx_presets[] = { |
403 | { .name = "Neutral", | 442 | { .name = "Neutral", |
404 | .vals = { 0x00000000, 0x43C80000, 0x44AF0000, | 443 | .vals = { 0x00000000, 0x43C80000, 0x44AF0000, |
405 | 0x44FA0000, 0x3F800000, 0x3F800000, | 444 | 0x44FA0000, 0x3F800000, 0x3F800000, |
@@ -472,6 +511,161 @@ static struct ct_voicefx_preset ca0132_voicefx_presets[] = { | |||
472 | } | 511 | } |
473 | }; | 512 | }; |
474 | 513 | ||
514 | /* ca0132 EQ presets, taken from Windows Sound Blaster Z Driver */ | ||
515 | |||
516 | #define EQ_PRESET_MAX_PARAM_COUNT 11 | ||
517 | |||
518 | struct ct_eq { | ||
519 | char *name; | ||
520 | hda_nid_t nid; | ||
521 | int mid; | ||
522 | int reqs[EQ_PRESET_MAX_PARAM_COUNT]; /*effect module request*/ | ||
523 | }; | ||
524 | |||
525 | struct ct_eq_preset { | ||
526 | char *name; /*preset name*/ | ||
527 | unsigned int vals[EQ_PRESET_MAX_PARAM_COUNT]; | ||
528 | }; | ||
529 | |||
530 | static const struct ct_eq ca0132_alt_eq_enum = { | ||
531 | .name = "FX: Equalizer Preset Switch", | ||
532 | .nid = EQ_PRESET_ENUM, | ||
533 | .mid = 0x96, | ||
534 | .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} | ||
535 | }; | ||
536 | |||
537 | |||
538 | static const struct ct_eq_preset ca0132_alt_eq_presets[] = { | ||
539 | { .name = "Flat", | ||
540 | .vals = { 0x00000000, 0x00000000, 0x00000000, | ||
541 | 0x00000000, 0x00000000, 0x00000000, | ||
542 | 0x00000000, 0x00000000, 0x00000000, | ||
543 | 0x00000000, 0x00000000 } | ||
544 | }, | ||
545 | { .name = "Acoustic", | ||
546 | .vals = { 0x00000000, 0x00000000, 0x3F8CCCCD, | ||
547 | 0x40000000, 0x00000000, 0x00000000, | ||
548 | 0x00000000, 0x00000000, 0x40000000, | ||
549 | 0x40000000, 0x40000000 } | ||
550 | }, | ||
551 | { .name = "Classical", | ||
552 | .vals = { 0x00000000, 0x00000000, 0x40C00000, | ||
553 | 0x40C00000, 0x40466666, 0x00000000, | ||
554 | 0x00000000, 0x00000000, 0x00000000, | ||
555 | 0x40466666, 0x40466666 } | ||
556 | }, | ||
557 | { .name = "Country", | ||
558 | .vals = { 0x00000000, 0xBF99999A, 0x00000000, | ||
559 | 0x3FA66666, 0x3FA66666, 0x3F8CCCCD, | ||
560 | 0x00000000, 0x00000000, 0x40000000, | ||
561 | 0x40466666, 0x40800000 } | ||
562 | }, | ||
563 | { .name = "Dance", | ||
564 | .vals = { 0x00000000, 0xBF99999A, 0x40000000, | ||
565 | 0x40466666, 0x40866666, 0xBF99999A, | ||
566 | 0xBF99999A, 0x00000000, 0x00000000, | ||
567 | 0x40800000, 0x40800000 } | ||
568 | }, | ||
569 | { .name = "Jazz", | ||
570 | .vals = { 0x00000000, 0x00000000, 0x00000000, | ||
571 | 0x3F8CCCCD, 0x40800000, 0x40800000, | ||
572 | 0x40800000, 0x00000000, 0x3F8CCCCD, | ||
573 | 0x40466666, 0x40466666 } | ||
574 | }, | ||
575 | { .name = "New Age", | ||
576 | .vals = { 0x00000000, 0x00000000, 0x40000000, | ||
577 | 0x40000000, 0x00000000, 0x00000000, | ||
578 | 0x00000000, 0x3F8CCCCD, 0x40000000, | ||
579 | 0x40000000, 0x40000000 } | ||
580 | }, | ||
581 | { .name = "Pop", | ||
582 | .vals = { 0x00000000, 0xBFCCCCCD, 0x00000000, | ||
583 | 0x40000000, 0x40000000, 0x00000000, | ||
584 | 0xBF99999A, 0xBF99999A, 0x00000000, | ||
585 | 0x40466666, 0x40C00000 } | ||
586 | }, | ||
587 | { .name = "Rock", | ||
588 | .vals = { 0x00000000, 0xBF99999A, 0xBF99999A, | ||
589 | 0x3F8CCCCD, 0x40000000, 0xBF99999A, | ||
590 | 0xBF99999A, 0x00000000, 0x00000000, | ||
591 | 0x40800000, 0x40800000 } | ||
592 | }, | ||
593 | { .name = "Vocal", | ||
594 | .vals = { 0x00000000, 0xC0000000, 0xBF99999A, | ||
595 | 0xBF99999A, 0x00000000, 0x40466666, | ||
596 | 0x40800000, 0x40466666, 0x00000000, | ||
597 | 0x00000000, 0x3F8CCCCD } | ||
598 | } | ||
599 | }; | ||
600 | |||
601 | /* DSP command sequences for ca0132_alt_select_out */ | ||
602 | #define ALT_OUT_SET_MAX_COMMANDS 9 /* Max number of commands in sequence */ | ||
603 | struct ca0132_alt_out_set { | ||
604 | char *name; /*preset name*/ | ||
605 | unsigned char commands; | ||
606 | unsigned int mids[ALT_OUT_SET_MAX_COMMANDS]; | ||
607 | unsigned int reqs[ALT_OUT_SET_MAX_COMMANDS]; | ||
608 | unsigned int vals[ALT_OUT_SET_MAX_COMMANDS]; | ||
609 | }; | ||
610 | |||
611 | static const struct ca0132_alt_out_set alt_out_presets[] = { | ||
612 | { .name = "Line Out", | ||
613 | .commands = 7, | ||
614 | .mids = { 0x96, 0x96, 0x96, 0x8F, | ||
615 | 0x96, 0x96, 0x96 }, | ||
616 | .reqs = { 0x19, 0x17, 0x18, 0x01, | ||
617 | 0x1F, 0x15, 0x3A }, | ||
618 | .vals = { 0x3F000000, 0x42A00000, 0x00000000, | ||
619 | 0x00000000, 0x00000000, 0x00000000, | ||
620 | 0x00000000 } | ||
621 | }, | ||
622 | { .name = "Headphone", | ||
623 | .commands = 7, | ||
624 | .mids = { 0x96, 0x96, 0x96, 0x8F, | ||
625 | 0x96, 0x96, 0x96 }, | ||
626 | .reqs = { 0x19, 0x17, 0x18, 0x01, | ||
627 | 0x1F, 0x15, 0x3A }, | ||
628 | .vals = { 0x3F000000, 0x42A00000, 0x00000000, | ||
629 | 0x00000000, 0x00000000, 0x00000000, | ||
630 | 0x00000000 } | ||
631 | }, | ||
632 | { .name = "Surround", | ||
633 | .commands = 8, | ||
634 | .mids = { 0x96, 0x8F, 0x96, 0x96, | ||
635 | 0x96, 0x96, 0x96, 0x96 }, | ||
636 | .reqs = { 0x18, 0x01, 0x1F, 0x15, | ||
637 | 0x3A, 0x1A, 0x1B, 0x1C }, | ||
638 | .vals = { 0x00000000, 0x00000000, 0x00000000, | ||
639 | 0x00000000, 0x00000000, 0x00000000, | ||
640 | 0x00000000, 0x00000000 } | ||
641 | } | ||
642 | }; | ||
643 | |||
644 | /* | ||
645 | * DSP volume setting structs. Req 1 is left volume, req 2 is right volume, | ||
646 | * and I don't know what the third req is, but it's always zero. I assume it's | ||
647 | * some sort of update or set command to tell the DSP there's new volume info. | ||
648 | */ | ||
649 | #define DSP_VOL_OUT 0 | ||
650 | #define DSP_VOL_IN 1 | ||
651 | |||
652 | struct ct_dsp_volume_ctl { | ||
653 | hda_nid_t vnid; | ||
654 | int mid; /* module ID*/ | ||
655 | unsigned int reqs[3]; /* scp req ID */ | ||
656 | }; | ||
657 | |||
658 | static const struct ct_dsp_volume_ctl ca0132_alt_vol_ctls[] = { | ||
659 | { .vnid = VNID_SPK, | ||
660 | .mid = 0x32, | ||
661 | .reqs = {3, 4, 2} | ||
662 | }, | ||
663 | { .vnid = VNID_MIC, | ||
664 | .mid = 0x37, | ||
665 | .reqs = {2, 3, 1} | ||
666 | } | ||
667 | }; | ||
668 | |||
475 | enum hda_cmd_vendor_io { | 669 | enum hda_cmd_vendor_io { |
476 | /* for DspIO node */ | 670 | /* for DspIO node */ |
477 | VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, | 671 | VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, |
@@ -698,11 +892,12 @@ enum dsp_download_state { | |||
698 | */ | 892 | */ |
699 | 893 | ||
700 | struct ca0132_spec { | 894 | struct ca0132_spec { |
701 | struct snd_kcontrol_new *mixers[5]; | 895 | const struct snd_kcontrol_new *mixers[5]; |
702 | unsigned int num_mixers; | 896 | unsigned int num_mixers; |
703 | const struct hda_verb *base_init_verbs; | 897 | const struct hda_verb *base_init_verbs; |
704 | const struct hda_verb *base_exit_verbs; | 898 | const struct hda_verb *base_exit_verbs; |
705 | const struct hda_verb *chip_init_verbs; | 899 | const struct hda_verb *chip_init_verbs; |
900 | const struct hda_verb *sbz_init_verbs; | ||
706 | struct hda_verb *spec_init_verbs; | 901 | struct hda_verb *spec_init_verbs; |
707 | struct auto_pin_cfg autocfg; | 902 | struct auto_pin_cfg autocfg; |
708 | 903 | ||
@@ -719,6 +914,7 @@ struct ca0132_spec { | |||
719 | hda_nid_t shared_mic_nid; | 914 | hda_nid_t shared_mic_nid; |
720 | hda_nid_t shared_out_nid; | 915 | hda_nid_t shared_out_nid; |
721 | hda_nid_t unsol_tag_hp; | 916 | hda_nid_t unsol_tag_hp; |
917 | hda_nid_t unsol_tag_front_hp; /* for desktop ca0132 codecs */ | ||
722 | hda_nid_t unsol_tag_amic1; | 918 | hda_nid_t unsol_tag_amic1; |
723 | 919 | ||
724 | /* chip access */ | 920 | /* chip access */ |
@@ -734,6 +930,9 @@ struct ca0132_spec { | |||
734 | unsigned int scp_resp_header; | 930 | unsigned int scp_resp_header; |
735 | unsigned int scp_resp_data[4]; | 931 | unsigned int scp_resp_data[4]; |
736 | unsigned int scp_resp_count; | 932 | unsigned int scp_resp_count; |
933 | bool alt_firmware_present; | ||
934 | bool startup_check_entered; | ||
935 | bool dsp_reload; | ||
737 | 936 | ||
738 | /* mixer and effects related */ | 937 | /* mixer and effects related */ |
739 | unsigned char dmic_ctl; | 938 | unsigned char dmic_ctl; |
@@ -746,6 +945,17 @@ struct ca0132_spec { | |||
746 | long effects_switch[EFFECTS_COUNT]; | 945 | long effects_switch[EFFECTS_COUNT]; |
747 | long voicefx_val; | 946 | long voicefx_val; |
748 | long cur_mic_boost; | 947 | long cur_mic_boost; |
948 | /* ca0132_alt control related values */ | ||
949 | unsigned char in_enum_val; | ||
950 | unsigned char out_enum_val; | ||
951 | unsigned char mic_boost_enum_val; | ||
952 | unsigned char smart_volume_setting; | ||
953 | long fx_ctl_val[EFFECT_LEVEL_SLIDERS]; | ||
954 | long xbass_xover_freq; | ||
955 | long eq_preset_val; | ||
956 | unsigned int tlv[4]; | ||
957 | struct hda_vmaster_mute_hook vmaster_mute; | ||
958 | |||
749 | 959 | ||
750 | struct hda_codec *codec; | 960 | struct hda_codec *codec; |
751 | struct delayed_work unsol_hp_work; | 961 | struct delayed_work unsol_hp_work; |
@@ -754,6 +964,25 @@ struct ca0132_spec { | |||
754 | #ifdef ENABLE_TUNING_CONTROLS | 964 | #ifdef ENABLE_TUNING_CONTROLS |
755 | long cur_ctl_vals[TUNING_CTLS_COUNT]; | 965 | long cur_ctl_vals[TUNING_CTLS_COUNT]; |
756 | #endif | 966 | #endif |
967 | /* | ||
968 | * Sound Blaster Z PCI region 2 iomem, used for input and output | ||
969 | * switching, and other unknown commands. | ||
970 | */ | ||
971 | void __iomem *mem_base; | ||
972 | |||
973 | /* | ||
974 | * Whether or not to use the alt functions like alt_select_out, | ||
975 | * alt_select_in, etc. Only used on desktop codecs for now, because of | ||
976 | * surround sound support. | ||
977 | */ | ||
978 | bool use_alt_functions; | ||
979 | |||
980 | /* | ||
981 | * Whether or not to use alt controls: volume effect sliders, EQ | ||
982 | * presets, smart volume presets, and new control names with FX prefix. | ||
983 | * Renames PlayEnhancement and CrystalVoice too. | ||
984 | */ | ||
985 | bool use_alt_controls; | ||
757 | }; | 986 | }; |
758 | 987 | ||
759 | /* | 988 | /* |
@@ -762,6 +991,8 @@ struct ca0132_spec { | |||
762 | enum { | 991 | enum { |
763 | QUIRK_NONE, | 992 | QUIRK_NONE, |
764 | QUIRK_ALIENWARE, | 993 | QUIRK_ALIENWARE, |
994 | QUIRK_SBZ, | ||
995 | QUIRK_R3DI, | ||
765 | }; | 996 | }; |
766 | 997 | ||
767 | static const struct hda_pintbl alienware_pincfgs[] = { | 998 | static const struct hda_pintbl alienware_pincfgs[] = { |
@@ -778,10 +1009,44 @@ static const struct hda_pintbl alienware_pincfgs[] = { | |||
778 | {} | 1009 | {} |
779 | }; | 1010 | }; |
780 | 1011 | ||
1012 | /* Sound Blaster Z pin configs taken from Windows Driver */ | ||
1013 | static const struct hda_pintbl sbz_pincfgs[] = { | ||
1014 | { 0x0b, 0x01017010 }, /* Port G -- Lineout FRONT L/R */ | ||
1015 | { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */ | ||
1016 | { 0x0d, 0x014510f0 }, /* Digital Out */ | ||
1017 | { 0x0e, 0x01c510f0 }, /* SPDIF In */ | ||
1018 | { 0x0f, 0x0221701f }, /* Port A -- BackPanel HP */ | ||
1019 | { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */ | ||
1020 | { 0x11, 0x01017014 }, /* Port B -- LineMicIn2 / Rear L/R */ | ||
1021 | { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */ | ||
1022 | { 0x13, 0x908700f0 }, /* What U Hear In*/ | ||
1023 | { 0x18, 0x50d000f0 }, /* N/A */ | ||
1024 | {} | ||
1025 | }; | ||
1026 | |||
1027 | /* Recon3D integrated pin configs taken from Windows Driver */ | ||
1028 | static const struct hda_pintbl r3di_pincfgs[] = { | ||
1029 | { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ | ||
1030 | { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */ | ||
1031 | { 0x0d, 0x014510f0 }, /* Digital Out */ | ||
1032 | { 0x0e, 0x41c520f0 }, /* SPDIF In */ | ||
1033 | { 0x0f, 0x0221401f }, /* Port A -- BackPanel HP */ | ||
1034 | { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */ | ||
1035 | { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */ | ||
1036 | { 0x12, 0x02a090f0 }, /* Port C -- LineIn1 */ | ||
1037 | { 0x13, 0x908700f0 }, /* What U Hear In*/ | ||
1038 | { 0x18, 0x500000f0 }, /* N/A */ | ||
1039 | {} | ||
1040 | }; | ||
1041 | |||
781 | static const struct snd_pci_quirk ca0132_quirks[] = { | 1042 | static const struct snd_pci_quirk ca0132_quirks[] = { |
782 | SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), | 1043 | SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), |
783 | SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE), | 1044 | SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE), |
784 | SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE), | 1045 | SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE), |
1046 | SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ), | ||
1047 | SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ), | ||
1048 | SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), | ||
1049 | SND_PCI_QUIRK(0x1458, 0xA036, "Recon3Di", QUIRK_R3DI), | ||
785 | {} | 1050 | {} |
786 | }; | 1051 | }; |
787 | 1052 | ||
@@ -965,6 +1230,29 @@ exit: | |||
965 | } | 1230 | } |
966 | 1231 | ||
967 | /* | 1232 | /* |
1233 | * Write given value to the given address through the chip I/O widget. | ||
1234 | * not protected by the Mutex | ||
1235 | */ | ||
1236 | static int chipio_write_no_mutex(struct hda_codec *codec, | ||
1237 | unsigned int chip_addx, const unsigned int data) | ||
1238 | { | ||
1239 | int err; | ||
1240 | |||
1241 | |||
1242 | /* write the address, and if successful proceed to write data */ | ||
1243 | err = chipio_write_address(codec, chip_addx); | ||
1244 | if (err < 0) | ||
1245 | goto exit; | ||
1246 | |||
1247 | err = chipio_write_data(codec, data); | ||
1248 | if (err < 0) | ||
1249 | goto exit; | ||
1250 | |||
1251 | exit: | ||
1252 | return err; | ||
1253 | } | ||
1254 | |||
1255 | /* | ||
968 | * Write multiple values to the given address through the chip I/O widget. | 1256 | * Write multiple values to the given address through the chip I/O widget. |
969 | * protected by the Mutex | 1257 | * protected by the Mutex |
970 | */ | 1258 | */ |
@@ -1058,6 +1346,81 @@ static void chipio_set_control_param(struct hda_codec *codec, | |||
1058 | } | 1346 | } |
1059 | 1347 | ||
1060 | /* | 1348 | /* |
1349 | * Set chip parameters through the chip I/O widget. NO MUTEX. | ||
1350 | */ | ||
1351 | static void chipio_set_control_param_no_mutex(struct hda_codec *codec, | ||
1352 | enum control_param_id param_id, int param_val) | ||
1353 | { | ||
1354 | int val; | ||
1355 | |||
1356 | if ((param_id < 32) && (param_val < 8)) { | ||
1357 | val = (param_val << 5) | (param_id); | ||
1358 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
1359 | VENDOR_CHIPIO_PARAM_SET, val); | ||
1360 | } else { | ||
1361 | if (chipio_send(codec, VENDOR_CHIPIO_STATUS, 0) == 0) { | ||
1362 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
1363 | VENDOR_CHIPIO_PARAM_EX_ID_SET, | ||
1364 | param_id); | ||
1365 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
1366 | VENDOR_CHIPIO_PARAM_EX_VALUE_SET, | ||
1367 | param_val); | ||
1368 | } | ||
1369 | } | ||
1370 | } | ||
1371 | /* | ||
1372 | * Connect stream to a source point, and then connect | ||
1373 | * that source point to a destination point. | ||
1374 | */ | ||
1375 | static void chipio_set_stream_source_dest(struct hda_codec *codec, | ||
1376 | int streamid, int source_point, int dest_point) | ||
1377 | { | ||
1378 | chipio_set_control_param_no_mutex(codec, | ||
1379 | CONTROL_PARAM_STREAM_ID, streamid); | ||
1380 | chipio_set_control_param_no_mutex(codec, | ||
1381 | CONTROL_PARAM_STREAM_SOURCE_CONN_POINT, source_point); | ||
1382 | chipio_set_control_param_no_mutex(codec, | ||
1383 | CONTROL_PARAM_STREAM_DEST_CONN_POINT, dest_point); | ||
1384 | } | ||
1385 | |||
1386 | /* | ||
1387 | * Set number of channels in the selected stream. | ||
1388 | */ | ||
1389 | static void chipio_set_stream_channels(struct hda_codec *codec, | ||
1390 | int streamid, unsigned int channels) | ||
1391 | { | ||
1392 | chipio_set_control_param_no_mutex(codec, | ||
1393 | CONTROL_PARAM_STREAM_ID, streamid); | ||
1394 | chipio_set_control_param_no_mutex(codec, | ||
1395 | CONTROL_PARAM_STREAMS_CHANNELS, channels); | ||
1396 | } | ||
1397 | |||
1398 | /* | ||
1399 | * Enable/Disable audio stream. | ||
1400 | */ | ||
1401 | static void chipio_set_stream_control(struct hda_codec *codec, | ||
1402 | int streamid, int enable) | ||
1403 | { | ||
1404 | chipio_set_control_param_no_mutex(codec, | ||
1405 | CONTROL_PARAM_STREAM_ID, streamid); | ||
1406 | chipio_set_control_param_no_mutex(codec, | ||
1407 | CONTROL_PARAM_STREAM_CONTROL, enable); | ||
1408 | } | ||
1409 | |||
1410 | |||
1411 | /* | ||
1412 | * Set sampling rate of the connection point. NO MUTEX. | ||
1413 | */ | ||
1414 | static void chipio_set_conn_rate_no_mutex(struct hda_codec *codec, | ||
1415 | int connid, enum ca0132_sample_rate rate) | ||
1416 | { | ||
1417 | chipio_set_control_param_no_mutex(codec, | ||
1418 | CONTROL_PARAM_CONN_POINT_ID, connid); | ||
1419 | chipio_set_control_param_no_mutex(codec, | ||
1420 | CONTROL_PARAM_CONN_POINT_SAMPLE_RATE, rate); | ||
1421 | } | ||
1422 | |||
1423 | /* | ||
1061 | * Set sampling rate of the connection point. | 1424 | * Set sampling rate of the connection point. |
1062 | */ | 1425 | */ |
1063 | static void chipio_set_conn_rate(struct hda_codec *codec, | 1426 | static void chipio_set_conn_rate(struct hda_codec *codec, |
@@ -1420,8 +1783,8 @@ static int dspio_send_scp_message(struct hda_codec *codec, | |||
1420 | * Returns zero or a negative error code. | 1783 | * Returns zero or a negative error code. |
1421 | */ | 1784 | */ |
1422 | static int dspio_scp(struct hda_codec *codec, | 1785 | static int dspio_scp(struct hda_codec *codec, |
1423 | int mod_id, int req, int dir, void *data, unsigned int len, | 1786 | int mod_id, int src_id, int req, int dir, const void *data, |
1424 | void *reply, unsigned int *reply_len) | 1787 | unsigned int len, void *reply, unsigned int *reply_len) |
1425 | { | 1788 | { |
1426 | int status = 0; | 1789 | int status = 0; |
1427 | struct scp_msg scp_send, scp_reply; | 1790 | struct scp_msg scp_send, scp_reply; |
@@ -1445,7 +1808,7 @@ static int dspio_scp(struct hda_codec *codec, | |||
1445 | return -EINVAL; | 1808 | return -EINVAL; |
1446 | } | 1809 | } |
1447 | 1810 | ||
1448 | scp_send.hdr = make_scp_header(mod_id, 0x20, (dir == SCP_GET), req, | 1811 | scp_send.hdr = make_scp_header(mod_id, src_id, (dir == SCP_GET), req, |
1449 | 0, 0, 0, len/sizeof(unsigned int)); | 1812 | 0, 0, 0, len/sizeof(unsigned int)); |
1450 | if (data != NULL && len > 0) { | 1813 | if (data != NULL && len > 0) { |
1451 | len = min((unsigned int)(sizeof(scp_send.data)), len); | 1814 | len = min((unsigned int)(sizeof(scp_send.data)), len); |
@@ -1502,15 +1865,24 @@ static int dspio_scp(struct hda_codec *codec, | |||
1502 | * Set DSP parameters | 1865 | * Set DSP parameters |
1503 | */ | 1866 | */ |
1504 | static int dspio_set_param(struct hda_codec *codec, int mod_id, | 1867 | static int dspio_set_param(struct hda_codec *codec, int mod_id, |
1505 | int req, void *data, unsigned int len) | 1868 | int src_id, int req, const void *data, unsigned int len) |
1506 | { | 1869 | { |
1507 | return dspio_scp(codec, mod_id, req, SCP_SET, data, len, NULL, NULL); | 1870 | return dspio_scp(codec, mod_id, src_id, req, SCP_SET, data, len, NULL, |
1871 | NULL); | ||
1508 | } | 1872 | } |
1509 | 1873 | ||
1510 | static int dspio_set_uint_param(struct hda_codec *codec, int mod_id, | 1874 | static int dspio_set_uint_param(struct hda_codec *codec, int mod_id, |
1511 | int req, unsigned int data) | 1875 | int req, const unsigned int data) |
1512 | { | 1876 | { |
1513 | return dspio_set_param(codec, mod_id, req, &data, sizeof(unsigned int)); | 1877 | return dspio_set_param(codec, mod_id, 0x20, req, &data, |
1878 | sizeof(unsigned int)); | ||
1879 | } | ||
1880 | |||
1881 | static int dspio_set_uint_param_no_source(struct hda_codec *codec, int mod_id, | ||
1882 | int req, const unsigned int data) | ||
1883 | { | ||
1884 | return dspio_set_param(codec, mod_id, 0x00, req, &data, | ||
1885 | sizeof(unsigned int)); | ||
1514 | } | 1886 | } |
1515 | 1887 | ||
1516 | /* | 1888 | /* |
@@ -1522,8 +1894,9 @@ static int dspio_alloc_dma_chan(struct hda_codec *codec, unsigned int *dma_chan) | |||
1522 | unsigned int size = sizeof(dma_chan); | 1894 | unsigned int size = sizeof(dma_chan); |
1523 | 1895 | ||
1524 | codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n"); | 1896 | codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n"); |
1525 | status = dspio_scp(codec, MASTERCONTROL, MASTERCONTROL_ALLOC_DMA_CHAN, | 1897 | status = dspio_scp(codec, MASTERCONTROL, 0x20, |
1526 | SCP_GET, NULL, 0, dma_chan, &size); | 1898 | MASTERCONTROL_ALLOC_DMA_CHAN, SCP_GET, NULL, 0, |
1899 | dma_chan, &size); | ||
1527 | 1900 | ||
1528 | if (status < 0) { | 1901 | if (status < 0) { |
1529 | codec_dbg(codec, "dspio_alloc_dma_chan: SCP Failed\n"); | 1902 | codec_dbg(codec, "dspio_alloc_dma_chan: SCP Failed\n"); |
@@ -1552,8 +1925,9 @@ static int dspio_free_dma_chan(struct hda_codec *codec, unsigned int dma_chan) | |||
1552 | codec_dbg(codec, " dspio_free_dma_chan() -- begin\n"); | 1925 | codec_dbg(codec, " dspio_free_dma_chan() -- begin\n"); |
1553 | codec_dbg(codec, "dspio_free_dma_chan: chan=%d\n", dma_chan); | 1926 | codec_dbg(codec, "dspio_free_dma_chan: chan=%d\n", dma_chan); |
1554 | 1927 | ||
1555 | status = dspio_scp(codec, MASTERCONTROL, MASTERCONTROL_ALLOC_DMA_CHAN, | 1928 | status = dspio_scp(codec, MASTERCONTROL, 0x20, |
1556 | SCP_SET, &dma_chan, sizeof(dma_chan), NULL, &dummy); | 1929 | MASTERCONTROL_ALLOC_DMA_CHAN, SCP_SET, &dma_chan, |
1930 | sizeof(dma_chan), NULL, &dummy); | ||
1557 | 1931 | ||
1558 | if (status < 0) { | 1932 | if (status < 0) { |
1559 | codec_dbg(codec, "dspio_free_dma_chan: SCP Failed\n"); | 1933 | codec_dbg(codec, "dspio_free_dma_chan: SCP Failed\n"); |
@@ -2575,14 +2949,16 @@ exit: | |||
2575 | */ | 2949 | */ |
2576 | static void dspload_post_setup(struct hda_codec *codec) | 2950 | static void dspload_post_setup(struct hda_codec *codec) |
2577 | { | 2951 | { |
2952 | struct ca0132_spec *spec = codec->spec; | ||
2578 | codec_dbg(codec, "---- dspload_post_setup ------\n"); | 2953 | codec_dbg(codec, "---- dspload_post_setup ------\n"); |
2954 | if (!spec->use_alt_functions) { | ||
2955 | /*set DSP speaker to 2.0 configuration*/ | ||
2956 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080); | ||
2957 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000); | ||
2579 | 2958 | ||
2580 | /*set DSP speaker to 2.0 configuration*/ | 2959 | /*update write pointer*/ |
2581 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080); | 2960 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002); |
2582 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000); | 2961 | } |
2583 | |||
2584 | /*update write pointer*/ | ||
2585 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002); | ||
2586 | } | 2962 | } |
2587 | 2963 | ||
2588 | /** | 2964 | /** |
@@ -2690,6 +3066,170 @@ static bool dspload_wait_loaded(struct hda_codec *codec) | |||
2690 | } | 3066 | } |
2691 | 3067 | ||
2692 | /* | 3068 | /* |
3069 | * Setup GPIO for the other variants of Core3D. | ||
3070 | */ | ||
3071 | |||
3072 | /* | ||
3073 | * Sets up the GPIO pins so that they are discoverable. If this isn't done, | ||
3074 | * the card shows as having no GPIO pins. | ||
3075 | */ | ||
3076 | static void ca0132_gpio_init(struct hda_codec *codec) | ||
3077 | { | ||
3078 | struct ca0132_spec *spec = codec->spec; | ||
3079 | |||
3080 | switch (spec->quirk) { | ||
3081 | case QUIRK_SBZ: | ||
3082 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); | ||
3083 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); | ||
3084 | snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23); | ||
3085 | break; | ||
3086 | case QUIRK_R3DI: | ||
3087 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); | ||
3088 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5B); | ||
3089 | break; | ||
3090 | } | ||
3091 | |||
3092 | } | ||
3093 | |||
3094 | /* Sets the GPIO for audio output. */ | ||
3095 | static void ca0132_gpio_setup(struct hda_codec *codec) | ||
3096 | { | ||
3097 | struct ca0132_spec *spec = codec->spec; | ||
3098 | |||
3099 | switch (spec->quirk) { | ||
3100 | case QUIRK_SBZ: | ||
3101 | snd_hda_codec_write(codec, 0x01, 0, | ||
3102 | AC_VERB_SET_GPIO_DIRECTION, 0x07); | ||
3103 | snd_hda_codec_write(codec, 0x01, 0, | ||
3104 | AC_VERB_SET_GPIO_MASK, 0x07); | ||
3105 | snd_hda_codec_write(codec, 0x01, 0, | ||
3106 | AC_VERB_SET_GPIO_DATA, 0x04); | ||
3107 | snd_hda_codec_write(codec, 0x01, 0, | ||
3108 | AC_VERB_SET_GPIO_DATA, 0x06); | ||
3109 | break; | ||
3110 | case QUIRK_R3DI: | ||
3111 | snd_hda_codec_write(codec, 0x01, 0, | ||
3112 | AC_VERB_SET_GPIO_DIRECTION, 0x1E); | ||
3113 | snd_hda_codec_write(codec, 0x01, 0, | ||
3114 | AC_VERB_SET_GPIO_MASK, 0x1F); | ||
3115 | snd_hda_codec_write(codec, 0x01, 0, | ||
3116 | AC_VERB_SET_GPIO_DATA, 0x0C); | ||
3117 | break; | ||
3118 | } | ||
3119 | } | ||
3120 | |||
3121 | /* | ||
3122 | * GPIO control functions for the Recon3D integrated. | ||
3123 | */ | ||
3124 | |||
3125 | enum r3di_gpio_bit { | ||
3126 | /* Bit 1 - Switch between front/rear mic. 0 = rear, 1 = front */ | ||
3127 | R3DI_MIC_SELECT_BIT = 1, | ||
3128 | /* Bit 2 - Switch between headphone/line out. 0 = Headphone, 1 = Line */ | ||
3129 | R3DI_OUT_SELECT_BIT = 2, | ||
3130 | /* | ||
3131 | * I dunno what this actually does, but it stays on until the dsp | ||
3132 | * is downloaded. | ||
3133 | */ | ||
3134 | R3DI_GPIO_DSP_DOWNLOADING = 3, | ||
3135 | /* | ||
3136 | * Same as above, no clue what it does, but it comes on after the dsp | ||
3137 | * is downloaded. | ||
3138 | */ | ||
3139 | R3DI_GPIO_DSP_DOWNLOADED = 4 | ||
3140 | }; | ||
3141 | |||
3142 | enum r3di_mic_select { | ||
3143 | /* Set GPIO bit 1 to 0 for rear mic */ | ||
3144 | R3DI_REAR_MIC = 0, | ||
3145 | /* Set GPIO bit 1 to 1 for front microphone*/ | ||
3146 | R3DI_FRONT_MIC = 1 | ||
3147 | }; | ||
3148 | |||
3149 | enum r3di_out_select { | ||
3150 | /* Set GPIO bit 2 to 0 for headphone */ | ||
3151 | R3DI_HEADPHONE_OUT = 0, | ||
3152 | /* Set GPIO bit 2 to 1 for speaker */ | ||
3153 | R3DI_LINE_OUT = 1 | ||
3154 | }; | ||
3155 | enum r3di_dsp_status { | ||
3156 | /* Set GPIO bit 3 to 1 until DSP is downloaded */ | ||
3157 | R3DI_DSP_DOWNLOADING = 0, | ||
3158 | /* Set GPIO bit 4 to 1 once DSP is downloaded */ | ||
3159 | R3DI_DSP_DOWNLOADED = 1 | ||
3160 | }; | ||
3161 | |||
3162 | |||
3163 | static void r3di_gpio_mic_set(struct hda_codec *codec, | ||
3164 | enum r3di_mic_select cur_mic) | ||
3165 | { | ||
3166 | unsigned int cur_gpio; | ||
3167 | |||
3168 | /* Get the current GPIO Data setup */ | ||
3169 | cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0); | ||
3170 | |||
3171 | switch (cur_mic) { | ||
3172 | case R3DI_REAR_MIC: | ||
3173 | cur_gpio &= ~(1 << R3DI_MIC_SELECT_BIT); | ||
3174 | break; | ||
3175 | case R3DI_FRONT_MIC: | ||
3176 | cur_gpio |= (1 << R3DI_MIC_SELECT_BIT); | ||
3177 | break; | ||
3178 | } | ||
3179 | snd_hda_codec_write(codec, codec->core.afg, 0, | ||
3180 | AC_VERB_SET_GPIO_DATA, cur_gpio); | ||
3181 | } | ||
3182 | |||
3183 | static void r3di_gpio_out_set(struct hda_codec *codec, | ||
3184 | enum r3di_out_select cur_out) | ||
3185 | { | ||
3186 | unsigned int cur_gpio; | ||
3187 | |||
3188 | /* Get the current GPIO Data setup */ | ||
3189 | cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0); | ||
3190 | |||
3191 | switch (cur_out) { | ||
3192 | case R3DI_HEADPHONE_OUT: | ||
3193 | cur_gpio &= ~(1 << R3DI_OUT_SELECT_BIT); | ||
3194 | break; | ||
3195 | case R3DI_LINE_OUT: | ||
3196 | cur_gpio |= (1 << R3DI_OUT_SELECT_BIT); | ||
3197 | break; | ||
3198 | } | ||
3199 | snd_hda_codec_write(codec, codec->core.afg, 0, | ||
3200 | AC_VERB_SET_GPIO_DATA, cur_gpio); | ||
3201 | } | ||
3202 | |||
3203 | static void r3di_gpio_dsp_status_set(struct hda_codec *codec, | ||
3204 | enum r3di_dsp_status dsp_status) | ||
3205 | { | ||
3206 | unsigned int cur_gpio; | ||
3207 | |||
3208 | /* Get the current GPIO Data setup */ | ||
3209 | cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0); | ||
3210 | |||
3211 | switch (dsp_status) { | ||
3212 | case R3DI_DSP_DOWNLOADING: | ||
3213 | cur_gpio |= (1 << R3DI_GPIO_DSP_DOWNLOADING); | ||
3214 | snd_hda_codec_write(codec, codec->core.afg, 0, | ||
3215 | AC_VERB_SET_GPIO_DATA, cur_gpio); | ||
3216 | break; | ||
3217 | case R3DI_DSP_DOWNLOADED: | ||
3218 | /* Set DOWNLOADING bit to 0. */ | ||
3219 | cur_gpio &= ~(1 << R3DI_GPIO_DSP_DOWNLOADING); | ||
3220 | |||
3221 | snd_hda_codec_write(codec, codec->core.afg, 0, | ||
3222 | AC_VERB_SET_GPIO_DATA, cur_gpio); | ||
3223 | |||
3224 | cur_gpio |= (1 << R3DI_GPIO_DSP_DOWNLOADED); | ||
3225 | break; | ||
3226 | } | ||
3227 | |||
3228 | snd_hda_codec_write(codec, codec->core.afg, 0, | ||
3229 | AC_VERB_SET_GPIO_DATA, cur_gpio); | ||
3230 | } | ||
3231 | |||
3232 | /* | ||
2693 | * PCM callbacks | 3233 | * PCM callbacks |
2694 | */ | 3234 | */ |
2695 | static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 3235 | static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
@@ -2852,6 +3392,24 @@ static unsigned int ca0132_capture_pcm_delay(struct hda_pcm_stream *info, | |||
2852 | .tlv = { .c = ca0132_volume_tlv }, \ | 3392 | .tlv = { .c = ca0132_volume_tlv }, \ |
2853 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) } | 3393 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) } |
2854 | 3394 | ||
3395 | /* | ||
3396 | * Creates a mixer control that uses defaults of HDA_CODEC_VOL except for the | ||
3397 | * volume put, which is used for setting the DSP volume. This was done because | ||
3398 | * the ca0132 functions were taking too much time and causing lag. | ||
3399 | */ | ||
3400 | #define CA0132_ALT_CODEC_VOL_MONO(xname, nid, channel, dir) \ | ||
3401 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3402 | .name = xname, \ | ||
3403 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ | ||
3404 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
3405 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
3406 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ | ||
3407 | .info = snd_hda_mixer_amp_volume_info, \ | ||
3408 | .get = snd_hda_mixer_amp_volume_get, \ | ||
3409 | .put = ca0132_alt_volume_put, \ | ||
3410 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ | ||
3411 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) } | ||
3412 | |||
2855 | #define CA0132_CODEC_MUTE_MONO(xname, nid, channel, dir) \ | 3413 | #define CA0132_CODEC_MUTE_MONO(xname, nid, channel, dir) \ |
2856 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3414 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2857 | .name = xname, \ | 3415 | .name = xname, \ |
@@ -2864,9 +3422,88 @@ static unsigned int ca0132_capture_pcm_delay(struct hda_pcm_stream *info, | |||
2864 | /* stereo */ | 3422 | /* stereo */ |
2865 | #define CA0132_CODEC_VOL(xname, nid, dir) \ | 3423 | #define CA0132_CODEC_VOL(xname, nid, dir) \ |
2866 | CA0132_CODEC_VOL_MONO(xname, nid, 3, dir) | 3424 | CA0132_CODEC_VOL_MONO(xname, nid, 3, dir) |
3425 | #define CA0132_ALT_CODEC_VOL(xname, nid, dir) \ | ||
3426 | CA0132_ALT_CODEC_VOL_MONO(xname, nid, 3, dir) | ||
2867 | #define CA0132_CODEC_MUTE(xname, nid, dir) \ | 3427 | #define CA0132_CODEC_MUTE(xname, nid, dir) \ |
2868 | CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir) | 3428 | CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir) |
2869 | 3429 | ||
3430 | /* lookup tables */ | ||
3431 | /* | ||
3432 | * Lookup table with decibel values for the DSP. When volume is changed in | ||
3433 | * Windows, the DSP is also sent the dB value in floating point. In Windows, | ||
3434 | * these values have decimal points, probably because the Windows driver | ||
3435 | * actually uses floating point. We can't here, so I made a lookup table of | ||
3436 | * values -90 to 9. -90 is the lowest decibel value for both the ADC's and the | ||
3437 | * DAC's, and 9 is the maximum. | ||
3438 | */ | ||
3439 | static const unsigned int float_vol_db_lookup[] = { | ||
3440 | 0xC2B40000, 0xC2B20000, 0xC2B00000, 0xC2AE0000, 0xC2AC0000, 0xC2AA0000, | ||
3441 | 0xC2A80000, 0xC2A60000, 0xC2A40000, 0xC2A20000, 0xC2A00000, 0xC29E0000, | ||
3442 | 0xC29C0000, 0xC29A0000, 0xC2980000, 0xC2960000, 0xC2940000, 0xC2920000, | ||
3443 | 0xC2900000, 0xC28E0000, 0xC28C0000, 0xC28A0000, 0xC2880000, 0xC2860000, | ||
3444 | 0xC2840000, 0xC2820000, 0xC2800000, 0xC27C0000, 0xC2780000, 0xC2740000, | ||
3445 | 0xC2700000, 0xC26C0000, 0xC2680000, 0xC2640000, 0xC2600000, 0xC25C0000, | ||
3446 | 0xC2580000, 0xC2540000, 0xC2500000, 0xC24C0000, 0xC2480000, 0xC2440000, | ||
3447 | 0xC2400000, 0xC23C0000, 0xC2380000, 0xC2340000, 0xC2300000, 0xC22C0000, | ||
3448 | 0xC2280000, 0xC2240000, 0xC2200000, 0xC21C0000, 0xC2180000, 0xC2140000, | ||
3449 | 0xC2100000, 0xC20C0000, 0xC2080000, 0xC2040000, 0xC2000000, 0xC1F80000, | ||
3450 | 0xC1F00000, 0xC1E80000, 0xC1E00000, 0xC1D80000, 0xC1D00000, 0xC1C80000, | ||
3451 | 0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000, | ||
3452 | 0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000, | ||
3453 | 0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000, | ||
3454 | 0xC0C00000, 0xC0A00000, 0xC0800000, 0xC0400000, 0xC0000000, 0xBF800000, | ||
3455 | 0x00000000, 0x3F800000, 0x40000000, 0x40400000, 0x40800000, 0x40A00000, | ||
3456 | 0x40C00000, 0x40E00000, 0x41000000, 0x41100000 | ||
3457 | }; | ||
3458 | |||
3459 | /* | ||
3460 | * This table counts from float 0 to 1 in increments of .01, which is | ||
3461 | * useful for a few different sliders. | ||
3462 | */ | ||
3463 | static const unsigned int float_zero_to_one_lookup[] = { | ||
3464 | 0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD, | ||
3465 | 0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE, | ||
3466 | 0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B, | ||
3467 | 0x3E3851EC, 0x3E428F5C, 0x3E4CCCCD, 0x3E570A3D, 0x3E6147AE, 0x3E6B851F, | ||
3468 | 0x3E75C28F, 0x3E800000, 0x3E851EB8, 0x3E8A3D71, 0x3E8F5C29, 0x3E947AE1, | ||
3469 | 0x3E99999A, 0x3E9EB852, 0x3EA3D70A, 0x3EA8F5C3, 0x3EAE147B, 0x3EB33333, | ||
3470 | 0x3EB851EC, 0x3EBD70A4, 0x3EC28F5C, 0x3EC7AE14, 0x3ECCCCCD, 0x3ED1EB85, | ||
3471 | 0x3ED70A3D, 0x3EDC28F6, 0x3EE147AE, 0x3EE66666, 0x3EEB851F, 0x3EF0A3D7, | ||
3472 | 0x3EF5C28F, 0x3EFAE148, 0x3F000000, 0x3F028F5C, 0x3F051EB8, 0x3F07AE14, | ||
3473 | 0x3F0A3D71, 0x3F0CCCCD, 0x3F0F5C29, 0x3F11EB85, 0x3F147AE1, 0x3F170A3D, | ||
3474 | 0x3F19999A, 0x3F1C28F6, 0x3F1EB852, 0x3F2147AE, 0x3F23D70A, 0x3F266666, | ||
3475 | 0x3F28F5C3, 0x3F2B851F, 0x3F2E147B, 0x3F30A3D7, 0x3F333333, 0x3F35C28F, | ||
3476 | 0x3F3851EC, 0x3F3AE148, 0x3F3D70A4, 0x3F400000, 0x3F428F5C, 0x3F451EB8, | ||
3477 | 0x3F47AE14, 0x3F4A3D71, 0x3F4CCCCD, 0x3F4F5C29, 0x3F51EB85, 0x3F547AE1, | ||
3478 | 0x3F570A3D, 0x3F59999A, 0x3F5C28F6, 0x3F5EB852, 0x3F6147AE, 0x3F63D70A, | ||
3479 | 0x3F666666, 0x3F68F5C3, 0x3F6B851F, 0x3F6E147B, 0x3F70A3D7, 0x3F733333, | ||
3480 | 0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000 | ||
3481 | }; | ||
3482 | |||
3483 | /* | ||
3484 | * This table counts from float 10 to 1000, which is the range of the x-bass | ||
3485 | * crossover slider in Windows. | ||
3486 | */ | ||
3487 | static const unsigned int float_xbass_xover_lookup[] = { | ||
3488 | 0x41200000, 0x41A00000, 0x41F00000, 0x42200000, 0x42480000, 0x42700000, | ||
3489 | 0x428C0000, 0x42A00000, 0x42B40000, 0x42C80000, 0x42DC0000, 0x42F00000, | ||
3490 | 0x43020000, 0x430C0000, 0x43160000, 0x43200000, 0x432A0000, 0x43340000, | ||
3491 | 0x433E0000, 0x43480000, 0x43520000, 0x435C0000, 0x43660000, 0x43700000, | ||
3492 | 0x437A0000, 0x43820000, 0x43870000, 0x438C0000, 0x43910000, 0x43960000, | ||
3493 | 0x439B0000, 0x43A00000, 0x43A50000, 0x43AA0000, 0x43AF0000, 0x43B40000, | ||
3494 | 0x43B90000, 0x43BE0000, 0x43C30000, 0x43C80000, 0x43CD0000, 0x43D20000, | ||
3495 | 0x43D70000, 0x43DC0000, 0x43E10000, 0x43E60000, 0x43EB0000, 0x43F00000, | ||
3496 | 0x43F50000, 0x43FA0000, 0x43FF0000, 0x44020000, 0x44048000, 0x44070000, | ||
3497 | 0x44098000, 0x440C0000, 0x440E8000, 0x44110000, 0x44138000, 0x44160000, | ||
3498 | 0x44188000, 0x441B0000, 0x441D8000, 0x44200000, 0x44228000, 0x44250000, | ||
3499 | 0x44278000, 0x442A0000, 0x442C8000, 0x442F0000, 0x44318000, 0x44340000, | ||
3500 | 0x44368000, 0x44390000, 0x443B8000, 0x443E0000, 0x44408000, 0x44430000, | ||
3501 | 0x44458000, 0x44480000, 0x444A8000, 0x444D0000, 0x444F8000, 0x44520000, | ||
3502 | 0x44548000, 0x44570000, 0x44598000, 0x445C0000, 0x445E8000, 0x44610000, | ||
3503 | 0x44638000, 0x44660000, 0x44688000, 0x446B0000, 0x446D8000, 0x44700000, | ||
3504 | 0x44728000, 0x44750000, 0x44778000, 0x447A0000 | ||
3505 | }; | ||
3506 | |||
2870 | /* The following are for tuning of products */ | 3507 | /* The following are for tuning of products */ |
2871 | #ifdef ENABLE_TUNING_CONTROLS | 3508 | #ifdef ENABLE_TUNING_CONTROLS |
2872 | 3509 | ||
@@ -2942,7 +3579,7 @@ static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid, | |||
2942 | break; | 3579 | break; |
2943 | 3580 | ||
2944 | snd_hda_power_up(codec); | 3581 | snd_hda_power_up(codec); |
2945 | dspio_set_param(codec, ca0132_tuning_ctls[i].mid, | 3582 | dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20, |
2946 | ca0132_tuning_ctls[i].req, | 3583 | ca0132_tuning_ctls[i].req, |
2947 | &(lookup[idx]), sizeof(unsigned int)); | 3584 | &(lookup[idx]), sizeof(unsigned int)); |
2948 | snd_hda_power_down(codec); | 3585 | snd_hda_power_down(codec); |
@@ -3068,8 +3705,8 @@ static int equalizer_ctl_put(struct snd_kcontrol *kcontrol, | |||
3068 | return 1; | 3705 | return 1; |
3069 | } | 3706 | } |
3070 | 3707 | ||
3071 | static const DECLARE_TLV_DB_SCALE(voice_focus_db_scale, 2000, 100, 0); | 3708 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(voice_focus_db_scale, 2000, 100, 0); |
3072 | static const DECLARE_TLV_DB_SCALE(eq_db_scale, -2400, 100, 0); | 3709 | static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(eq_db_scale, -2400, 100, 0); |
3073 | 3710 | ||
3074 | static int add_tuning_control(struct hda_codec *codec, | 3711 | static int add_tuning_control(struct hda_codec *codec, |
3075 | hda_nid_t pnid, hda_nid_t nid, | 3712 | hda_nid_t pnid, hda_nid_t nid, |
@@ -3207,7 +3844,7 @@ static int ca0132_select_out(struct hda_codec *codec) | |||
3207 | pin_ctl & ~PIN_HP); | 3844 | pin_ctl & ~PIN_HP); |
3208 | /* enable speaker node */ | 3845 | /* enable speaker node */ |
3209 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, | 3846 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, |
3210 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 3847 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
3211 | snd_hda_set_pin_ctl(codec, spec->out_pins[0], | 3848 | snd_hda_set_pin_ctl(codec, spec->out_pins[0], |
3212 | pin_ctl | PIN_OUT); | 3849 | pin_ctl | PIN_OUT); |
3213 | } else { | 3850 | } else { |
@@ -3251,13 +3888,209 @@ exit: | |||
3251 | return err < 0 ? err : 0; | 3888 | return err < 0 ? err : 0; |
3252 | } | 3889 | } |
3253 | 3890 | ||
3891 | /* | ||
3892 | * This function behaves similarly to the ca0132_select_out funciton above, | ||
3893 | * except with a few differences. It adds the ability to select the current | ||
3894 | * output with an enumerated control "output source" if the auto detect | ||
3895 | * mute switch is set to off. If the auto detect mute switch is enabled, it | ||
3896 | * will detect either headphone or lineout(SPEAKER_OUT) from jack detection. | ||
3897 | * It also adds the ability to auto-detect the front headphone port. The only | ||
3898 | * way to select surround is to disable auto detect, and set Surround with the | ||
3899 | * enumerated control. | ||
3900 | */ | ||
3901 | static int ca0132_alt_select_out(struct hda_codec *codec) | ||
3902 | { | ||
3903 | struct ca0132_spec *spec = codec->spec; | ||
3904 | unsigned int pin_ctl; | ||
3905 | int jack_present; | ||
3906 | int auto_jack; | ||
3907 | unsigned int i; | ||
3908 | unsigned int tmp; | ||
3909 | int err; | ||
3910 | /* Default Headphone is rear headphone */ | ||
3911 | hda_nid_t headphone_nid = spec->out_pins[1]; | ||
3912 | |||
3913 | codec_dbg(codec, "%s\n", __func__); | ||
3914 | |||
3915 | snd_hda_power_up_pm(codec); | ||
3916 | |||
3917 | auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; | ||
3918 | |||
3919 | /* | ||
3920 | * If headphone rear or front is plugged in, set to headphone. | ||
3921 | * If neither is plugged in, set to rear line out. Only if | ||
3922 | * hp/speaker auto detect is enabled. | ||
3923 | */ | ||
3924 | if (auto_jack) { | ||
3925 | jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_hp) || | ||
3926 | snd_hda_jack_detect(codec, spec->unsol_tag_front_hp); | ||
3927 | |||
3928 | if (jack_present) | ||
3929 | spec->cur_out_type = HEADPHONE_OUT; | ||
3930 | else | ||
3931 | spec->cur_out_type = SPEAKER_OUT; | ||
3932 | } else | ||
3933 | spec->cur_out_type = spec->out_enum_val; | ||
3934 | |||
3935 | /* Begin DSP output switch */ | ||
3936 | tmp = FLOAT_ONE; | ||
3937 | err = dspio_set_uint_param(codec, 0x96, 0x3A, tmp); | ||
3938 | if (err < 0) | ||
3939 | goto exit; | ||
3940 | |||
3941 | switch (spec->cur_out_type) { | ||
3942 | case SPEAKER_OUT: | ||
3943 | codec_dbg(codec, "%s speaker\n", __func__); | ||
3944 | /*speaker out config*/ | ||
3945 | switch (spec->quirk) { | ||
3946 | case QUIRK_SBZ: | ||
3947 | writew(0x0007, spec->mem_base + 0x320); | ||
3948 | writew(0x0104, spec->mem_base + 0x320); | ||
3949 | writew(0x0101, spec->mem_base + 0x320); | ||
3950 | chipio_set_control_param(codec, 0x0D, 0x18); | ||
3951 | break; | ||
3952 | case QUIRK_R3DI: | ||
3953 | chipio_set_control_param(codec, 0x0D, 0x24); | ||
3954 | r3di_gpio_out_set(codec, R3DI_LINE_OUT); | ||
3955 | break; | ||
3956 | } | ||
3957 | |||
3958 | /* disable headphone node */ | ||
3959 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0, | ||
3960 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
3961 | snd_hda_set_pin_ctl(codec, spec->out_pins[1], | ||
3962 | pin_ctl & ~PIN_HP); | ||
3963 | /* enable line-out node */ | ||
3964 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, | ||
3965 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
3966 | snd_hda_set_pin_ctl(codec, spec->out_pins[0], | ||
3967 | pin_ctl | PIN_OUT); | ||
3968 | /* Enable EAPD */ | ||
3969 | snd_hda_codec_write(codec, spec->out_pins[0], 0, | ||
3970 | AC_VERB_SET_EAPD_BTLENABLE, 0x01); | ||
3971 | |||
3972 | /* If PlayEnhancement is enabled, set different source */ | ||
3973 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) | ||
3974 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); | ||
3975 | else | ||
3976 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT); | ||
3977 | break; | ||
3978 | case HEADPHONE_OUT: | ||
3979 | codec_dbg(codec, "%s hp\n", __func__); | ||
3980 | /* Headphone out config*/ | ||
3981 | switch (spec->quirk) { | ||
3982 | case QUIRK_SBZ: | ||
3983 | writew(0x0107, spec->mem_base + 0x320); | ||
3984 | writew(0x0104, spec->mem_base + 0x320); | ||
3985 | writew(0x0001, spec->mem_base + 0x320); | ||
3986 | chipio_set_control_param(codec, 0x0D, 0x12); | ||
3987 | break; | ||
3988 | case QUIRK_R3DI: | ||
3989 | chipio_set_control_param(codec, 0x0D, 0x21); | ||
3990 | r3di_gpio_out_set(codec, R3DI_HEADPHONE_OUT); | ||
3991 | break; | ||
3992 | } | ||
3993 | |||
3994 | snd_hda_codec_write(codec, spec->out_pins[0], 0, | ||
3995 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); | ||
3996 | |||
3997 | /* disable speaker*/ | ||
3998 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, | ||
3999 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4000 | snd_hda_set_pin_ctl(codec, spec->out_pins[0], | ||
4001 | pin_ctl & ~PIN_HP); | ||
4002 | |||
4003 | /* enable headphone, either front or rear */ | ||
4004 | |||
4005 | if (snd_hda_jack_detect(codec, spec->unsol_tag_front_hp)) | ||
4006 | headphone_nid = spec->out_pins[2]; | ||
4007 | else if (snd_hda_jack_detect(codec, spec->unsol_tag_hp)) | ||
4008 | headphone_nid = spec->out_pins[1]; | ||
4009 | |||
4010 | pin_ctl = snd_hda_codec_read(codec, headphone_nid, 0, | ||
4011 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4012 | snd_hda_set_pin_ctl(codec, headphone_nid, | ||
4013 | pin_ctl | PIN_HP); | ||
4014 | |||
4015 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) | ||
4016 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); | ||
4017 | else | ||
4018 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO); | ||
4019 | break; | ||
4020 | case SURROUND_OUT: | ||
4021 | codec_dbg(codec, "%s surround\n", __func__); | ||
4022 | /* Surround out config*/ | ||
4023 | switch (spec->quirk) { | ||
4024 | case QUIRK_SBZ: | ||
4025 | writew(0x0007, spec->mem_base + 0x320); | ||
4026 | writew(0x0104, spec->mem_base + 0x320); | ||
4027 | writew(0x0101, spec->mem_base + 0x320); | ||
4028 | chipio_set_control_param(codec, 0x0D, 0x18); | ||
4029 | break; | ||
4030 | case QUIRK_R3DI: | ||
4031 | chipio_set_control_param(codec, 0x0D, 0x24); | ||
4032 | r3di_gpio_out_set(codec, R3DI_LINE_OUT); | ||
4033 | break; | ||
4034 | } | ||
4035 | /* enable line out node */ | ||
4036 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, | ||
4037 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4038 | snd_hda_set_pin_ctl(codec, spec->out_pins[0], | ||
4039 | pin_ctl | PIN_OUT); | ||
4040 | /* Disable headphone out */ | ||
4041 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0, | ||
4042 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4043 | snd_hda_set_pin_ctl(codec, spec->out_pins[1], | ||
4044 | pin_ctl & ~PIN_HP); | ||
4045 | /* Enable EAPD on line out */ | ||
4046 | snd_hda_codec_write(codec, spec->out_pins[0], 0, | ||
4047 | AC_VERB_SET_EAPD_BTLENABLE, 0x01); | ||
4048 | /* enable center/lfe out node */ | ||
4049 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[2], 0, | ||
4050 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4051 | snd_hda_set_pin_ctl(codec, spec->out_pins[2], | ||
4052 | pin_ctl | PIN_OUT); | ||
4053 | /* Now set rear surround node as out. */ | ||
4054 | pin_ctl = snd_hda_codec_read(codec, spec->out_pins[3], 0, | ||
4055 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4056 | snd_hda_set_pin_ctl(codec, spec->out_pins[3], | ||
4057 | pin_ctl | PIN_OUT); | ||
4058 | |||
4059 | if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) | ||
4060 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); | ||
4061 | else | ||
4062 | dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT); | ||
4063 | break; | ||
4064 | } | ||
4065 | |||
4066 | /* run through the output dsp commands for line-out */ | ||
4067 | for (i = 0; i < alt_out_presets[spec->cur_out_type].commands; i++) { | ||
4068 | err = dspio_set_uint_param(codec, | ||
4069 | alt_out_presets[spec->cur_out_type].mids[i], | ||
4070 | alt_out_presets[spec->cur_out_type].reqs[i], | ||
4071 | alt_out_presets[spec->cur_out_type].vals[i]); | ||
4072 | |||
4073 | if (err < 0) | ||
4074 | goto exit; | ||
4075 | } | ||
4076 | |||
4077 | exit: | ||
4078 | snd_hda_power_down_pm(codec); | ||
4079 | |||
4080 | return err < 0 ? err : 0; | ||
4081 | } | ||
4082 | |||
3254 | static void ca0132_unsol_hp_delayed(struct work_struct *work) | 4083 | static void ca0132_unsol_hp_delayed(struct work_struct *work) |
3255 | { | 4084 | { |
3256 | struct ca0132_spec *spec = container_of( | 4085 | struct ca0132_spec *spec = container_of( |
3257 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); | 4086 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); |
3258 | struct hda_jack_tbl *jack; | 4087 | struct hda_jack_tbl *jack; |
3259 | 4088 | ||
3260 | ca0132_select_out(spec->codec); | 4089 | if (spec->use_alt_functions) |
4090 | ca0132_alt_select_out(spec->codec); | ||
4091 | else | ||
4092 | ca0132_select_out(spec->codec); | ||
4093 | |||
3261 | jack = snd_hda_jack_tbl_get(spec->codec, spec->unsol_tag_hp); | 4094 | jack = snd_hda_jack_tbl_get(spec->codec, spec->unsol_tag_hp); |
3262 | if (jack) { | 4095 | if (jack) { |
3263 | jack->block_report = 0; | 4096 | jack->block_report = 0; |
@@ -3268,6 +4101,10 @@ static void ca0132_unsol_hp_delayed(struct work_struct *work) | |||
3268 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); | 4101 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); |
3269 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); | 4102 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val); |
3270 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); | 4103 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); |
4104 | static void resume_mic1(struct hda_codec *codec, unsigned int oldval); | ||
4105 | static int stop_mic1(struct hda_codec *codec); | ||
4106 | static int ca0132_cvoice_switch_set(struct hda_codec *codec); | ||
4107 | static int ca0132_alt_mic_boost_set(struct hda_codec *codec, long val); | ||
3271 | 4108 | ||
3272 | /* | 4109 | /* |
3273 | * Select the active VIP source | 4110 | * Select the active VIP source |
@@ -3310,6 +4147,71 @@ static int ca0132_set_vipsource(struct hda_codec *codec, int val) | |||
3310 | return 1; | 4147 | return 1; |
3311 | } | 4148 | } |
3312 | 4149 | ||
4150 | static int ca0132_alt_set_vipsource(struct hda_codec *codec, int val) | ||
4151 | { | ||
4152 | struct ca0132_spec *spec = codec->spec; | ||
4153 | unsigned int tmp; | ||
4154 | |||
4155 | if (spec->dsp_state != DSP_DOWNLOADED) | ||
4156 | return 0; | ||
4157 | |||
4158 | codec_dbg(codec, "%s\n", __func__); | ||
4159 | |||
4160 | chipio_set_stream_control(codec, 0x03, 0); | ||
4161 | chipio_set_stream_control(codec, 0x04, 0); | ||
4162 | |||
4163 | /* if CrystalVoice is off, vipsource should be 0 */ | ||
4164 | if (!spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] || | ||
4165 | (val == 0) || spec->in_enum_val == REAR_LINE_IN) { | ||
4166 | codec_dbg(codec, "%s: off.", __func__); | ||
4167 | chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0); | ||
4168 | |||
4169 | tmp = FLOAT_ZERO; | ||
4170 | dspio_set_uint_param(codec, 0x80, 0x05, tmp); | ||
4171 | |||
4172 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | ||
4173 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
4174 | if (spec->quirk == QUIRK_R3DI) | ||
4175 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
4176 | |||
4177 | |||
4178 | if (spec->in_enum_val == REAR_LINE_IN) | ||
4179 | tmp = FLOAT_ZERO; | ||
4180 | else { | ||
4181 | if (spec->quirk == QUIRK_SBZ) | ||
4182 | tmp = FLOAT_THREE; | ||
4183 | else | ||
4184 | tmp = FLOAT_ONE; | ||
4185 | } | ||
4186 | |||
4187 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
4188 | |||
4189 | } else { | ||
4190 | codec_dbg(codec, "%s: on.", __func__); | ||
4191 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000); | ||
4192 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000); | ||
4193 | if (spec->quirk == QUIRK_R3DI) | ||
4194 | chipio_set_conn_rate(codec, 0x0F, SR_16_000); | ||
4195 | |||
4196 | if (spec->effects_switch[VOICE_FOCUS - EFFECT_START_NID]) | ||
4197 | tmp = FLOAT_TWO; | ||
4198 | else | ||
4199 | tmp = FLOAT_ONE; | ||
4200 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
4201 | |||
4202 | tmp = FLOAT_ONE; | ||
4203 | dspio_set_uint_param(codec, 0x80, 0x05, tmp); | ||
4204 | |||
4205 | msleep(20); | ||
4206 | chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, val); | ||
4207 | } | ||
4208 | |||
4209 | chipio_set_stream_control(codec, 0x03, 1); | ||
4210 | chipio_set_stream_control(codec, 0x04, 1); | ||
4211 | |||
4212 | return 1; | ||
4213 | } | ||
4214 | |||
3313 | /* | 4215 | /* |
3314 | * Select the active microphone. | 4216 | * Select the active microphone. |
3315 | * If autodetect is enabled, mic will be selected based on jack detection. | 4217 | * If autodetect is enabled, mic will be selected based on jack detection. |
@@ -3363,6 +4265,125 @@ static int ca0132_select_mic(struct hda_codec *codec) | |||
3363 | } | 4265 | } |
3364 | 4266 | ||
3365 | /* | 4267 | /* |
4268 | * Select the active input. | ||
4269 | * Mic detection isn't used, because it's kind of pointless on the SBZ. | ||
4270 | * The front mic has no jack-detection, so the only way to switch to it | ||
4271 | * is to do it manually in alsamixer. | ||
4272 | */ | ||
4273 | static int ca0132_alt_select_in(struct hda_codec *codec) | ||
4274 | { | ||
4275 | struct ca0132_spec *spec = codec->spec; | ||
4276 | unsigned int tmp; | ||
4277 | |||
4278 | codec_dbg(codec, "%s\n", __func__); | ||
4279 | |||
4280 | snd_hda_power_up_pm(codec); | ||
4281 | |||
4282 | chipio_set_stream_control(codec, 0x03, 0); | ||
4283 | chipio_set_stream_control(codec, 0x04, 0); | ||
4284 | |||
4285 | spec->cur_mic_type = spec->in_enum_val; | ||
4286 | |||
4287 | switch (spec->cur_mic_type) { | ||
4288 | case REAR_MIC: | ||
4289 | switch (spec->quirk) { | ||
4290 | case QUIRK_SBZ: | ||
4291 | writew(0x0000, spec->mem_base + 0x320); | ||
4292 | tmp = FLOAT_THREE; | ||
4293 | break; | ||
4294 | case QUIRK_R3DI: | ||
4295 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); | ||
4296 | tmp = FLOAT_ONE; | ||
4297 | break; | ||
4298 | default: | ||
4299 | tmp = FLOAT_ONE; | ||
4300 | break; | ||
4301 | } | ||
4302 | |||
4303 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | ||
4304 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
4305 | if (spec->quirk == QUIRK_R3DI) | ||
4306 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
4307 | |||
4308 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
4309 | |||
4310 | chipio_set_stream_control(codec, 0x03, 1); | ||
4311 | chipio_set_stream_control(codec, 0x04, 1); | ||
4312 | |||
4313 | if (spec->quirk == QUIRK_SBZ) { | ||
4314 | chipio_write(codec, 0x18B098, 0x0000000C); | ||
4315 | chipio_write(codec, 0x18B09C, 0x0000000C); | ||
4316 | } | ||
4317 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); | ||
4318 | break; | ||
4319 | case REAR_LINE_IN: | ||
4320 | ca0132_mic_boost_set(codec, 0); | ||
4321 | switch (spec->quirk) { | ||
4322 | case QUIRK_SBZ: | ||
4323 | writew(0x0000, spec->mem_base + 0x320); | ||
4324 | break; | ||
4325 | case QUIRK_R3DI: | ||
4326 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); | ||
4327 | break; | ||
4328 | } | ||
4329 | |||
4330 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | ||
4331 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
4332 | if (spec->quirk == QUIRK_R3DI) | ||
4333 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
4334 | |||
4335 | tmp = FLOAT_ZERO; | ||
4336 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
4337 | |||
4338 | if (spec->quirk == QUIRK_SBZ) { | ||
4339 | chipio_write(codec, 0x18B098, 0x00000000); | ||
4340 | chipio_write(codec, 0x18B09C, 0x00000000); | ||
4341 | } | ||
4342 | |||
4343 | chipio_set_stream_control(codec, 0x03, 1); | ||
4344 | chipio_set_stream_control(codec, 0x04, 1); | ||
4345 | break; | ||
4346 | case FRONT_MIC: | ||
4347 | switch (spec->quirk) { | ||
4348 | case QUIRK_SBZ: | ||
4349 | writew(0x0100, spec->mem_base + 0x320); | ||
4350 | writew(0x0005, spec->mem_base + 0x320); | ||
4351 | tmp = FLOAT_THREE; | ||
4352 | break; | ||
4353 | case QUIRK_R3DI: | ||
4354 | r3di_gpio_mic_set(codec, R3DI_FRONT_MIC); | ||
4355 | tmp = FLOAT_ONE; | ||
4356 | break; | ||
4357 | default: | ||
4358 | tmp = FLOAT_ONE; | ||
4359 | break; | ||
4360 | } | ||
4361 | |||
4362 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | ||
4363 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
4364 | if (spec->quirk == QUIRK_R3DI) | ||
4365 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
4366 | |||
4367 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
4368 | |||
4369 | chipio_set_stream_control(codec, 0x03, 1); | ||
4370 | chipio_set_stream_control(codec, 0x04, 1); | ||
4371 | |||
4372 | if (spec->quirk == QUIRK_SBZ) { | ||
4373 | chipio_write(codec, 0x18B098, 0x0000000C); | ||
4374 | chipio_write(codec, 0x18B09C, 0x000000CC); | ||
4375 | } | ||
4376 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); | ||
4377 | break; | ||
4378 | } | ||
4379 | ca0132_cvoice_switch_set(codec); | ||
4380 | |||
4381 | snd_hda_power_down_pm(codec); | ||
4382 | return 0; | ||
4383 | |||
4384 | } | ||
4385 | |||
4386 | /* | ||
3366 | * Check if VNODE settings take effect immediately. | 4387 | * Check if VNODE settings take effect immediately. |
3367 | */ | 4388 | */ |
3368 | static bool ca0132_is_vnode_effective(struct hda_codec *codec, | 4389 | static bool ca0132_is_vnode_effective(struct hda_codec *codec, |
@@ -3418,7 +4439,7 @@ static int ca0132_voicefx_set(struct hda_codec *codec, int enable) | |||
3418 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) | 4439 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) |
3419 | { | 4440 | { |
3420 | struct ca0132_spec *spec = codec->spec; | 4441 | struct ca0132_spec *spec = codec->spec; |
3421 | unsigned int on; | 4442 | unsigned int on, tmp; |
3422 | int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; | 4443 | int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; |
3423 | int err = 0; | 4444 | int err = 0; |
3424 | int idx = nid - EFFECT_START_NID; | 4445 | int idx = nid - EFFECT_START_NID; |
@@ -3442,6 +4463,46 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) | |||
3442 | /* Voice Focus applies to 2-ch Mic, Digital Mic */ | 4463 | /* Voice Focus applies to 2-ch Mic, Digital Mic */ |
3443 | if ((nid == VOICE_FOCUS) && (spec->cur_mic_type != DIGITAL_MIC)) | 4464 | if ((nid == VOICE_FOCUS) && (spec->cur_mic_type != DIGITAL_MIC)) |
3444 | val = 0; | 4465 | val = 0; |
4466 | |||
4467 | /* If Voice Focus on SBZ, set to two channel. */ | ||
4468 | if ((nid == VOICE_FOCUS) && (spec->quirk == QUIRK_SBZ) | ||
4469 | && (spec->cur_mic_type != REAR_LINE_IN)) { | ||
4470 | if (spec->effects_switch[CRYSTAL_VOICE - | ||
4471 | EFFECT_START_NID]) { | ||
4472 | |||
4473 | if (spec->effects_switch[VOICE_FOCUS - | ||
4474 | EFFECT_START_NID]) { | ||
4475 | tmp = FLOAT_TWO; | ||
4476 | val = 1; | ||
4477 | } else | ||
4478 | tmp = FLOAT_ONE; | ||
4479 | |||
4480 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
4481 | } | ||
4482 | } | ||
4483 | /* | ||
4484 | * For SBZ noise reduction, there's an extra command | ||
4485 | * to module ID 0x47. No clue why. | ||
4486 | */ | ||
4487 | if ((nid == NOISE_REDUCTION) && (spec->quirk == QUIRK_SBZ) | ||
4488 | && (spec->cur_mic_type != REAR_LINE_IN)) { | ||
4489 | if (spec->effects_switch[CRYSTAL_VOICE - | ||
4490 | EFFECT_START_NID]) { | ||
4491 | if (spec->effects_switch[NOISE_REDUCTION - | ||
4492 | EFFECT_START_NID]) | ||
4493 | tmp = FLOAT_ONE; | ||
4494 | else | ||
4495 | tmp = FLOAT_ZERO; | ||
4496 | } else | ||
4497 | tmp = FLOAT_ZERO; | ||
4498 | |||
4499 | dspio_set_uint_param(codec, 0x47, 0x00, tmp); | ||
4500 | } | ||
4501 | |||
4502 | /* If rear line in disable effects. */ | ||
4503 | if (spec->use_alt_functions && | ||
4504 | spec->in_enum_val == REAR_LINE_IN) | ||
4505 | val = 0; | ||
3445 | } | 4506 | } |
3446 | 4507 | ||
3447 | codec_dbg(codec, "ca0132_effect_set: nid=0x%x, val=%ld\n", | 4508 | codec_dbg(codec, "ca0132_effect_set: nid=0x%x, val=%ld\n", |
@@ -3469,6 +4530,9 @@ static int ca0132_pe_switch_set(struct hda_codec *codec) | |||
3469 | codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n", | 4530 | codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n", |
3470 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]); | 4531 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]); |
3471 | 4532 | ||
4533 | if (spec->use_alt_functions) | ||
4534 | ca0132_alt_select_out(codec); | ||
4535 | |||
3472 | i = OUT_EFFECT_START_NID - EFFECT_START_NID; | 4536 | i = OUT_EFFECT_START_NID - EFFECT_START_NID; |
3473 | nid = OUT_EFFECT_START_NID; | 4537 | nid = OUT_EFFECT_START_NID; |
3474 | /* PE affects all out effects */ | 4538 | /* PE affects all out effects */ |
@@ -3526,7 +4590,10 @@ static int ca0132_cvoice_switch_set(struct hda_codec *codec) | |||
3526 | 4590 | ||
3527 | /* set correct vipsource */ | 4591 | /* set correct vipsource */ |
3528 | oldval = stop_mic1(codec); | 4592 | oldval = stop_mic1(codec); |
3529 | ret |= ca0132_set_vipsource(codec, 1); | 4593 | if (spec->use_alt_functions) |
4594 | ret |= ca0132_alt_set_vipsource(codec, 1); | ||
4595 | else | ||
4596 | ret |= ca0132_set_vipsource(codec, 1); | ||
3530 | resume_mic1(codec, oldval); | 4597 | resume_mic1(codec, oldval); |
3531 | return ret; | 4598 | return ret; |
3532 | } | 4599 | } |
@@ -3546,6 +4613,16 @@ static int ca0132_mic_boost_set(struct hda_codec *codec, long val) | |||
3546 | return ret; | 4613 | return ret; |
3547 | } | 4614 | } |
3548 | 4615 | ||
4616 | static int ca0132_alt_mic_boost_set(struct hda_codec *codec, long val) | ||
4617 | { | ||
4618 | struct ca0132_spec *spec = codec->spec; | ||
4619 | int ret = 0; | ||
4620 | |||
4621 | ret = snd_hda_codec_amp_update(codec, spec->input_pins[0], 0, | ||
4622 | HDA_INPUT, 0, HDA_AMP_VOLMASK, val); | ||
4623 | return ret; | ||
4624 | } | ||
4625 | |||
3549 | static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, | 4626 | static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, |
3550 | struct snd_ctl_elem_value *ucontrol) | 4627 | struct snd_ctl_elem_value *ucontrol) |
3551 | { | 4628 | { |
@@ -3560,8 +4637,12 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, | |||
3560 | if (nid == VNID_HP_SEL) { | 4637 | if (nid == VNID_HP_SEL) { |
3561 | auto_jack = | 4638 | auto_jack = |
3562 | spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; | 4639 | spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; |
3563 | if (!auto_jack) | 4640 | if (!auto_jack) { |
3564 | ca0132_select_out(codec); | 4641 | if (spec->use_alt_functions) |
4642 | ca0132_alt_select_out(codec); | ||
4643 | else | ||
4644 | ca0132_select_out(codec); | ||
4645 | } | ||
3565 | return 1; | 4646 | return 1; |
3566 | } | 4647 | } |
3567 | 4648 | ||
@@ -3574,7 +4655,10 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, | |||
3574 | } | 4655 | } |
3575 | 4656 | ||
3576 | if (nid == VNID_HP_ASEL) { | 4657 | if (nid == VNID_HP_ASEL) { |
3577 | ca0132_select_out(codec); | 4658 | if (spec->use_alt_functions) |
4659 | ca0132_alt_select_out(codec); | ||
4660 | else | ||
4661 | ca0132_select_out(codec); | ||
3578 | return 1; | 4662 | return 1; |
3579 | } | 4663 | } |
3580 | 4664 | ||
@@ -3602,6 +4686,432 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, | |||
3602 | return ret; | 4686 | return ret; |
3603 | } | 4687 | } |
3604 | /* End of control change helpers. */ | 4688 | /* End of control change helpers. */ |
4689 | /* | ||
4690 | * Below I've added controls to mess with the effect levels, I've only enabled | ||
4691 | * them on the Sound Blaster Z, but they would probably also work on the | ||
4692 | * Chromebook. I figured they were probably tuned specifically for it, and left | ||
4693 | * out for a reason. | ||
4694 | */ | ||
4695 | |||
4696 | /* Sets DSP effect level from the sliders above the controls */ | ||
4697 | static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid, | ||
4698 | const unsigned int *lookup, int idx) | ||
4699 | { | ||
4700 | int i = 0; | ||
4701 | unsigned int y; | ||
4702 | /* | ||
4703 | * For X_BASS, req 2 is actually crossover freq instead of | ||
4704 | * effect level | ||
4705 | */ | ||
4706 | if (nid == X_BASS) | ||
4707 | y = 2; | ||
4708 | else | ||
4709 | y = 1; | ||
4710 | |||
4711 | snd_hda_power_up(codec); | ||
4712 | if (nid == XBASS_XOVER) { | ||
4713 | for (i = 0; i < OUT_EFFECTS_COUNT; i++) | ||
4714 | if (ca0132_effects[i].nid == X_BASS) | ||
4715 | break; | ||
4716 | |||
4717 | dspio_set_param(codec, ca0132_effects[i].mid, 0x20, | ||
4718 | ca0132_effects[i].reqs[1], | ||
4719 | &(lookup[idx - 1]), sizeof(unsigned int)); | ||
4720 | } else { | ||
4721 | /* Find the actual effect structure */ | ||
4722 | for (i = 0; i < OUT_EFFECTS_COUNT; i++) | ||
4723 | if (nid == ca0132_effects[i].nid) | ||
4724 | break; | ||
4725 | |||
4726 | dspio_set_param(codec, ca0132_effects[i].mid, 0x20, | ||
4727 | ca0132_effects[i].reqs[y], | ||
4728 | &(lookup[idx]), sizeof(unsigned int)); | ||
4729 | } | ||
4730 | |||
4731 | snd_hda_power_down(codec); | ||
4732 | |||
4733 | return 0; | ||
4734 | } | ||
4735 | |||
4736 | static int ca0132_alt_xbass_xover_slider_ctl_get(struct snd_kcontrol *kcontrol, | ||
4737 | struct snd_ctl_elem_value *ucontrol) | ||
4738 | { | ||
4739 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4740 | struct ca0132_spec *spec = codec->spec; | ||
4741 | long *valp = ucontrol->value.integer.value; | ||
4742 | |||
4743 | *valp = spec->xbass_xover_freq; | ||
4744 | return 0; | ||
4745 | } | ||
4746 | |||
4747 | static int ca0132_alt_slider_ctl_get(struct snd_kcontrol *kcontrol, | ||
4748 | struct snd_ctl_elem_value *ucontrol) | ||
4749 | { | ||
4750 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4751 | struct ca0132_spec *spec = codec->spec; | ||
4752 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
4753 | long *valp = ucontrol->value.integer.value; | ||
4754 | int idx = nid - OUT_EFFECT_START_NID; | ||
4755 | |||
4756 | *valp = spec->fx_ctl_val[idx]; | ||
4757 | return 0; | ||
4758 | } | ||
4759 | |||
4760 | /* | ||
4761 | * The X-bass crossover starts at 10hz, so the min is 1. The | ||
4762 | * frequency is set in multiples of 10. | ||
4763 | */ | ||
4764 | static int ca0132_alt_xbass_xover_slider_info(struct snd_kcontrol *kcontrol, | ||
4765 | struct snd_ctl_elem_info *uinfo) | ||
4766 | { | ||
4767 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
4768 | uinfo->count = 1; | ||
4769 | uinfo->value.integer.min = 1; | ||
4770 | uinfo->value.integer.max = 100; | ||
4771 | uinfo->value.integer.step = 1; | ||
4772 | |||
4773 | return 0; | ||
4774 | } | ||
4775 | |||
4776 | static int ca0132_alt_effect_slider_info(struct snd_kcontrol *kcontrol, | ||
4777 | struct snd_ctl_elem_info *uinfo) | ||
4778 | { | ||
4779 | int chs = get_amp_channels(kcontrol); | ||
4780 | |||
4781 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
4782 | uinfo->count = chs == 3 ? 2 : 1; | ||
4783 | uinfo->value.integer.min = 0; | ||
4784 | uinfo->value.integer.max = 100; | ||
4785 | uinfo->value.integer.step = 1; | ||
4786 | |||
4787 | return 0; | ||
4788 | } | ||
4789 | |||
4790 | static int ca0132_alt_xbass_xover_slider_put(struct snd_kcontrol *kcontrol, | ||
4791 | struct snd_ctl_elem_value *ucontrol) | ||
4792 | { | ||
4793 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4794 | struct ca0132_spec *spec = codec->spec; | ||
4795 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
4796 | long *valp = ucontrol->value.integer.value; | ||
4797 | int idx; | ||
4798 | |||
4799 | /* any change? */ | ||
4800 | if (spec->xbass_xover_freq == *valp) | ||
4801 | return 0; | ||
4802 | |||
4803 | spec->xbass_xover_freq = *valp; | ||
4804 | |||
4805 | idx = *valp; | ||
4806 | ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx); | ||
4807 | |||
4808 | return 0; | ||
4809 | } | ||
4810 | |||
4811 | static int ca0132_alt_effect_slider_put(struct snd_kcontrol *kcontrol, | ||
4812 | struct snd_ctl_elem_value *ucontrol) | ||
4813 | { | ||
4814 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4815 | struct ca0132_spec *spec = codec->spec; | ||
4816 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
4817 | long *valp = ucontrol->value.integer.value; | ||
4818 | int idx; | ||
4819 | |||
4820 | idx = nid - EFFECT_START_NID; | ||
4821 | /* any change? */ | ||
4822 | if (spec->fx_ctl_val[idx] == *valp) | ||
4823 | return 0; | ||
4824 | |||
4825 | spec->fx_ctl_val[idx] = *valp; | ||
4826 | |||
4827 | idx = *valp; | ||
4828 | ca0132_alt_slider_ctl_set(codec, nid, float_zero_to_one_lookup, idx); | ||
4829 | |||
4830 | return 0; | ||
4831 | } | ||
4832 | |||
4833 | |||
4834 | /* | ||
4835 | * Mic Boost Enum for alternative ca0132 codecs. I didn't like that the original | ||
4836 | * only has off or full 30 dB, and didn't like making a volume slider that has | ||
4837 | * traditional 0-100 in alsamixer that goes in big steps. I like enum better. | ||
4838 | */ | ||
4839 | #define MIC_BOOST_NUM_OF_STEPS 4 | ||
4840 | #define MIC_BOOST_ENUM_MAX_STRLEN 10 | ||
4841 | |||
4842 | static int ca0132_alt_mic_boost_info(struct snd_kcontrol *kcontrol, | ||
4843 | struct snd_ctl_elem_info *uinfo) | ||
4844 | { | ||
4845 | char *sfx = "dB"; | ||
4846 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
4847 | |||
4848 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
4849 | uinfo->count = 1; | ||
4850 | uinfo->value.enumerated.items = MIC_BOOST_NUM_OF_STEPS; | ||
4851 | if (uinfo->value.enumerated.item >= MIC_BOOST_NUM_OF_STEPS) | ||
4852 | uinfo->value.enumerated.item = MIC_BOOST_NUM_OF_STEPS - 1; | ||
4853 | sprintf(namestr, "%d %s", (uinfo->value.enumerated.item * 10), sfx); | ||
4854 | strcpy(uinfo->value.enumerated.name, namestr); | ||
4855 | return 0; | ||
4856 | } | ||
4857 | |||
4858 | static int ca0132_alt_mic_boost_get(struct snd_kcontrol *kcontrol, | ||
4859 | struct snd_ctl_elem_value *ucontrol) | ||
4860 | { | ||
4861 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4862 | struct ca0132_spec *spec = codec->spec; | ||
4863 | |||
4864 | ucontrol->value.enumerated.item[0] = spec->mic_boost_enum_val; | ||
4865 | return 0; | ||
4866 | } | ||
4867 | |||
4868 | static int ca0132_alt_mic_boost_put(struct snd_kcontrol *kcontrol, | ||
4869 | struct snd_ctl_elem_value *ucontrol) | ||
4870 | { | ||
4871 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4872 | struct ca0132_spec *spec = codec->spec; | ||
4873 | int sel = ucontrol->value.enumerated.item[0]; | ||
4874 | unsigned int items = MIC_BOOST_NUM_OF_STEPS; | ||
4875 | |||
4876 | if (sel >= items) | ||
4877 | return 0; | ||
4878 | |||
4879 | codec_dbg(codec, "ca0132_alt_mic_boost: boost=%d\n", | ||
4880 | sel); | ||
4881 | |||
4882 | spec->mic_boost_enum_val = sel; | ||
4883 | |||
4884 | if (spec->in_enum_val != REAR_LINE_IN) | ||
4885 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); | ||
4886 | |||
4887 | return 1; | ||
4888 | } | ||
4889 | |||
4890 | |||
4891 | /* | ||
4892 | * Input Select Control for alternative ca0132 codecs. This exists because | ||
4893 | * front microphone has no auto-detect, and we need a way to set the rear | ||
4894 | * as line-in | ||
4895 | */ | ||
4896 | static int ca0132_alt_input_source_info(struct snd_kcontrol *kcontrol, | ||
4897 | struct snd_ctl_elem_info *uinfo) | ||
4898 | { | ||
4899 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
4900 | uinfo->count = 1; | ||
4901 | uinfo->value.enumerated.items = IN_SRC_NUM_OF_INPUTS; | ||
4902 | if (uinfo->value.enumerated.item >= IN_SRC_NUM_OF_INPUTS) | ||
4903 | uinfo->value.enumerated.item = IN_SRC_NUM_OF_INPUTS - 1; | ||
4904 | strcpy(uinfo->value.enumerated.name, | ||
4905 | in_src_str[uinfo->value.enumerated.item]); | ||
4906 | return 0; | ||
4907 | } | ||
4908 | |||
4909 | static int ca0132_alt_input_source_get(struct snd_kcontrol *kcontrol, | ||
4910 | struct snd_ctl_elem_value *ucontrol) | ||
4911 | { | ||
4912 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4913 | struct ca0132_spec *spec = codec->spec; | ||
4914 | |||
4915 | ucontrol->value.enumerated.item[0] = spec->in_enum_val; | ||
4916 | return 0; | ||
4917 | } | ||
4918 | |||
4919 | static int ca0132_alt_input_source_put(struct snd_kcontrol *kcontrol, | ||
4920 | struct snd_ctl_elem_value *ucontrol) | ||
4921 | { | ||
4922 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4923 | struct ca0132_spec *spec = codec->spec; | ||
4924 | int sel = ucontrol->value.enumerated.item[0]; | ||
4925 | unsigned int items = IN_SRC_NUM_OF_INPUTS; | ||
4926 | |||
4927 | if (sel >= items) | ||
4928 | return 0; | ||
4929 | |||
4930 | codec_dbg(codec, "ca0132_alt_input_select: sel=%d, preset=%s\n", | ||
4931 | sel, in_src_str[sel]); | ||
4932 | |||
4933 | spec->in_enum_val = sel; | ||
4934 | |||
4935 | ca0132_alt_select_in(codec); | ||
4936 | |||
4937 | return 1; | ||
4938 | } | ||
4939 | |||
4940 | /* Sound Blaster Z Output Select Control */ | ||
4941 | static int ca0132_alt_output_select_get_info(struct snd_kcontrol *kcontrol, | ||
4942 | struct snd_ctl_elem_info *uinfo) | ||
4943 | { | ||
4944 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
4945 | uinfo->count = 1; | ||
4946 | uinfo->value.enumerated.items = NUM_OF_OUTPUTS; | ||
4947 | if (uinfo->value.enumerated.item >= NUM_OF_OUTPUTS) | ||
4948 | uinfo->value.enumerated.item = NUM_OF_OUTPUTS - 1; | ||
4949 | strcpy(uinfo->value.enumerated.name, | ||
4950 | alt_out_presets[uinfo->value.enumerated.item].name); | ||
4951 | return 0; | ||
4952 | } | ||
4953 | |||
4954 | static int ca0132_alt_output_select_get(struct snd_kcontrol *kcontrol, | ||
4955 | struct snd_ctl_elem_value *ucontrol) | ||
4956 | { | ||
4957 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4958 | struct ca0132_spec *spec = codec->spec; | ||
4959 | |||
4960 | ucontrol->value.enumerated.item[0] = spec->out_enum_val; | ||
4961 | return 0; | ||
4962 | } | ||
4963 | |||
4964 | static int ca0132_alt_output_select_put(struct snd_kcontrol *kcontrol, | ||
4965 | struct snd_ctl_elem_value *ucontrol) | ||
4966 | { | ||
4967 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
4968 | struct ca0132_spec *spec = codec->spec; | ||
4969 | int sel = ucontrol->value.enumerated.item[0]; | ||
4970 | unsigned int items = NUM_OF_OUTPUTS; | ||
4971 | unsigned int auto_jack; | ||
4972 | |||
4973 | if (sel >= items) | ||
4974 | return 0; | ||
4975 | |||
4976 | codec_dbg(codec, "ca0132_alt_output_select: sel=%d, preset=%s\n", | ||
4977 | sel, alt_out_presets[sel].name); | ||
4978 | |||
4979 | spec->out_enum_val = sel; | ||
4980 | |||
4981 | auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; | ||
4982 | |||
4983 | if (!auto_jack) | ||
4984 | ca0132_alt_select_out(codec); | ||
4985 | |||
4986 | return 1; | ||
4987 | } | ||
4988 | |||
4989 | /* | ||
4990 | * Smart Volume output setting control. Three different settings, Normal, | ||
4991 | * which takes the value from the smart volume slider. The two others, loud | ||
4992 | * and night, disregard the slider value and have uneditable values. | ||
4993 | */ | ||
4994 | #define NUM_OF_SVM_SETTINGS 3 | ||
4995 | static const char *const out_svm_set_enum_str[3] = {"Normal", "Loud", "Night" }; | ||
4996 | |||
4997 | static int ca0132_alt_svm_setting_info(struct snd_kcontrol *kcontrol, | ||
4998 | struct snd_ctl_elem_info *uinfo) | ||
4999 | { | ||
5000 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
5001 | uinfo->count = 1; | ||
5002 | uinfo->value.enumerated.items = NUM_OF_SVM_SETTINGS; | ||
5003 | if (uinfo->value.enumerated.item >= NUM_OF_SVM_SETTINGS) | ||
5004 | uinfo->value.enumerated.item = NUM_OF_SVM_SETTINGS - 1; | ||
5005 | strcpy(uinfo->value.enumerated.name, | ||
5006 | out_svm_set_enum_str[uinfo->value.enumerated.item]); | ||
5007 | return 0; | ||
5008 | } | ||
5009 | |||
5010 | static int ca0132_alt_svm_setting_get(struct snd_kcontrol *kcontrol, | ||
5011 | struct snd_ctl_elem_value *ucontrol) | ||
5012 | { | ||
5013 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5014 | struct ca0132_spec *spec = codec->spec; | ||
5015 | |||
5016 | ucontrol->value.enumerated.item[0] = spec->smart_volume_setting; | ||
5017 | return 0; | ||
5018 | } | ||
5019 | |||
5020 | static int ca0132_alt_svm_setting_put(struct snd_kcontrol *kcontrol, | ||
5021 | struct snd_ctl_elem_value *ucontrol) | ||
5022 | { | ||
5023 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5024 | struct ca0132_spec *spec = codec->spec; | ||
5025 | int sel = ucontrol->value.enumerated.item[0]; | ||
5026 | unsigned int items = NUM_OF_SVM_SETTINGS; | ||
5027 | unsigned int idx = SMART_VOLUME - EFFECT_START_NID; | ||
5028 | unsigned int tmp; | ||
5029 | |||
5030 | if (sel >= items) | ||
5031 | return 0; | ||
5032 | |||
5033 | codec_dbg(codec, "ca0132_alt_svm_setting: sel=%d, preset=%s\n", | ||
5034 | sel, out_svm_set_enum_str[sel]); | ||
5035 | |||
5036 | spec->smart_volume_setting = sel; | ||
5037 | |||
5038 | switch (sel) { | ||
5039 | case 0: | ||
5040 | tmp = FLOAT_ZERO; | ||
5041 | break; | ||
5042 | case 1: | ||
5043 | tmp = FLOAT_ONE; | ||
5044 | break; | ||
5045 | case 2: | ||
5046 | tmp = FLOAT_TWO; | ||
5047 | break; | ||
5048 | default: | ||
5049 | tmp = FLOAT_ZERO; | ||
5050 | break; | ||
5051 | } | ||
5052 | /* Req 2 is the Smart Volume Setting req. */ | ||
5053 | dspio_set_uint_param(codec, ca0132_effects[idx].mid, | ||
5054 | ca0132_effects[idx].reqs[2], tmp); | ||
5055 | return 1; | ||
5056 | } | ||
5057 | |||
5058 | /* Sound Blaster Z EQ preset controls */ | ||
5059 | static int ca0132_alt_eq_preset_info(struct snd_kcontrol *kcontrol, | ||
5060 | struct snd_ctl_elem_info *uinfo) | ||
5061 | { | ||
5062 | unsigned int items = ARRAY_SIZE(ca0132_alt_eq_presets); | ||
5063 | |||
5064 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
5065 | uinfo->count = 1; | ||
5066 | uinfo->value.enumerated.items = items; | ||
5067 | if (uinfo->value.enumerated.item >= items) | ||
5068 | uinfo->value.enumerated.item = items - 1; | ||
5069 | strcpy(uinfo->value.enumerated.name, | ||
5070 | ca0132_alt_eq_presets[uinfo->value.enumerated.item].name); | ||
5071 | return 0; | ||
5072 | } | ||
5073 | |||
5074 | static int ca0132_alt_eq_preset_get(struct snd_kcontrol *kcontrol, | ||
5075 | struct snd_ctl_elem_value *ucontrol) | ||
5076 | { | ||
5077 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5078 | struct ca0132_spec *spec = codec->spec; | ||
5079 | |||
5080 | ucontrol->value.enumerated.item[0] = spec->eq_preset_val; | ||
5081 | return 0; | ||
5082 | } | ||
5083 | |||
5084 | static int ca0132_alt_eq_preset_put(struct snd_kcontrol *kcontrol, | ||
5085 | struct snd_ctl_elem_value *ucontrol) | ||
5086 | { | ||
5087 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5088 | struct ca0132_spec *spec = codec->spec; | ||
5089 | int i, err = 0; | ||
5090 | int sel = ucontrol->value.enumerated.item[0]; | ||
5091 | unsigned int items = ARRAY_SIZE(ca0132_alt_eq_presets); | ||
5092 | |||
5093 | if (sel >= items) | ||
5094 | return 0; | ||
5095 | |||
5096 | codec_dbg(codec, "%s: sel=%d, preset=%s\n", __func__, sel, | ||
5097 | ca0132_alt_eq_presets[sel].name); | ||
5098 | /* | ||
5099 | * Idx 0 is default. | ||
5100 | * Default needs to qualify with CrystalVoice state. | ||
5101 | */ | ||
5102 | for (i = 0; i < EQ_PRESET_MAX_PARAM_COUNT; i++) { | ||
5103 | err = dspio_set_uint_param(codec, ca0132_alt_eq_enum.mid, | ||
5104 | ca0132_alt_eq_enum.reqs[i], | ||
5105 | ca0132_alt_eq_presets[sel].vals[i]); | ||
5106 | if (err < 0) | ||
5107 | break; | ||
5108 | } | ||
5109 | |||
5110 | if (err >= 0) | ||
5111 | spec->eq_preset_val = sel; | ||
5112 | |||
5113 | return 1; | ||
5114 | } | ||
3605 | 5115 | ||
3606 | static int ca0132_voicefx_info(struct snd_kcontrol *kcontrol, | 5116 | static int ca0132_voicefx_info(struct snd_kcontrol *kcontrol, |
3607 | struct snd_ctl_elem_info *uinfo) | 5117 | struct snd_ctl_elem_info *uinfo) |
@@ -3753,10 +5263,15 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, | |||
3753 | /* mic boost */ | 5263 | /* mic boost */ |
3754 | if (nid == spec->input_pins[0]) { | 5264 | if (nid == spec->input_pins[0]) { |
3755 | spec->cur_mic_boost = *valp; | 5265 | spec->cur_mic_boost = *valp; |
5266 | if (spec->use_alt_functions) { | ||
5267 | if (spec->in_enum_val != REAR_LINE_IN) | ||
5268 | changed = ca0132_mic_boost_set(codec, *valp); | ||
5269 | } else { | ||
5270 | /* Mic boost does not apply to Digital Mic */ | ||
5271 | if (spec->cur_mic_type != DIGITAL_MIC) | ||
5272 | changed = ca0132_mic_boost_set(codec, *valp); | ||
5273 | } | ||
3756 | 5274 | ||
3757 | /* Mic boost does not apply to Digital Mic */ | ||
3758 | if (spec->cur_mic_type != DIGITAL_MIC) | ||
3759 | changed = ca0132_mic_boost_set(codec, *valp); | ||
3760 | goto exit; | 5275 | goto exit; |
3761 | } | 5276 | } |
3762 | 5277 | ||
@@ -3768,6 +5283,41 @@ exit: | |||
3768 | /* | 5283 | /* |
3769 | * Volume related | 5284 | * Volume related |
3770 | */ | 5285 | */ |
5286 | /* | ||
5287 | * Sets the internal DSP decibel level to match the DAC for output, and the | ||
5288 | * ADC for input. Currently only the SBZ sets dsp capture volume level, and | ||
5289 | * all alternative codecs set DSP playback volume. | ||
5290 | */ | ||
5291 | static void ca0132_alt_dsp_volume_put(struct hda_codec *codec, hda_nid_t nid) | ||
5292 | { | ||
5293 | struct ca0132_spec *spec = codec->spec; | ||
5294 | unsigned int dsp_dir; | ||
5295 | unsigned int lookup_val; | ||
5296 | |||
5297 | if (nid == VNID_SPK) | ||
5298 | dsp_dir = DSP_VOL_OUT; | ||
5299 | else | ||
5300 | dsp_dir = DSP_VOL_IN; | ||
5301 | |||
5302 | lookup_val = spec->vnode_lvol[nid - VNODE_START_NID]; | ||
5303 | |||
5304 | dspio_set_uint_param(codec, | ||
5305 | ca0132_alt_vol_ctls[dsp_dir].mid, | ||
5306 | ca0132_alt_vol_ctls[dsp_dir].reqs[0], | ||
5307 | float_vol_db_lookup[lookup_val]); | ||
5308 | |||
5309 | lookup_val = spec->vnode_rvol[nid - VNODE_START_NID]; | ||
5310 | |||
5311 | dspio_set_uint_param(codec, | ||
5312 | ca0132_alt_vol_ctls[dsp_dir].mid, | ||
5313 | ca0132_alt_vol_ctls[dsp_dir].reqs[1], | ||
5314 | float_vol_db_lookup[lookup_val]); | ||
5315 | |||
5316 | dspio_set_uint_param(codec, | ||
5317 | ca0132_alt_vol_ctls[dsp_dir].mid, | ||
5318 | ca0132_alt_vol_ctls[dsp_dir].reqs[2], FLOAT_ZERO); | ||
5319 | } | ||
5320 | |||
3771 | static int ca0132_volume_info(struct snd_kcontrol *kcontrol, | 5321 | static int ca0132_volume_info(struct snd_kcontrol *kcontrol, |
3772 | struct snd_ctl_elem_info *uinfo) | 5322 | struct snd_ctl_elem_info *uinfo) |
3773 | { | 5323 | { |
@@ -3869,6 +5419,51 @@ static int ca0132_volume_put(struct snd_kcontrol *kcontrol, | |||
3869 | return changed; | 5419 | return changed; |
3870 | } | 5420 | } |
3871 | 5421 | ||
5422 | /* | ||
5423 | * This function is the same as the one above, because using an if statement | ||
5424 | * inside of the above volume control for the DSP volume would cause too much | ||
5425 | * lag. This is a lot more smooth. | ||
5426 | */ | ||
5427 | static int ca0132_alt_volume_put(struct snd_kcontrol *kcontrol, | ||
5428 | struct snd_ctl_elem_value *ucontrol) | ||
5429 | { | ||
5430 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5431 | struct ca0132_spec *spec = codec->spec; | ||
5432 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
5433 | int ch = get_amp_channels(kcontrol); | ||
5434 | long *valp = ucontrol->value.integer.value; | ||
5435 | hda_nid_t vnid = 0; | ||
5436 | int changed = 1; | ||
5437 | |||
5438 | switch (nid) { | ||
5439 | case 0x02: | ||
5440 | vnid = VNID_SPK; | ||
5441 | break; | ||
5442 | case 0x07: | ||
5443 | vnid = VNID_MIC; | ||
5444 | break; | ||
5445 | } | ||
5446 | |||
5447 | /* store the left and right volume */ | ||
5448 | if (ch & 1) { | ||
5449 | spec->vnode_lvol[vnid - VNODE_START_NID] = *valp; | ||
5450 | valp++; | ||
5451 | } | ||
5452 | if (ch & 2) { | ||
5453 | spec->vnode_rvol[vnid - VNODE_START_NID] = *valp; | ||
5454 | valp++; | ||
5455 | } | ||
5456 | |||
5457 | snd_hda_power_up(codec); | ||
5458 | ca0132_alt_dsp_volume_put(codec, vnid); | ||
5459 | mutex_lock(&codec->control_mutex); | ||
5460 | changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); | ||
5461 | mutex_unlock(&codec->control_mutex); | ||
5462 | snd_hda_power_down(codec); | ||
5463 | |||
5464 | return changed; | ||
5465 | } | ||
5466 | |||
3872 | static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 5467 | static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
3873 | unsigned int size, unsigned int __user *tlv) | 5468 | unsigned int size, unsigned int __user *tlv) |
3874 | { | 5469 | { |
@@ -3907,14 +5502,59 @@ static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
3907 | return err; | 5502 | return err; |
3908 | } | 5503 | } |
3909 | 5504 | ||
5505 | /* Add volume slider control for effect level */ | ||
5506 | static int ca0132_alt_add_effect_slider(struct hda_codec *codec, hda_nid_t nid, | ||
5507 | const char *pfx, int dir) | ||
5508 | { | ||
5509 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | ||
5510 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | ||
5511 | struct snd_kcontrol_new knew = | ||
5512 | HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type); | ||
5513 | |||
5514 | sprintf(namestr, "FX: %s %s Volume", pfx, dirstr[dir]); | ||
5515 | |||
5516 | knew.tlv.c = 0; | ||
5517 | knew.tlv.p = 0; | ||
5518 | |||
5519 | switch (nid) { | ||
5520 | case XBASS_XOVER: | ||
5521 | knew.info = ca0132_alt_xbass_xover_slider_info; | ||
5522 | knew.get = ca0132_alt_xbass_xover_slider_ctl_get; | ||
5523 | knew.put = ca0132_alt_xbass_xover_slider_put; | ||
5524 | break; | ||
5525 | default: | ||
5526 | knew.info = ca0132_alt_effect_slider_info; | ||
5527 | knew.get = ca0132_alt_slider_ctl_get; | ||
5528 | knew.put = ca0132_alt_effect_slider_put; | ||
5529 | knew.private_value = | ||
5530 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, type); | ||
5531 | break; | ||
5532 | } | ||
5533 | |||
5534 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
5535 | } | ||
5536 | |||
5537 | /* | ||
5538 | * Added FX: prefix for the alternative codecs, because otherwise the surround | ||
5539 | * effect would conflict with the Surround sound volume control. Also seems more | ||
5540 | * clear as to what the switches do. Left alone for others. | ||
5541 | */ | ||
3910 | static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid, | 5542 | static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid, |
3911 | const char *pfx, int dir) | 5543 | const char *pfx, int dir) |
3912 | { | 5544 | { |
5545 | struct ca0132_spec *spec = codec->spec; | ||
3913 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | 5546 | char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
3914 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | 5547 | int type = dir ? HDA_INPUT : HDA_OUTPUT; |
3915 | struct snd_kcontrol_new knew = | 5548 | struct snd_kcontrol_new knew = |
3916 | CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type); | 5549 | CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type); |
3917 | sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); | 5550 | /* If using alt_controls, add FX: prefix. But, don't add FX: |
5551 | * prefix to OutFX or InFX enable controls. | ||
5552 | */ | ||
5553 | if ((spec->use_alt_controls) && (nid <= IN_EFFECT_END_NID)) | ||
5554 | sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]); | ||
5555 | else | ||
5556 | sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); | ||
5557 | |||
3918 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | 5558 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); |
3919 | } | 5559 | } |
3920 | 5560 | ||
@@ -3929,11 +5569,141 @@ static int add_voicefx(struct hda_codec *codec) | |||
3929 | return snd_hda_ctl_add(codec, VOICEFX, snd_ctl_new1(&knew, codec)); | 5569 | return snd_hda_ctl_add(codec, VOICEFX, snd_ctl_new1(&knew, codec)); |
3930 | } | 5570 | } |
3931 | 5571 | ||
5572 | /* Create the EQ Preset control */ | ||
5573 | static int add_ca0132_alt_eq_presets(struct hda_codec *codec) | ||
5574 | { | ||
5575 | struct snd_kcontrol_new knew = | ||
5576 | HDA_CODEC_MUTE_MONO(ca0132_alt_eq_enum.name, | ||
5577 | EQ_PRESET_ENUM, 1, 0, HDA_OUTPUT); | ||
5578 | knew.info = ca0132_alt_eq_preset_info; | ||
5579 | knew.get = ca0132_alt_eq_preset_get; | ||
5580 | knew.put = ca0132_alt_eq_preset_put; | ||
5581 | return snd_hda_ctl_add(codec, EQ_PRESET_ENUM, | ||
5582 | snd_ctl_new1(&knew, codec)); | ||
5583 | } | ||
5584 | |||
5585 | /* | ||
5586 | * Add enumerated control for the three different settings of the smart volume | ||
5587 | * output effect. Normal just uses the slider value, and loud and night are | ||
5588 | * their own things that ignore that value. | ||
5589 | */ | ||
5590 | static int ca0132_alt_add_svm_enum(struct hda_codec *codec) | ||
5591 | { | ||
5592 | struct snd_kcontrol_new knew = | ||
5593 | HDA_CODEC_MUTE_MONO("FX: Smart Volume Setting", | ||
5594 | SMART_VOLUME_ENUM, 1, 0, HDA_OUTPUT); | ||
5595 | knew.info = ca0132_alt_svm_setting_info; | ||
5596 | knew.get = ca0132_alt_svm_setting_get; | ||
5597 | knew.put = ca0132_alt_svm_setting_put; | ||
5598 | return snd_hda_ctl_add(codec, SMART_VOLUME_ENUM, | ||
5599 | snd_ctl_new1(&knew, codec)); | ||
5600 | |||
5601 | } | ||
5602 | |||
5603 | /* | ||
5604 | * Create an Output Select enumerated control for codecs with surround | ||
5605 | * out capabilities. | ||
5606 | */ | ||
5607 | static int ca0132_alt_add_output_enum(struct hda_codec *codec) | ||
5608 | { | ||
5609 | struct snd_kcontrol_new knew = | ||
5610 | HDA_CODEC_MUTE_MONO("Output Select", | ||
5611 | OUTPUT_SOURCE_ENUM, 1, 0, HDA_OUTPUT); | ||
5612 | knew.info = ca0132_alt_output_select_get_info; | ||
5613 | knew.get = ca0132_alt_output_select_get; | ||
5614 | knew.put = ca0132_alt_output_select_put; | ||
5615 | return snd_hda_ctl_add(codec, OUTPUT_SOURCE_ENUM, | ||
5616 | snd_ctl_new1(&knew, codec)); | ||
5617 | } | ||
5618 | |||
5619 | /* | ||
5620 | * Create an Input Source enumerated control for the alternate ca0132 codecs | ||
5621 | * because the front microphone has no auto-detect, and Line-in has to be set | ||
5622 | * somehow. | ||
5623 | */ | ||
5624 | static int ca0132_alt_add_input_enum(struct hda_codec *codec) | ||
5625 | { | ||
5626 | struct snd_kcontrol_new knew = | ||
5627 | HDA_CODEC_MUTE_MONO("Input Source", | ||
5628 | INPUT_SOURCE_ENUM, 1, 0, HDA_INPUT); | ||
5629 | knew.info = ca0132_alt_input_source_info; | ||
5630 | knew.get = ca0132_alt_input_source_get; | ||
5631 | knew.put = ca0132_alt_input_source_put; | ||
5632 | return snd_hda_ctl_add(codec, INPUT_SOURCE_ENUM, | ||
5633 | snd_ctl_new1(&knew, codec)); | ||
5634 | } | ||
5635 | |||
5636 | /* | ||
5637 | * Add mic boost enumerated control. Switches through 0dB to 30dB. This adds | ||
5638 | * more control than the original mic boost, which is either full 30dB or off. | ||
5639 | */ | ||
5640 | static int ca0132_alt_add_mic_boost_enum(struct hda_codec *codec) | ||
5641 | { | ||
5642 | struct snd_kcontrol_new knew = | ||
5643 | HDA_CODEC_MUTE_MONO("Mic Boost Capture Switch", | ||
5644 | MIC_BOOST_ENUM, 1, 0, HDA_INPUT); | ||
5645 | knew.info = ca0132_alt_mic_boost_info; | ||
5646 | knew.get = ca0132_alt_mic_boost_get; | ||
5647 | knew.put = ca0132_alt_mic_boost_put; | ||
5648 | return snd_hda_ctl_add(codec, MIC_BOOST_ENUM, | ||
5649 | snd_ctl_new1(&knew, codec)); | ||
5650 | |||
5651 | } | ||
5652 | |||
5653 | /* | ||
5654 | * Need to create slave controls for the alternate codecs that have surround | ||
5655 | * capabilities. | ||
5656 | */ | ||
5657 | static const char * const ca0132_alt_slave_pfxs[] = { | ||
5658 | "Front", "Surround", "Center", "LFE", NULL, | ||
5659 | }; | ||
5660 | |||
5661 | /* | ||
5662 | * Also need special channel map, because the default one is incorrect. | ||
5663 | * I think this has to do with the pin for rear surround being 0x11, | ||
5664 | * and the center/lfe being 0x10. Usually the pin order is the opposite. | ||
5665 | */ | ||
5666 | const struct snd_pcm_chmap_elem ca0132_alt_chmaps[] = { | ||
5667 | { .channels = 2, | ||
5668 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, | ||
5669 | { .channels = 4, | ||
5670 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
5671 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
5672 | { .channels = 6, | ||
5673 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
5674 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE, | ||
5675 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
5676 | { } | ||
5677 | }; | ||
5678 | |||
5679 | /* Add the correct chmap for streams with 6 channels. */ | ||
5680 | static void ca0132_alt_add_chmap_ctls(struct hda_codec *codec) | ||
5681 | { | ||
5682 | int err = 0; | ||
5683 | struct hda_pcm *pcm; | ||
5684 | |||
5685 | list_for_each_entry(pcm, &codec->pcm_list_head, list) { | ||
5686 | struct hda_pcm_stream *hinfo = | ||
5687 | &pcm->stream[SNDRV_PCM_STREAM_PLAYBACK]; | ||
5688 | struct snd_pcm_chmap *chmap; | ||
5689 | const struct snd_pcm_chmap_elem *elem; | ||
5690 | |||
5691 | elem = ca0132_alt_chmaps; | ||
5692 | if (hinfo->channels_max == 6) { | ||
5693 | err = snd_pcm_add_chmap_ctls(pcm->pcm, | ||
5694 | SNDRV_PCM_STREAM_PLAYBACK, | ||
5695 | elem, hinfo->channels_max, 0, &chmap); | ||
5696 | if (err < 0) | ||
5697 | codec_dbg(codec, "snd_pcm_add_chmap_ctls failed!"); | ||
5698 | } | ||
5699 | } | ||
5700 | } | ||
5701 | |||
3932 | /* | 5702 | /* |
3933 | * When changing Node IDs for Mixer Controls below, make sure to update | 5703 | * When changing Node IDs for Mixer Controls below, make sure to update |
3934 | * Node IDs in ca0132_config() as well. | 5704 | * Node IDs in ca0132_config() as well. |
3935 | */ | 5705 | */ |
3936 | static struct snd_kcontrol_new ca0132_mixer[] = { | 5706 | static const struct snd_kcontrol_new ca0132_mixer[] = { |
3937 | CA0132_CODEC_VOL("Master Playback Volume", VNID_SPK, HDA_OUTPUT), | 5707 | CA0132_CODEC_VOL("Master Playback Volume", VNID_SPK, HDA_OUTPUT), |
3938 | CA0132_CODEC_MUTE("Master Playback Switch", VNID_SPK, HDA_OUTPUT), | 5708 | CA0132_CODEC_MUTE("Master Playback Switch", VNID_SPK, HDA_OUTPUT), |
3939 | CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT), | 5709 | CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT), |
@@ -3955,10 +5725,55 @@ static struct snd_kcontrol_new ca0132_mixer[] = { | |||
3955 | { } /* end */ | 5725 | { } /* end */ |
3956 | }; | 5726 | }; |
3957 | 5727 | ||
5728 | /* | ||
5729 | * SBZ specific control mixer. Removes auto-detect for mic, and adds surround | ||
5730 | * controls. Also sets both the Front Playback and Capture Volume controls to | ||
5731 | * alt so they set the DSP's decibel level. | ||
5732 | */ | ||
5733 | static const struct snd_kcontrol_new sbz_mixer[] = { | ||
5734 | CA0132_ALT_CODEC_VOL("Front Playback Volume", 0x02, HDA_OUTPUT), | ||
5735 | CA0132_CODEC_MUTE("Front Playback Switch", VNID_SPK, HDA_OUTPUT), | ||
5736 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x04, 0, HDA_OUTPUT), | ||
5737 | HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0, HDA_OUTPUT), | ||
5738 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x03, 1, 0, HDA_OUTPUT), | ||
5739 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x03, 1, 0, HDA_OUTPUT), | ||
5740 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x03, 2, 0, HDA_OUTPUT), | ||
5741 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x03, 2, 0, HDA_OUTPUT), | ||
5742 | CA0132_ALT_CODEC_VOL("Capture Volume", 0x07, HDA_INPUT), | ||
5743 | CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT), | ||
5744 | HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT), | ||
5745 | HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT), | ||
5746 | CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch", | ||
5747 | VNID_HP_ASEL, 1, HDA_OUTPUT), | ||
5748 | { } /* end */ | ||
5749 | }; | ||
5750 | |||
5751 | /* | ||
5752 | * Same as the Sound Blaster Z, except doesn't use the alt volume for capture | ||
5753 | * because it doesn't set decibel levels for the DSP for capture. | ||
5754 | */ | ||
5755 | static const struct snd_kcontrol_new r3di_mixer[] = { | ||
5756 | CA0132_ALT_CODEC_VOL("Front Playback Volume", 0x02, HDA_OUTPUT), | ||
5757 | CA0132_CODEC_MUTE("Front Playback Switch", VNID_SPK, HDA_OUTPUT), | ||
5758 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x04, 0, HDA_OUTPUT), | ||
5759 | HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0, HDA_OUTPUT), | ||
5760 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x03, 1, 0, HDA_OUTPUT), | ||
5761 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x03, 1, 0, HDA_OUTPUT), | ||
5762 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x03, 2, 0, HDA_OUTPUT), | ||
5763 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x03, 2, 0, HDA_OUTPUT), | ||
5764 | CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT), | ||
5765 | CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT), | ||
5766 | HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT), | ||
5767 | HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT), | ||
5768 | CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch", | ||
5769 | VNID_HP_ASEL, 1, HDA_OUTPUT), | ||
5770 | { } /* end */ | ||
5771 | }; | ||
5772 | |||
3958 | static int ca0132_build_controls(struct hda_codec *codec) | 5773 | static int ca0132_build_controls(struct hda_codec *codec) |
3959 | { | 5774 | { |
3960 | struct ca0132_spec *spec = codec->spec; | 5775 | struct ca0132_spec *spec = codec->spec; |
3961 | int i, num_fx; | 5776 | int i, num_fx, num_sliders; |
3962 | int err = 0; | 5777 | int err = 0; |
3963 | 5778 | ||
3964 | /* Add Mixer controls */ | 5779 | /* Add Mixer controls */ |
@@ -3967,29 +5782,94 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
3967 | if (err < 0) | 5782 | if (err < 0) |
3968 | return err; | 5783 | return err; |
3969 | } | 5784 | } |
5785 | /* Setup vmaster with surround slaves for desktop ca0132 devices */ | ||
5786 | if (spec->use_alt_functions) { | ||
5787 | snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT, | ||
5788 | spec->tlv); | ||
5789 | snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
5790 | spec->tlv, ca0132_alt_slave_pfxs, | ||
5791 | "Playback Volume"); | ||
5792 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
5793 | NULL, ca0132_alt_slave_pfxs, | ||
5794 | "Playback Switch", | ||
5795 | true, &spec->vmaster_mute.sw_kctl); | ||
5796 | |||
5797 | } | ||
3970 | 5798 | ||
3971 | /* Add in and out effects controls. | 5799 | /* Add in and out effects controls. |
3972 | * VoiceFX, PE and CrystalVoice are added separately. | 5800 | * VoiceFX, PE and CrystalVoice are added separately. |
3973 | */ | 5801 | */ |
3974 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; | 5802 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; |
3975 | for (i = 0; i < num_fx; i++) { | 5803 | for (i = 0; i < num_fx; i++) { |
5804 | /* SBZ breaks if Echo Cancellation is used */ | ||
5805 | if (spec->quirk == QUIRK_SBZ) { | ||
5806 | if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID + | ||
5807 | OUT_EFFECTS_COUNT)) | ||
5808 | continue; | ||
5809 | } | ||
5810 | |||
3976 | err = add_fx_switch(codec, ca0132_effects[i].nid, | 5811 | err = add_fx_switch(codec, ca0132_effects[i].nid, |
3977 | ca0132_effects[i].name, | 5812 | ca0132_effects[i].name, |
3978 | ca0132_effects[i].direct); | 5813 | ca0132_effects[i].direct); |
3979 | if (err < 0) | 5814 | if (err < 0) |
3980 | return err; | 5815 | return err; |
3981 | } | 5816 | } |
5817 | /* | ||
5818 | * If codec has use_alt_controls set to true, add effect level sliders, | ||
5819 | * EQ presets, and Smart Volume presets. Also, change names to add FX | ||
5820 | * prefix, and change PlayEnhancement and CrystalVoice to match. | ||
5821 | */ | ||
5822 | if (spec->use_alt_controls) { | ||
5823 | ca0132_alt_add_svm_enum(codec); | ||
5824 | add_ca0132_alt_eq_presets(codec); | ||
5825 | err = add_fx_switch(codec, PLAY_ENHANCEMENT, | ||
5826 | "Enable OutFX", 0); | ||
5827 | if (err < 0) | ||
5828 | return err; | ||
3982 | 5829 | ||
3983 | err = add_fx_switch(codec, PLAY_ENHANCEMENT, "PlayEnhancement", 0); | 5830 | err = add_fx_switch(codec, CRYSTAL_VOICE, |
3984 | if (err < 0) | 5831 | "Enable InFX", 1); |
3985 | return err; | 5832 | if (err < 0) |
5833 | return err; | ||
3986 | 5834 | ||
3987 | err = add_fx_switch(codec, CRYSTAL_VOICE, "CrystalVoice", 1); | 5835 | num_sliders = OUT_EFFECTS_COUNT - 1; |
3988 | if (err < 0) | 5836 | for (i = 0; i < num_sliders; i++) { |
3989 | return err; | 5837 | err = ca0132_alt_add_effect_slider(codec, |
5838 | ca0132_effects[i].nid, | ||
5839 | ca0132_effects[i].name, | ||
5840 | ca0132_effects[i].direct); | ||
5841 | if (err < 0) | ||
5842 | return err; | ||
5843 | } | ||
5844 | |||
5845 | err = ca0132_alt_add_effect_slider(codec, XBASS_XOVER, | ||
5846 | "X-Bass Crossover", EFX_DIR_OUT); | ||
3990 | 5847 | ||
5848 | if (err < 0) | ||
5849 | return err; | ||
5850 | } else { | ||
5851 | err = add_fx_switch(codec, PLAY_ENHANCEMENT, | ||
5852 | "PlayEnhancement", 0); | ||
5853 | if (err < 0) | ||
5854 | return err; | ||
5855 | |||
5856 | err = add_fx_switch(codec, CRYSTAL_VOICE, | ||
5857 | "CrystalVoice", 1); | ||
5858 | if (err < 0) | ||
5859 | return err; | ||
5860 | } | ||
3991 | add_voicefx(codec); | 5861 | add_voicefx(codec); |
3992 | 5862 | ||
5863 | /* | ||
5864 | * If the codec uses alt_functions, you need the enumerated controls | ||
5865 | * to select the new outputs and inputs, plus add the new mic boost | ||
5866 | * setting control. | ||
5867 | */ | ||
5868 | if (spec->use_alt_functions) { | ||
5869 | ca0132_alt_add_output_enum(codec); | ||
5870 | ca0132_alt_add_input_enum(codec); | ||
5871 | ca0132_alt_add_mic_boost_enum(codec); | ||
5872 | } | ||
3993 | #ifdef ENABLE_TUNING_CONTROLS | 5873 | #ifdef ENABLE_TUNING_CONTROLS |
3994 | add_tuning_ctls(codec); | 5874 | add_tuning_ctls(codec); |
3995 | #endif | 5875 | #endif |
@@ -4014,6 +5894,10 @@ static int ca0132_build_controls(struct hda_codec *codec) | |||
4014 | if (err < 0) | 5894 | if (err < 0) |
4015 | return err; | 5895 | return err; |
4016 | } | 5896 | } |
5897 | |||
5898 | if (spec->use_alt_functions) | ||
5899 | ca0132_alt_add_chmap_ctls(codec); | ||
5900 | |||
4017 | return 0; | 5901 | return 0; |
4018 | } | 5902 | } |
4019 | 5903 | ||
@@ -4068,6 +5952,11 @@ static int ca0132_build_pcms(struct hda_codec *codec) | |||
4068 | info = snd_hda_codec_pcm_new(codec, "CA0132 Analog"); | 5952 | info = snd_hda_codec_pcm_new(codec, "CA0132 Analog"); |
4069 | if (!info) | 5953 | if (!info) |
4070 | return -ENOMEM; | 5954 | return -ENOMEM; |
5955 | if (spec->use_alt_functions) { | ||
5956 | info->own_chmap = true; | ||
5957 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap | ||
5958 | = ca0132_alt_chmaps; | ||
5959 | } | ||
4071 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback; | 5960 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback; |
4072 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0]; | 5961 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0]; |
4073 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | 5962 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = |
@@ -4076,12 +5965,16 @@ static int ca0132_build_pcms(struct hda_codec *codec) | |||
4076 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1; | 5965 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1; |
4077 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; | 5966 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; |
4078 | 5967 | ||
4079 | info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2"); | 5968 | /* With the DSP enabled, desktops don't use this ADC. */ |
4080 | if (!info) | 5969 | if (spec->use_alt_functions) { |
4081 | return -ENOMEM; | 5970 | info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2"); |
4082 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; | 5971 | if (!info) |
4083 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1; | 5972 | return -ENOMEM; |
4084 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1]; | 5973 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = |
5974 | ca0132_pcm_analog_capture; | ||
5975 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1; | ||
5976 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1]; | ||
5977 | } | ||
4085 | 5978 | ||
4086 | info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear"); | 5979 | info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear"); |
4087 | if (!info) | 5980 | if (!info) |
@@ -4288,6 +6181,196 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec) | |||
4288 | } | 6181 | } |
4289 | 6182 | ||
4290 | /* | 6183 | /* |
6184 | * Recon3Di r3di_setup_defaults sub functions. | ||
6185 | */ | ||
6186 | |||
6187 | static void r3di_dsp_scp_startup(struct hda_codec *codec) | ||
6188 | { | ||
6189 | unsigned int tmp; | ||
6190 | |||
6191 | tmp = 0x00000000; | ||
6192 | dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); | ||
6193 | |||
6194 | tmp = 0x00000001; | ||
6195 | dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); | ||
6196 | |||
6197 | tmp = 0x00000004; | ||
6198 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6199 | |||
6200 | tmp = 0x00000005; | ||
6201 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6202 | |||
6203 | tmp = 0x00000000; | ||
6204 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6205 | |||
6206 | } | ||
6207 | |||
6208 | static void r3di_dsp_initial_mic_setup(struct hda_codec *codec) | ||
6209 | { | ||
6210 | unsigned int tmp; | ||
6211 | |||
6212 | /* Mic 1 Setup */ | ||
6213 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | ||
6214 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
6215 | /* This ConnPointID is unique to Recon3Di. Haven't seen it elsewhere */ | ||
6216 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
6217 | tmp = FLOAT_ONE; | ||
6218 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
6219 | |||
6220 | /* Mic 2 Setup, even though it isn't connected on SBZ */ | ||
6221 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000); | ||
6222 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000); | ||
6223 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); | ||
6224 | tmp = FLOAT_ZERO; | ||
6225 | dspio_set_uint_param(codec, 0x80, 0x01, tmp); | ||
6226 | } | ||
6227 | |||
6228 | /* | ||
6229 | * Initialize Sound Blaster Z analog microphones. | ||
6230 | */ | ||
6231 | static void sbz_init_analog_mics(struct hda_codec *codec) | ||
6232 | { | ||
6233 | unsigned int tmp; | ||
6234 | |||
6235 | /* Mic 1 Setup */ | ||
6236 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | ||
6237 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
6238 | tmp = FLOAT_THREE; | ||
6239 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
6240 | |||
6241 | /* Mic 2 Setup, even though it isn't connected on SBZ */ | ||
6242 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000); | ||
6243 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000); | ||
6244 | tmp = FLOAT_ZERO; | ||
6245 | dspio_set_uint_param(codec, 0x80, 0x01, tmp); | ||
6246 | |||
6247 | } | ||
6248 | |||
6249 | /* | ||
6250 | * Sets the source of stream 0x14 to connpointID 0x48, and the destination | ||
6251 | * connpointID to 0x91. If this isn't done, the destination is 0x71, and | ||
6252 | * you get no sound. I'm guessing this has to do with the Sound Blaster Z | ||
6253 | * having an updated DAC, which changes the destination to that DAC. | ||
6254 | */ | ||
6255 | static void sbz_connect_streams(struct hda_codec *codec) | ||
6256 | { | ||
6257 | struct ca0132_spec *spec = codec->spec; | ||
6258 | |||
6259 | mutex_lock(&spec->chipio_mutex); | ||
6260 | |||
6261 | codec_dbg(codec, "Connect Streams entered, mutex locked and loaded.\n"); | ||
6262 | |||
6263 | chipio_set_stream_channels(codec, 0x0C, 6); | ||
6264 | chipio_set_stream_control(codec, 0x0C, 1); | ||
6265 | |||
6266 | /* This value is 0x43 for 96khz, and 0x83 for 192khz. */ | ||
6267 | chipio_write_no_mutex(codec, 0x18a020, 0x00000043); | ||
6268 | |||
6269 | /* Setup stream 0x14 with it's source and destination points */ | ||
6270 | chipio_set_stream_source_dest(codec, 0x14, 0x48, 0x91); | ||
6271 | chipio_set_conn_rate_no_mutex(codec, 0x48, SR_96_000); | ||
6272 | chipio_set_conn_rate_no_mutex(codec, 0x91, SR_96_000); | ||
6273 | chipio_set_stream_channels(codec, 0x14, 2); | ||
6274 | chipio_set_stream_control(codec, 0x14, 1); | ||
6275 | |||
6276 | codec_dbg(codec, "Connect Streams exited, mutex released.\n"); | ||
6277 | |||
6278 | mutex_unlock(&spec->chipio_mutex); | ||
6279 | |||
6280 | } | ||
6281 | |||
6282 | /* | ||
6283 | * Write data through ChipIO to setup proper stream destinations. | ||
6284 | * Not sure how it exactly works, but it seems to direct data | ||
6285 | * to different destinations. Example is f8 to c0, e0 to c0. | ||
6286 | * All I know is, if you don't set these, you get no sound. | ||
6287 | */ | ||
6288 | static void sbz_chipio_startup_data(struct hda_codec *codec) | ||
6289 | { | ||
6290 | struct ca0132_spec *spec = codec->spec; | ||
6291 | |||
6292 | mutex_lock(&spec->chipio_mutex); | ||
6293 | codec_dbg(codec, "Startup Data entered, mutex locked and loaded.\n"); | ||
6294 | |||
6295 | /* These control audio output */ | ||
6296 | chipio_write_no_mutex(codec, 0x190060, 0x0001f8c0); | ||
6297 | chipio_write_no_mutex(codec, 0x190064, 0x0001f9c1); | ||
6298 | chipio_write_no_mutex(codec, 0x190068, 0x0001fac6); | ||
6299 | chipio_write_no_mutex(codec, 0x19006c, 0x0001fbc7); | ||
6300 | /* Signal to update I think */ | ||
6301 | chipio_write_no_mutex(codec, 0x19042c, 0x00000001); | ||
6302 | |||
6303 | chipio_set_stream_channels(codec, 0x0C, 6); | ||
6304 | chipio_set_stream_control(codec, 0x0C, 1); | ||
6305 | /* No clue what these control */ | ||
6306 | chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0); | ||
6307 | chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1); | ||
6308 | chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2); | ||
6309 | chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3); | ||
6310 | chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4); | ||
6311 | chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5); | ||
6312 | chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6); | ||
6313 | chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7); | ||
6314 | chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8); | ||
6315 | chipio_write_no_mutex(codec, 0x190054, 0x0001edc9); | ||
6316 | chipio_write_no_mutex(codec, 0x190058, 0x0001eaca); | ||
6317 | chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb); | ||
6318 | |||
6319 | chipio_write_no_mutex(codec, 0x19042c, 0x00000001); | ||
6320 | |||
6321 | codec_dbg(codec, "Startup Data exited, mutex released.\n"); | ||
6322 | mutex_unlock(&spec->chipio_mutex); | ||
6323 | } | ||
6324 | |||
6325 | /* | ||
6326 | * Sound Blaster Z uses these after DSP is loaded. Weird SCP commands | ||
6327 | * without a 0x20 source like normal. | ||
6328 | */ | ||
6329 | static void sbz_dsp_scp_startup(struct hda_codec *codec) | ||
6330 | { | ||
6331 | unsigned int tmp; | ||
6332 | |||
6333 | tmp = 0x00000003; | ||
6334 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6335 | |||
6336 | tmp = 0x00000000; | ||
6337 | dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); | ||
6338 | |||
6339 | tmp = 0x00000001; | ||
6340 | dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); | ||
6341 | |||
6342 | tmp = 0x00000004; | ||
6343 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6344 | |||
6345 | tmp = 0x00000005; | ||
6346 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6347 | |||
6348 | tmp = 0x00000000; | ||
6349 | dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); | ||
6350 | |||
6351 | } | ||
6352 | |||
6353 | static void sbz_dsp_initial_mic_setup(struct hda_codec *codec) | ||
6354 | { | ||
6355 | unsigned int tmp; | ||
6356 | |||
6357 | chipio_set_stream_control(codec, 0x03, 0); | ||
6358 | chipio_set_stream_control(codec, 0x04, 0); | ||
6359 | |||
6360 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); | ||
6361 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); | ||
6362 | |||
6363 | tmp = FLOAT_THREE; | ||
6364 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); | ||
6365 | |||
6366 | chipio_set_stream_control(codec, 0x03, 1); | ||
6367 | chipio_set_stream_control(codec, 0x04, 1); | ||
6368 | |||
6369 | chipio_write(codec, 0x18b098, 0x0000000c); | ||
6370 | chipio_write(codec, 0x18b09C, 0x0000000c); | ||
6371 | } | ||
6372 | |||
6373 | /* | ||
4291 | * Setup default parameters for DSP | 6374 | * Setup default parameters for DSP |
4292 | */ | 6375 | */ |
4293 | static void ca0132_setup_defaults(struct hda_codec *codec) | 6376 | static void ca0132_setup_defaults(struct hda_codec *codec) |
@@ -4332,16 +6415,159 @@ static void ca0132_setup_defaults(struct hda_codec *codec) | |||
4332 | } | 6415 | } |
4333 | 6416 | ||
4334 | /* | 6417 | /* |
6418 | * Setup default parameters for Recon3Di DSP. | ||
6419 | */ | ||
6420 | |||
6421 | static void r3di_setup_defaults(struct hda_codec *codec) | ||
6422 | { | ||
6423 | struct ca0132_spec *spec = codec->spec; | ||
6424 | unsigned int tmp; | ||
6425 | int num_fx; | ||
6426 | int idx, i; | ||
6427 | |||
6428 | if (spec->dsp_state != DSP_DOWNLOADED) | ||
6429 | return; | ||
6430 | |||
6431 | r3di_dsp_scp_startup(codec); | ||
6432 | |||
6433 | r3di_dsp_initial_mic_setup(codec); | ||
6434 | |||
6435 | /*remove DSP headroom*/ | ||
6436 | tmp = FLOAT_ZERO; | ||
6437 | dspio_set_uint_param(codec, 0x96, 0x3C, tmp); | ||
6438 | |||
6439 | /* set WUH source */ | ||
6440 | tmp = FLOAT_TWO; | ||
6441 | dspio_set_uint_param(codec, 0x31, 0x00, tmp); | ||
6442 | chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); | ||
6443 | |||
6444 | /* Set speaker source? */ | ||
6445 | dspio_set_uint_param(codec, 0x32, 0x00, tmp); | ||
6446 | |||
6447 | r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED); | ||
6448 | |||
6449 | /* Setup effect defaults */ | ||
6450 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; | ||
6451 | for (idx = 0; idx < num_fx; idx++) { | ||
6452 | for (i = 0; i <= ca0132_effects[idx].params; i++) { | ||
6453 | dspio_set_uint_param(codec, | ||
6454 | ca0132_effects[idx].mid, | ||
6455 | ca0132_effects[idx].reqs[i], | ||
6456 | ca0132_effects[idx].def_vals[i]); | ||
6457 | } | ||
6458 | } | ||
6459 | |||
6460 | } | ||
6461 | |||
6462 | /* | ||
6463 | * Setup default parameters for the Sound Blaster Z DSP. A lot more going on | ||
6464 | * than the Chromebook setup. | ||
6465 | */ | ||
6466 | static void sbz_setup_defaults(struct hda_codec *codec) | ||
6467 | { | ||
6468 | struct ca0132_spec *spec = codec->spec; | ||
6469 | unsigned int tmp, stream_format; | ||
6470 | int num_fx; | ||
6471 | int idx, i; | ||
6472 | |||
6473 | if (spec->dsp_state != DSP_DOWNLOADED) | ||
6474 | return; | ||
6475 | |||
6476 | sbz_dsp_scp_startup(codec); | ||
6477 | |||
6478 | sbz_init_analog_mics(codec); | ||
6479 | |||
6480 | sbz_connect_streams(codec); | ||
6481 | |||
6482 | sbz_chipio_startup_data(codec); | ||
6483 | |||
6484 | chipio_set_stream_control(codec, 0x03, 1); | ||
6485 | chipio_set_stream_control(codec, 0x04, 1); | ||
6486 | |||
6487 | /* | ||
6488 | * Sets internal input loopback to off, used to have a switch to | ||
6489 | * enable input loopback, but turned out to be way too buggy. | ||
6490 | */ | ||
6491 | tmp = FLOAT_ONE; | ||
6492 | dspio_set_uint_param(codec, 0x37, 0x08, tmp); | ||
6493 | dspio_set_uint_param(codec, 0x37, 0x10, tmp); | ||
6494 | |||
6495 | /*remove DSP headroom*/ | ||
6496 | tmp = FLOAT_ZERO; | ||
6497 | dspio_set_uint_param(codec, 0x96, 0x3C, tmp); | ||
6498 | |||
6499 | /* set WUH source */ | ||
6500 | tmp = FLOAT_TWO; | ||
6501 | dspio_set_uint_param(codec, 0x31, 0x00, tmp); | ||
6502 | chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); | ||
6503 | |||
6504 | /* Set speaker source? */ | ||
6505 | dspio_set_uint_param(codec, 0x32, 0x00, tmp); | ||
6506 | |||
6507 | sbz_dsp_initial_mic_setup(codec); | ||
6508 | |||
6509 | |||
6510 | /* out, in effects + voicefx */ | ||
6511 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; | ||
6512 | for (idx = 0; idx < num_fx; idx++) { | ||
6513 | for (i = 0; i <= ca0132_effects[idx].params; i++) { | ||
6514 | dspio_set_uint_param(codec, | ||
6515 | ca0132_effects[idx].mid, | ||
6516 | ca0132_effects[idx].reqs[i], | ||
6517 | ca0132_effects[idx].def_vals[i]); | ||
6518 | } | ||
6519 | } | ||
6520 | |||
6521 | /* | ||
6522 | * Have to make a stream to bind the sound output to, otherwise | ||
6523 | * you'll get dead audio. Before I did this, it would bind to an | ||
6524 | * audio input, and would never work | ||
6525 | */ | ||
6526 | stream_format = snd_hdac_calc_stream_format(48000, 2, | ||
6527 | SNDRV_PCM_FORMAT_S32_LE, 32, 0); | ||
6528 | |||
6529 | snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, | ||
6530 | 0, stream_format); | ||
6531 | |||
6532 | snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); | ||
6533 | |||
6534 | snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, | ||
6535 | 0, stream_format); | ||
6536 | |||
6537 | snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); | ||
6538 | } | ||
6539 | |||
6540 | /* | ||
4335 | * Initialization of flags in chip | 6541 | * Initialization of flags in chip |
4336 | */ | 6542 | */ |
4337 | static void ca0132_init_flags(struct hda_codec *codec) | 6543 | static void ca0132_init_flags(struct hda_codec *codec) |
4338 | { | 6544 | { |
4339 | chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0); | 6545 | struct ca0132_spec *spec = codec->spec; |
4340 | chipio_set_control_flag(codec, CONTROL_FLAG_PORT_A_COMMON_MODE, 0); | 6546 | |
4341 | chipio_set_control_flag(codec, CONTROL_FLAG_PORT_D_COMMON_MODE, 0); | 6547 | if (spec->use_alt_functions) { |
4342 | chipio_set_control_flag(codec, CONTROL_FLAG_PORT_A_10KOHM_LOAD, 0); | 6548 | chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1); |
4343 | chipio_set_control_flag(codec, CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0); | 6549 | chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1); |
4344 | chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_HIGH_PASS, 1); | 6550 | chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1); |
6551 | chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_96KHZ, 1); | ||
6552 | chipio_set_control_flag(codec, CONTROL_FLAG_SRC_RATE_96KHZ, 1); | ||
6553 | chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0); | ||
6554 | chipio_set_control_flag(codec, CONTROL_FLAG_SPDIF2OUT, 0); | ||
6555 | chipio_set_control_flag(codec, | ||
6556 | CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0); | ||
6557 | chipio_set_control_flag(codec, | ||
6558 | CONTROL_FLAG_PORT_A_10KOHM_LOAD, 1); | ||
6559 | } else { | ||
6560 | chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0); | ||
6561 | chipio_set_control_flag(codec, | ||
6562 | CONTROL_FLAG_PORT_A_COMMON_MODE, 0); | ||
6563 | chipio_set_control_flag(codec, | ||
6564 | CONTROL_FLAG_PORT_D_COMMON_MODE, 0); | ||
6565 | chipio_set_control_flag(codec, | ||
6566 | CONTROL_FLAG_PORT_A_10KOHM_LOAD, 0); | ||
6567 | chipio_set_control_flag(codec, | ||
6568 | CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0); | ||
6569 | chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_HIGH_PASS, 1); | ||
6570 | } | ||
4345 | } | 6571 | } |
4346 | 6572 | ||
4347 | /* | 6573 | /* |
@@ -4349,6 +6575,16 @@ static void ca0132_init_flags(struct hda_codec *codec) | |||
4349 | */ | 6575 | */ |
4350 | static void ca0132_init_params(struct hda_codec *codec) | 6576 | static void ca0132_init_params(struct hda_codec *codec) |
4351 | { | 6577 | { |
6578 | struct ca0132_spec *spec = codec->spec; | ||
6579 | |||
6580 | if (spec->use_alt_functions) { | ||
6581 | chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); | ||
6582 | chipio_set_conn_rate(codec, 0x0B, SR_48_000); | ||
6583 | chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0); | ||
6584 | chipio_set_control_param(codec, 0, 0); | ||
6585 | chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0); | ||
6586 | } | ||
6587 | |||
4352 | chipio_set_control_param(codec, CONTROL_PARAM_PORTA_160OHM_GAIN, 6); | 6588 | chipio_set_control_param(codec, CONTROL_PARAM_PORTA_160OHM_GAIN, 6); |
4353 | chipio_set_control_param(codec, CONTROL_PARAM_PORTD_160OHM_GAIN, 6); | 6589 | chipio_set_control_param(codec, CONTROL_PARAM_PORTD_160OHM_GAIN, 6); |
4354 | } | 6590 | } |
@@ -4370,11 +6606,49 @@ static void ca0132_set_dsp_msr(struct hda_codec *codec, bool is96k) | |||
4370 | static bool ca0132_download_dsp_images(struct hda_codec *codec) | 6606 | static bool ca0132_download_dsp_images(struct hda_codec *codec) |
4371 | { | 6607 | { |
4372 | bool dsp_loaded = false; | 6608 | bool dsp_loaded = false; |
6609 | struct ca0132_spec *spec = codec->spec; | ||
4373 | const struct dsp_image_seg *dsp_os_image; | 6610 | const struct dsp_image_seg *dsp_os_image; |
4374 | const struct firmware *fw_entry; | 6611 | const struct firmware *fw_entry; |
4375 | 6612 | /* | |
4376 | if (request_firmware(&fw_entry, EFX_FILE, codec->card->dev) != 0) | 6613 | * Alternate firmwares for different variants. The Recon3Di apparently |
4377 | return false; | 6614 | * can use the default firmware, but I'll leave the option in case |
6615 | * it needs it again. | ||
6616 | */ | ||
6617 | switch (spec->quirk) { | ||
6618 | case QUIRK_SBZ: | ||
6619 | if (request_firmware(&fw_entry, SBZ_EFX_FILE, | ||
6620 | codec->card->dev) != 0) { | ||
6621 | codec_dbg(codec, "SBZ alt firmware not detected. "); | ||
6622 | spec->alt_firmware_present = false; | ||
6623 | } else { | ||
6624 | codec_dbg(codec, "Sound Blaster Z firmware selected."); | ||
6625 | spec->alt_firmware_present = true; | ||
6626 | } | ||
6627 | break; | ||
6628 | case QUIRK_R3DI: | ||
6629 | if (request_firmware(&fw_entry, R3DI_EFX_FILE, | ||
6630 | codec->card->dev) != 0) { | ||
6631 | codec_dbg(codec, "Recon3Di alt firmware not detected."); | ||
6632 | spec->alt_firmware_present = false; | ||
6633 | } else { | ||
6634 | codec_dbg(codec, "Recon3Di firmware selected."); | ||
6635 | spec->alt_firmware_present = true; | ||
6636 | } | ||
6637 | break; | ||
6638 | default: | ||
6639 | spec->alt_firmware_present = false; | ||
6640 | break; | ||
6641 | } | ||
6642 | /* | ||
6643 | * Use default ctefx.bin if no alt firmware is detected, or if none | ||
6644 | * exists for your particular codec. | ||
6645 | */ | ||
6646 | if (!spec->alt_firmware_present) { | ||
6647 | codec_dbg(codec, "Default firmware selected."); | ||
6648 | if (request_firmware(&fw_entry, EFX_FILE, | ||
6649 | codec->card->dev) != 0) | ||
6650 | return false; | ||
6651 | } | ||
4378 | 6652 | ||
4379 | dsp_os_image = (struct dsp_image_seg *)(fw_entry->data); | 6653 | dsp_os_image = (struct dsp_image_seg *)(fw_entry->data); |
4380 | if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) { | 6654 | if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) { |
@@ -4402,13 +6676,17 @@ static void ca0132_download_dsp(struct hda_codec *codec) | |||
4402 | return; /* don't retry failures */ | 6676 | return; /* don't retry failures */ |
4403 | 6677 | ||
4404 | chipio_enable_clocks(codec); | 6678 | chipio_enable_clocks(codec); |
4405 | spec->dsp_state = DSP_DOWNLOADING; | 6679 | if (spec->dsp_state != DSP_DOWNLOADED) { |
4406 | if (!ca0132_download_dsp_images(codec)) | 6680 | spec->dsp_state = DSP_DOWNLOADING; |
4407 | spec->dsp_state = DSP_DOWNLOAD_FAILED; | ||
4408 | else | ||
4409 | spec->dsp_state = DSP_DOWNLOADED; | ||
4410 | 6681 | ||
4411 | if (spec->dsp_state == DSP_DOWNLOADED) | 6682 | if (!ca0132_download_dsp_images(codec)) |
6683 | spec->dsp_state = DSP_DOWNLOAD_FAILED; | ||
6684 | else | ||
6685 | spec->dsp_state = DSP_DOWNLOADED; | ||
6686 | } | ||
6687 | |||
6688 | /* For codecs using alt functions, this is already done earlier */ | ||
6689 | if (spec->dsp_state == DSP_DOWNLOADED && (!spec->use_alt_functions)) | ||
4412 | ca0132_set_dsp_msr(codec, true); | 6690 | ca0132_set_dsp_msr(codec, true); |
4413 | } | 6691 | } |
4414 | 6692 | ||
@@ -4454,6 +6732,10 @@ static void ca0132_init_unsol(struct hda_codec *codec) | |||
4454 | amic_callback); | 6732 | amic_callback); |
4455 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, | 6733 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, |
4456 | ca0132_process_dsp_response); | 6734 | ca0132_process_dsp_response); |
6735 | /* Front headphone jack detection */ | ||
6736 | if (spec->use_alt_functions) | ||
6737 | snd_hda_jack_detect_enable_callback(codec, | ||
6738 | spec->unsol_tag_front_hp, hp_callback); | ||
4457 | } | 6739 | } |
4458 | 6740 | ||
4459 | /* | 6741 | /* |
@@ -4476,7 +6758,8 @@ static struct hda_verb ca0132_base_exit_verbs[] = { | |||
4476 | {} | 6758 | {} |
4477 | }; | 6759 | }; |
4478 | 6760 | ||
4479 | /* Other verbs tables. Sends after DSP download. */ | 6761 | /* Other verbs tables. Sends after DSP download. */ |
6762 | |||
4480 | static struct hda_verb ca0132_init_verbs0[] = { | 6763 | static struct hda_verb ca0132_init_verbs0[] = { |
4481 | /* chip init verbs */ | 6764 | /* chip init verbs */ |
4482 | {0x15, 0x70D, 0xF0}, | 6765 | {0x15, 0x70D, 0xF0}, |
@@ -4506,8 +6789,27 @@ static struct hda_verb ca0132_init_verbs0[] = { | |||
4506 | {0x15, 0x546, 0xC9}, | 6789 | {0x15, 0x546, 0xC9}, |
4507 | {0x15, 0x53B, 0xCE}, | 6790 | {0x15, 0x53B, 0xCE}, |
4508 | {0x15, 0x5E8, 0xC9}, | 6791 | {0x15, 0x5E8, 0xC9}, |
4509 | {0x15, 0x717, 0x0D}, | 6792 | {} |
4510 | {0x15, 0x718, 0x20}, | 6793 | }; |
6794 | |||
6795 | /* Extra init verbs for SBZ */ | ||
6796 | static struct hda_verb sbz_init_verbs[] = { | ||
6797 | {0x15, 0x70D, 0x20}, | ||
6798 | {0x15, 0x70E, 0x19}, | ||
6799 | {0x15, 0x707, 0x00}, | ||
6800 | {0x15, 0x539, 0xCE}, | ||
6801 | {0x15, 0x546, 0xC9}, | ||
6802 | {0x15, 0x70D, 0xB7}, | ||
6803 | {0x15, 0x70E, 0x09}, | ||
6804 | {0x15, 0x707, 0x10}, | ||
6805 | {0x15, 0x70D, 0xAF}, | ||
6806 | {0x15, 0x70E, 0x09}, | ||
6807 | {0x15, 0x707, 0x01}, | ||
6808 | {0x15, 0x707, 0x05}, | ||
6809 | {0x15, 0x70D, 0x73}, | ||
6810 | {0x15, 0x70E, 0x09}, | ||
6811 | {0x15, 0x707, 0x14}, | ||
6812 | {0x15, 0x6FF, 0xC4}, | ||
4511 | {} | 6813 | {} |
4512 | }; | 6814 | }; |
4513 | 6815 | ||
@@ -4521,7 +6823,11 @@ static void ca0132_init_chip(struct hda_codec *codec) | |||
4521 | mutex_init(&spec->chipio_mutex); | 6823 | mutex_init(&spec->chipio_mutex); |
4522 | 6824 | ||
4523 | spec->cur_out_type = SPEAKER_OUT; | 6825 | spec->cur_out_type = SPEAKER_OUT; |
4524 | spec->cur_mic_type = DIGITAL_MIC; | 6826 | if (!spec->use_alt_functions) |
6827 | spec->cur_mic_type = DIGITAL_MIC; | ||
6828 | else | ||
6829 | spec->cur_mic_type = REAR_MIC; | ||
6830 | |||
4525 | spec->cur_mic_boost = 0; | 6831 | spec->cur_mic_boost = 0; |
4526 | 6832 | ||
4527 | for (i = 0; i < VNODES_COUNT; i++) { | 6833 | for (i = 0; i < VNODES_COUNT; i++) { |
@@ -4539,6 +6845,15 @@ static void ca0132_init_chip(struct hda_codec *codec) | |||
4539 | on = (unsigned int)ca0132_effects[i].reqs[0]; | 6845 | on = (unsigned int)ca0132_effects[i].reqs[0]; |
4540 | spec->effects_switch[i] = on ? 1 : 0; | 6846 | spec->effects_switch[i] = on ? 1 : 0; |
4541 | } | 6847 | } |
6848 | /* | ||
6849 | * Sets defaults for the effect slider controls, only for alternative | ||
6850 | * ca0132 codecs. Also sets x-bass crossover frequency to 80hz. | ||
6851 | */ | ||
6852 | if (spec->use_alt_controls) { | ||
6853 | spec->xbass_xover_freq = 8; | ||
6854 | for (i = 0; i < EFFECT_LEVEL_SLIDERS; i++) | ||
6855 | spec->fx_ctl_val[i] = effect_slider_defaults[i]; | ||
6856 | } | ||
4542 | 6857 | ||
4543 | spec->voicefx_val = 0; | 6858 | spec->voicefx_val = 0; |
4544 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1; | 6859 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1; |
@@ -4549,6 +6864,120 @@ static void ca0132_init_chip(struct hda_codec *codec) | |||
4549 | #endif | 6864 | #endif |
4550 | } | 6865 | } |
4551 | 6866 | ||
6867 | /* | ||
6868 | * Recon3Di exit specific commands. | ||
6869 | */ | ||
6870 | /* prevents popping noise on shutdown */ | ||
6871 | static void r3di_gpio_shutdown(struct hda_codec *codec) | ||
6872 | { | ||
6873 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0x00); | ||
6874 | } | ||
6875 | |||
6876 | /* | ||
6877 | * Sound Blaster Z exit specific commands. | ||
6878 | */ | ||
6879 | static void sbz_region2_exit(struct hda_codec *codec) | ||
6880 | { | ||
6881 | struct ca0132_spec *spec = codec->spec; | ||
6882 | unsigned int i; | ||
6883 | |||
6884 | for (i = 0; i < 4; i++) | ||
6885 | writeb(0x0, spec->mem_base + 0x100); | ||
6886 | for (i = 0; i < 8; i++) | ||
6887 | writeb(0xb3, spec->mem_base + 0x304); | ||
6888 | /* | ||
6889 | * I believe these are GPIO, with the right most hex digit being the | ||
6890 | * gpio pin, and the second digit being on or off. We see this more in | ||
6891 | * the input/output select functions. | ||
6892 | */ | ||
6893 | writew(0x0000, spec->mem_base + 0x320); | ||
6894 | writew(0x0001, spec->mem_base + 0x320); | ||
6895 | writew(0x0104, spec->mem_base + 0x320); | ||
6896 | writew(0x0005, spec->mem_base + 0x320); | ||
6897 | writew(0x0007, spec->mem_base + 0x320); | ||
6898 | } | ||
6899 | |||
6900 | static void sbz_set_pin_ctl_default(struct hda_codec *codec) | ||
6901 | { | ||
6902 | hda_nid_t pins[5] = {0x0B, 0x0C, 0x0E, 0x12, 0x13}; | ||
6903 | unsigned int i; | ||
6904 | |||
6905 | snd_hda_codec_write(codec, 0x11, 0, | ||
6906 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40); | ||
6907 | |||
6908 | for (i = 0; i < 5; i++) | ||
6909 | snd_hda_codec_write(codec, pins[i], 0, | ||
6910 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00); | ||
6911 | } | ||
6912 | |||
6913 | static void sbz_clear_unsolicited(struct hda_codec *codec) | ||
6914 | { | ||
6915 | hda_nid_t pins[7] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13}; | ||
6916 | unsigned int i; | ||
6917 | |||
6918 | for (i = 0; i < 7; i++) { | ||
6919 | snd_hda_codec_write(codec, pins[i], 0, | ||
6920 | AC_VERB_SET_UNSOLICITED_ENABLE, 0x00); | ||
6921 | } | ||
6922 | } | ||
6923 | |||
6924 | /* On shutdown, sends commands in sets of three */ | ||
6925 | static void sbz_gpio_shutdown_commands(struct hda_codec *codec, int dir, | ||
6926 | int mask, int data) | ||
6927 | { | ||
6928 | if (dir >= 0) | ||
6929 | snd_hda_codec_write(codec, 0x01, 0, | ||
6930 | AC_VERB_SET_GPIO_DIRECTION, dir); | ||
6931 | if (mask >= 0) | ||
6932 | snd_hda_codec_write(codec, 0x01, 0, | ||
6933 | AC_VERB_SET_GPIO_MASK, mask); | ||
6934 | |||
6935 | if (data >= 0) | ||
6936 | snd_hda_codec_write(codec, 0x01, 0, | ||
6937 | AC_VERB_SET_GPIO_DATA, data); | ||
6938 | } | ||
6939 | |||
6940 | static void sbz_exit_chip(struct hda_codec *codec) | ||
6941 | { | ||
6942 | chipio_set_stream_control(codec, 0x03, 0); | ||
6943 | chipio_set_stream_control(codec, 0x04, 0); | ||
6944 | |||
6945 | /* Mess with GPIO */ | ||
6946 | sbz_gpio_shutdown_commands(codec, 0x07, 0x07, -1); | ||
6947 | sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x05); | ||
6948 | sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x01); | ||
6949 | |||
6950 | chipio_set_stream_control(codec, 0x14, 0); | ||
6951 | chipio_set_stream_control(codec, 0x0C, 0); | ||
6952 | |||
6953 | chipio_set_conn_rate(codec, 0x41, SR_192_000); | ||
6954 | chipio_set_conn_rate(codec, 0x91, SR_192_000); | ||
6955 | |||
6956 | chipio_write(codec, 0x18a020, 0x00000083); | ||
6957 | |||
6958 | sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x03); | ||
6959 | sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x07); | ||
6960 | sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x06); | ||
6961 | |||
6962 | chipio_set_stream_control(codec, 0x0C, 0); | ||
6963 | |||
6964 | chipio_set_control_param(codec, 0x0D, 0x24); | ||
6965 | |||
6966 | sbz_clear_unsolicited(codec); | ||
6967 | sbz_set_pin_ctl_default(codec); | ||
6968 | |||
6969 | snd_hda_codec_write(codec, 0x0B, 0, | ||
6970 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); | ||
6971 | |||
6972 | if (dspload_is_loaded(codec)) | ||
6973 | dsp_reset(codec); | ||
6974 | |||
6975 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
6976 | VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x00); | ||
6977 | |||
6978 | sbz_region2_exit(codec); | ||
6979 | } | ||
6980 | |||
4552 | static void ca0132_exit_chip(struct hda_codec *codec) | 6981 | static void ca0132_exit_chip(struct hda_codec *codec) |
4553 | { | 6982 | { |
4554 | /* put any chip cleanup stuffs here. */ | 6983 | /* put any chip cleanup stuffs here. */ |
@@ -4557,28 +6986,264 @@ static void ca0132_exit_chip(struct hda_codec *codec) | |||
4557 | dsp_reset(codec); | 6986 | dsp_reset(codec); |
4558 | } | 6987 | } |
4559 | 6988 | ||
6989 | /* | ||
6990 | * This fixes a problem that was hard to reproduce. Very rarely, I would | ||
6991 | * boot up, and there would be no sound, but the DSP indicated it had loaded | ||
6992 | * properly. I did a few memory dumps to see if anything was different, and | ||
6993 | * there were a few areas of memory uninitialized with a1a2a3a4. This function | ||
6994 | * checks if those areas are uninitialized, and if they are, it'll attempt to | ||
6995 | * reload the card 3 times. Usually it fixes by the second. | ||
6996 | */ | ||
6997 | static void sbz_dsp_startup_check(struct hda_codec *codec) | ||
6998 | { | ||
6999 | struct ca0132_spec *spec = codec->spec; | ||
7000 | unsigned int dsp_data_check[4]; | ||
7001 | unsigned int cur_address = 0x390; | ||
7002 | unsigned int i; | ||
7003 | unsigned int failure = 0; | ||
7004 | unsigned int reload = 3; | ||
7005 | |||
7006 | if (spec->startup_check_entered) | ||
7007 | return; | ||
7008 | |||
7009 | spec->startup_check_entered = true; | ||
7010 | |||
7011 | for (i = 0; i < 4; i++) { | ||
7012 | chipio_read(codec, cur_address, &dsp_data_check[i]); | ||
7013 | cur_address += 0x4; | ||
7014 | } | ||
7015 | for (i = 0; i < 4; i++) { | ||
7016 | if (dsp_data_check[i] == 0xa1a2a3a4) | ||
7017 | failure = 1; | ||
7018 | } | ||
7019 | |||
7020 | codec_dbg(codec, "Startup Check: %d ", failure); | ||
7021 | if (failure) | ||
7022 | codec_info(codec, "DSP not initialized properly. Attempting to fix."); | ||
7023 | /* | ||
7024 | * While the failure condition is true, and we haven't reached our | ||
7025 | * three reload limit, continue trying to reload the driver and | ||
7026 | * fix the issue. | ||
7027 | */ | ||
7028 | while (failure && (reload != 0)) { | ||
7029 | codec_info(codec, "Reloading... Tries left: %d", reload); | ||
7030 | sbz_exit_chip(codec); | ||
7031 | spec->dsp_state = DSP_DOWNLOAD_INIT; | ||
7032 | codec->patch_ops.init(codec); | ||
7033 | failure = 0; | ||
7034 | for (i = 0; i < 4; i++) { | ||
7035 | chipio_read(codec, cur_address, &dsp_data_check[i]); | ||
7036 | cur_address += 0x4; | ||
7037 | } | ||
7038 | for (i = 0; i < 4; i++) { | ||
7039 | if (dsp_data_check[i] == 0xa1a2a3a4) | ||
7040 | failure = 1; | ||
7041 | } | ||
7042 | reload--; | ||
7043 | } | ||
7044 | |||
7045 | if (!failure && reload < 3) | ||
7046 | codec_info(codec, "DSP fixed."); | ||
7047 | |||
7048 | if (!failure) | ||
7049 | return; | ||
7050 | |||
7051 | codec_info(codec, "DSP failed to initialize properly. Either try a full shutdown or a suspend to clear the internal memory."); | ||
7052 | } | ||
7053 | |||
7054 | /* | ||
7055 | * This is for the extra volume verbs 0x797 (left) and 0x798 (right). These add | ||
7056 | * extra precision for decibel values. If you had the dB value in floating point | ||
7057 | * you would take the value after the decimal point, multiply by 64, and divide | ||
7058 | * by 2. So for 8.59, it's (59 * 64) / 100. Useful if someone wanted to | ||
7059 | * implement fixed point or floating point dB volumes. For now, I'll set them | ||
7060 | * to 0 just incase a value has lingered from a boot into Windows. | ||
7061 | */ | ||
7062 | static void ca0132_alt_vol_setup(struct hda_codec *codec) | ||
7063 | { | ||
7064 | snd_hda_codec_write(codec, 0x02, 0, 0x797, 0x00); | ||
7065 | snd_hda_codec_write(codec, 0x02, 0, 0x798, 0x00); | ||
7066 | snd_hda_codec_write(codec, 0x03, 0, 0x797, 0x00); | ||
7067 | snd_hda_codec_write(codec, 0x03, 0, 0x798, 0x00); | ||
7068 | snd_hda_codec_write(codec, 0x04, 0, 0x797, 0x00); | ||
7069 | snd_hda_codec_write(codec, 0x04, 0, 0x798, 0x00); | ||
7070 | snd_hda_codec_write(codec, 0x07, 0, 0x797, 0x00); | ||
7071 | snd_hda_codec_write(codec, 0x07, 0, 0x798, 0x00); | ||
7072 | } | ||
7073 | |||
7074 | /* | ||
7075 | * Extra commands that don't really fit anywhere else. | ||
7076 | */ | ||
7077 | static void sbz_pre_dsp_setup(struct hda_codec *codec) | ||
7078 | { | ||
7079 | struct ca0132_spec *spec = codec->spec; | ||
7080 | |||
7081 | writel(0x00820680, spec->mem_base + 0x01C); | ||
7082 | writel(0x00820680, spec->mem_base + 0x01C); | ||
7083 | |||
7084 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfc); | ||
7085 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfd); | ||
7086 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfe); | ||
7087 | snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xff); | ||
7088 | |||
7089 | chipio_write(codec, 0x18b0a4, 0x000000c2); | ||
7090 | |||
7091 | snd_hda_codec_write(codec, 0x11, 0, | ||
7092 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44); | ||
7093 | } | ||
7094 | |||
7095 | /* | ||
7096 | * Extra commands that don't really fit anywhere else. | ||
7097 | */ | ||
7098 | static void r3di_pre_dsp_setup(struct hda_codec *codec) | ||
7099 | { | ||
7100 | chipio_write(codec, 0x18b0a4, 0x000000c2); | ||
7101 | |||
7102 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7103 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x1E); | ||
7104 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7105 | VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x1C); | ||
7106 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7107 | VENDOR_CHIPIO_8051_DATA_WRITE, 0x5B); | ||
7108 | |||
7109 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7110 | VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x20); | ||
7111 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7112 | VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19); | ||
7113 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7114 | VENDOR_CHIPIO_8051_DATA_WRITE, 0x00); | ||
7115 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7116 | VENDOR_CHIPIO_8051_DATA_WRITE, 0x40); | ||
7117 | |||
7118 | snd_hda_codec_write(codec, 0x11, 0, | ||
7119 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x04); | ||
7120 | } | ||
7121 | |||
7122 | |||
7123 | /* | ||
7124 | * These are sent before the DSP is downloaded. Not sure | ||
7125 | * what they do, or if they're necessary. Could possibly | ||
7126 | * be removed. Figure they're better to leave in. | ||
7127 | */ | ||
7128 | static void sbz_region2_startup(struct hda_codec *codec) | ||
7129 | { | ||
7130 | struct ca0132_spec *spec = codec->spec; | ||
7131 | |||
7132 | writel(0x00000000, spec->mem_base + 0x400); | ||
7133 | writel(0x00000000, spec->mem_base + 0x408); | ||
7134 | writel(0x00000000, spec->mem_base + 0x40C); | ||
7135 | writel(0x00880680, spec->mem_base + 0x01C); | ||
7136 | writel(0x00000083, spec->mem_base + 0xC0C); | ||
7137 | writel(0x00000030, spec->mem_base + 0xC00); | ||
7138 | writel(0x00000000, spec->mem_base + 0xC04); | ||
7139 | writel(0x00000003, spec->mem_base + 0xC0C); | ||
7140 | writel(0x00000003, spec->mem_base + 0xC0C); | ||
7141 | writel(0x00000003, spec->mem_base + 0xC0C); | ||
7142 | writel(0x00000003, spec->mem_base + 0xC0C); | ||
7143 | writel(0x000000C1, spec->mem_base + 0xC08); | ||
7144 | writel(0x000000F1, spec->mem_base + 0xC08); | ||
7145 | writel(0x00000001, spec->mem_base + 0xC08); | ||
7146 | writel(0x000000C7, spec->mem_base + 0xC08); | ||
7147 | writel(0x000000C1, spec->mem_base + 0xC08); | ||
7148 | writel(0x00000080, spec->mem_base + 0xC04); | ||
7149 | } | ||
7150 | |||
7151 | /* | ||
7152 | * Extra init functions for alternative ca0132 codecs. Done | ||
7153 | * here so they don't clutter up the main ca0132_init function | ||
7154 | * anymore than they have to. | ||
7155 | */ | ||
7156 | static void ca0132_alt_init(struct hda_codec *codec) | ||
7157 | { | ||
7158 | struct ca0132_spec *spec = codec->spec; | ||
7159 | |||
7160 | ca0132_alt_vol_setup(codec); | ||
7161 | |||
7162 | switch (spec->quirk) { | ||
7163 | case QUIRK_SBZ: | ||
7164 | codec_dbg(codec, "SBZ alt_init"); | ||
7165 | ca0132_gpio_init(codec); | ||
7166 | sbz_pre_dsp_setup(codec); | ||
7167 | snd_hda_sequence_write(codec, spec->chip_init_verbs); | ||
7168 | snd_hda_sequence_write(codec, spec->sbz_init_verbs); | ||
7169 | break; | ||
7170 | case QUIRK_R3DI: | ||
7171 | codec_dbg(codec, "R3DI alt_init"); | ||
7172 | ca0132_gpio_init(codec); | ||
7173 | ca0132_gpio_setup(codec); | ||
7174 | r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADING); | ||
7175 | r3di_pre_dsp_setup(codec); | ||
7176 | snd_hda_sequence_write(codec, spec->chip_init_verbs); | ||
7177 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x6FF, 0xC4); | ||
7178 | break; | ||
7179 | } | ||
7180 | } | ||
7181 | |||
4560 | static int ca0132_init(struct hda_codec *codec) | 7182 | static int ca0132_init(struct hda_codec *codec) |
4561 | { | 7183 | { |
4562 | struct ca0132_spec *spec = codec->spec; | 7184 | struct ca0132_spec *spec = codec->spec; |
4563 | struct auto_pin_cfg *cfg = &spec->autocfg; | 7185 | struct auto_pin_cfg *cfg = &spec->autocfg; |
4564 | int i; | 7186 | int i; |
7187 | bool dsp_loaded; | ||
7188 | |||
7189 | /* | ||
7190 | * If the DSP is already downloaded, and init has been entered again, | ||
7191 | * there's only two reasons for it. One, the codec has awaken from a | ||
7192 | * suspended state, and in that case dspload_is_loaded will return | ||
7193 | * false, and the init will be ran again. The other reason it gets | ||
7194 | * re entered is on startup for some reason it triggers a suspend and | ||
7195 | * resume state. In this case, it will check if the DSP is downloaded, | ||
7196 | * and not run the init function again. For codecs using alt_functions, | ||
7197 | * it will check if the DSP is loaded properly. | ||
7198 | */ | ||
7199 | if (spec->dsp_state == DSP_DOWNLOADED) { | ||
7200 | dsp_loaded = dspload_is_loaded(codec); | ||
7201 | if (!dsp_loaded) { | ||
7202 | spec->dsp_reload = true; | ||
7203 | spec->dsp_state = DSP_DOWNLOAD_INIT; | ||
7204 | } else { | ||
7205 | if (spec->quirk == QUIRK_SBZ) | ||
7206 | sbz_dsp_startup_check(codec); | ||
7207 | return 0; | ||
7208 | } | ||
7209 | } | ||
4565 | 7210 | ||
4566 | if (spec->dsp_state != DSP_DOWNLOAD_FAILED) | 7211 | if (spec->dsp_state != DSP_DOWNLOAD_FAILED) |
4567 | spec->dsp_state = DSP_DOWNLOAD_INIT; | 7212 | spec->dsp_state = DSP_DOWNLOAD_INIT; |
4568 | spec->curr_chip_addx = INVALID_CHIP_ADDRESS; | 7213 | spec->curr_chip_addx = INVALID_CHIP_ADDRESS; |
4569 | 7214 | ||
7215 | if (spec->quirk == QUIRK_SBZ) | ||
7216 | sbz_region2_startup(codec); | ||
7217 | |||
4570 | snd_hda_power_up_pm(codec); | 7218 | snd_hda_power_up_pm(codec); |
4571 | 7219 | ||
4572 | ca0132_init_unsol(codec); | 7220 | ca0132_init_unsol(codec); |
4573 | |||
4574 | ca0132_init_params(codec); | 7221 | ca0132_init_params(codec); |
4575 | ca0132_init_flags(codec); | 7222 | ca0132_init_flags(codec); |
7223 | |||
4576 | snd_hda_sequence_write(codec, spec->base_init_verbs); | 7224 | snd_hda_sequence_write(codec, spec->base_init_verbs); |
7225 | |||
7226 | if (spec->quirk != QUIRK_NONE) | ||
7227 | ca0132_alt_init(codec); | ||
7228 | |||
4577 | ca0132_download_dsp(codec); | 7229 | ca0132_download_dsp(codec); |
7230 | |||
4578 | ca0132_refresh_widget_caps(codec); | 7231 | ca0132_refresh_widget_caps(codec); |
4579 | ca0132_setup_defaults(codec); | 7232 | |
4580 | ca0132_init_analog_mic2(codec); | 7233 | if (spec->quirk == QUIRK_SBZ) |
4581 | ca0132_init_dmic(codec); | 7234 | writew(0x0107, spec->mem_base + 0x320); |
7235 | |||
7236 | switch (spec->quirk) { | ||
7237 | case QUIRK_R3DI: | ||
7238 | r3di_setup_defaults(codec); | ||
7239 | break; | ||
7240 | case QUIRK_NONE: | ||
7241 | case QUIRK_ALIENWARE: | ||
7242 | ca0132_setup_defaults(codec); | ||
7243 | ca0132_init_analog_mic2(codec); | ||
7244 | ca0132_init_dmic(codec); | ||
7245 | break; | ||
7246 | } | ||
4582 | 7247 | ||
4583 | for (i = 0; i < spec->num_outputs; i++) | 7248 | for (i = 0; i < spec->num_outputs; i++) |
4584 | init_output(codec, spec->out_pins[i], spec->dacs[0]); | 7249 | init_output(codec, spec->out_pins[i], spec->dacs[0]); |
@@ -4590,14 +7255,45 @@ static int ca0132_init(struct hda_codec *codec) | |||
4590 | 7255 | ||
4591 | init_input(codec, cfg->dig_in_pin, spec->dig_in); | 7256 | init_input(codec, cfg->dig_in_pin, spec->dig_in); |
4592 | 7257 | ||
4593 | snd_hda_sequence_write(codec, spec->chip_init_verbs); | 7258 | if (!spec->use_alt_functions) { |
4594 | snd_hda_sequence_write(codec, spec->spec_init_verbs); | 7259 | snd_hda_sequence_write(codec, spec->chip_init_verbs); |
7260 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7261 | VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D); | ||
7262 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
7263 | VENDOR_CHIPIO_PARAM_EX_VALUE_SET, 0x20); | ||
7264 | } | ||
4595 | 7265 | ||
4596 | ca0132_select_out(codec); | 7266 | if (spec->quirk == QUIRK_SBZ) |
4597 | ca0132_select_mic(codec); | 7267 | ca0132_gpio_setup(codec); |
7268 | |||
7269 | snd_hda_sequence_write(codec, spec->spec_init_verbs); | ||
7270 | switch (spec->quirk) { | ||
7271 | case QUIRK_SBZ: | ||
7272 | sbz_setup_defaults(codec); | ||
7273 | ca0132_alt_select_out(codec); | ||
7274 | ca0132_alt_select_in(codec); | ||
7275 | break; | ||
7276 | case QUIRK_R3DI: | ||
7277 | ca0132_alt_select_out(codec); | ||
7278 | ca0132_alt_select_in(codec); | ||
7279 | break; | ||
7280 | default: | ||
7281 | ca0132_select_out(codec); | ||
7282 | ca0132_select_mic(codec); | ||
7283 | break; | ||
7284 | } | ||
4598 | 7285 | ||
4599 | snd_hda_jack_report_sync(codec); | 7286 | snd_hda_jack_report_sync(codec); |
4600 | 7287 | ||
7288 | /* | ||
7289 | * Re set the PlayEnhancement switch on a resume event, because the | ||
7290 | * controls will not be reloaded. | ||
7291 | */ | ||
7292 | if (spec->dsp_reload) { | ||
7293 | spec->dsp_reload = false; | ||
7294 | ca0132_pe_switch_set(codec); | ||
7295 | } | ||
7296 | |||
4601 | snd_hda_power_down_pm(codec); | 7297 | snd_hda_power_down_pm(codec); |
4602 | 7298 | ||
4603 | return 0; | 7299 | return 0; |
@@ -4609,19 +7305,39 @@ static void ca0132_free(struct hda_codec *codec) | |||
4609 | 7305 | ||
4610 | cancel_delayed_work_sync(&spec->unsol_hp_work); | 7306 | cancel_delayed_work_sync(&spec->unsol_hp_work); |
4611 | snd_hda_power_up(codec); | 7307 | snd_hda_power_up(codec); |
4612 | snd_hda_sequence_write(codec, spec->base_exit_verbs); | 7308 | switch (spec->quirk) { |
4613 | ca0132_exit_chip(codec); | 7309 | case QUIRK_SBZ: |
7310 | sbz_exit_chip(codec); | ||
7311 | break; | ||
7312 | case QUIRK_R3DI: | ||
7313 | r3di_gpio_shutdown(codec); | ||
7314 | snd_hda_sequence_write(codec, spec->base_exit_verbs); | ||
7315 | ca0132_exit_chip(codec); | ||
7316 | break; | ||
7317 | default: | ||
7318 | snd_hda_sequence_write(codec, spec->base_exit_verbs); | ||
7319 | ca0132_exit_chip(codec); | ||
7320 | break; | ||
7321 | } | ||
4614 | snd_hda_power_down(codec); | 7322 | snd_hda_power_down(codec); |
7323 | if (spec->mem_base) | ||
7324 | iounmap(spec->mem_base); | ||
4615 | kfree(spec->spec_init_verbs); | 7325 | kfree(spec->spec_init_verbs); |
4616 | kfree(codec->spec); | 7326 | kfree(codec->spec); |
4617 | } | 7327 | } |
4618 | 7328 | ||
7329 | static void ca0132_reboot_notify(struct hda_codec *codec) | ||
7330 | { | ||
7331 | codec->patch_ops.free(codec); | ||
7332 | } | ||
7333 | |||
4619 | static const struct hda_codec_ops ca0132_patch_ops = { | 7334 | static const struct hda_codec_ops ca0132_patch_ops = { |
4620 | .build_controls = ca0132_build_controls, | 7335 | .build_controls = ca0132_build_controls, |
4621 | .build_pcms = ca0132_build_pcms, | 7336 | .build_pcms = ca0132_build_pcms, |
4622 | .init = ca0132_init, | 7337 | .init = ca0132_init, |
4623 | .free = ca0132_free, | 7338 | .free = ca0132_free, |
4624 | .unsol_event = snd_hda_jack_unsol_event, | 7339 | .unsol_event = snd_hda_jack_unsol_event, |
7340 | .reboot_notify = ca0132_reboot_notify, | ||
4625 | }; | 7341 | }; |
4626 | 7342 | ||
4627 | static void ca0132_config(struct hda_codec *codec) | 7343 | static void ca0132_config(struct hda_codec *codec) |
@@ -4635,9 +7351,14 @@ static void ca0132_config(struct hda_codec *codec) | |||
4635 | 7351 | ||
4636 | spec->multiout.dac_nids = spec->dacs; | 7352 | spec->multiout.dac_nids = spec->dacs; |
4637 | spec->multiout.num_dacs = 3; | 7353 | spec->multiout.num_dacs = 3; |
4638 | spec->multiout.max_channels = 2; | ||
4639 | 7354 | ||
4640 | if (spec->quirk == QUIRK_ALIENWARE) { | 7355 | if (!spec->use_alt_functions) |
7356 | spec->multiout.max_channels = 2; | ||
7357 | else | ||
7358 | spec->multiout.max_channels = 6; | ||
7359 | |||
7360 | switch (spec->quirk) { | ||
7361 | case QUIRK_ALIENWARE: | ||
4641 | codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n"); | 7362 | codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n"); |
4642 | snd_hda_apply_pincfgs(codec, alienware_pincfgs); | 7363 | snd_hda_apply_pincfgs(codec, alienware_pincfgs); |
4643 | 7364 | ||
@@ -4657,7 +7378,71 @@ static void ca0132_config(struct hda_codec *codec) | |||
4657 | spec->input_pins[2] = 0x13; | 7378 | spec->input_pins[2] = 0x13; |
4658 | spec->shared_mic_nid = 0x7; | 7379 | spec->shared_mic_nid = 0x7; |
4659 | spec->unsol_tag_amic1 = 0x11; | 7380 | spec->unsol_tag_amic1 = 0x11; |
4660 | } else { | 7381 | break; |
7382 | case QUIRK_SBZ: | ||
7383 | codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__); | ||
7384 | snd_hda_apply_pincfgs(codec, sbz_pincfgs); | ||
7385 | |||
7386 | spec->num_outputs = 2; | ||
7387 | spec->out_pins[0] = 0x0B; /* Line out */ | ||
7388 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ | ||
7389 | spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/ | ||
7390 | spec->out_pins[3] = 0x11; /* Rear surround */ | ||
7391 | spec->shared_out_nid = 0x2; | ||
7392 | spec->unsol_tag_hp = spec->out_pins[1]; | ||
7393 | spec->unsol_tag_front_hp = spec->out_pins[2]; | ||
7394 | |||
7395 | spec->adcs[0] = 0x7; /* Rear Mic / Line-in */ | ||
7396 | spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */ | ||
7397 | spec->adcs[2] = 0xa; /* what u hear */ | ||
7398 | |||
7399 | spec->num_inputs = 2; | ||
7400 | spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */ | ||
7401 | spec->input_pins[1] = 0x13; /* What U Hear */ | ||
7402 | spec->shared_mic_nid = 0x7; | ||
7403 | spec->unsol_tag_amic1 = spec->input_pins[0]; | ||
7404 | |||
7405 | /* SPDIF I/O */ | ||
7406 | spec->dig_out = 0x05; | ||
7407 | spec->multiout.dig_out_nid = spec->dig_out; | ||
7408 | cfg->dig_out_pins[0] = 0x0c; | ||
7409 | cfg->dig_outs = 1; | ||
7410 | cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF; | ||
7411 | spec->dig_in = 0x09; | ||
7412 | cfg->dig_in_pin = 0x0e; | ||
7413 | cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; | ||
7414 | break; | ||
7415 | case QUIRK_R3DI: | ||
7416 | codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__); | ||
7417 | snd_hda_apply_pincfgs(codec, r3di_pincfgs); | ||
7418 | |||
7419 | spec->num_outputs = 2; | ||
7420 | spec->out_pins[0] = 0x0B; /* Line out */ | ||
7421 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ | ||
7422 | spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/ | ||
7423 | spec->out_pins[3] = 0x11; /* Rear surround */ | ||
7424 | spec->shared_out_nid = 0x2; | ||
7425 | spec->unsol_tag_hp = spec->out_pins[1]; | ||
7426 | spec->unsol_tag_front_hp = spec->out_pins[2]; | ||
7427 | |||
7428 | spec->adcs[0] = 0x07; /* Rear Mic / Line-in */ | ||
7429 | spec->adcs[1] = 0x08; /* Front Mic, but only if no DSP */ | ||
7430 | spec->adcs[2] = 0x0a; /* what u hear */ | ||
7431 | |||
7432 | spec->num_inputs = 2; | ||
7433 | spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */ | ||
7434 | spec->input_pins[1] = 0x13; /* What U Hear */ | ||
7435 | spec->shared_mic_nid = 0x7; | ||
7436 | spec->unsol_tag_amic1 = spec->input_pins[0]; | ||
7437 | |||
7438 | /* SPDIF I/O */ | ||
7439 | spec->dig_out = 0x05; | ||
7440 | spec->multiout.dig_out_nid = spec->dig_out; | ||
7441 | cfg->dig_out_pins[0] = 0x0c; | ||
7442 | cfg->dig_outs = 1; | ||
7443 | cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF; | ||
7444 | break; | ||
7445 | default: | ||
4661 | spec->num_outputs = 2; | 7446 | spec->num_outputs = 2; |
4662 | spec->out_pins[0] = 0x0b; /* speaker out */ | 7447 | spec->out_pins[0] = 0x0b; /* speaker out */ |
4663 | spec->out_pins[1] = 0x10; /* headphone out */ | 7448 | spec->out_pins[1] = 0x10; /* headphone out */ |
@@ -4684,6 +7469,7 @@ static void ca0132_config(struct hda_codec *codec) | |||
4684 | spec->dig_in = 0x09; | 7469 | spec->dig_in = 0x09; |
4685 | cfg->dig_in_pin = 0x0e; | 7470 | cfg->dig_in_pin = 0x0e; |
4686 | cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; | 7471 | cfg->dig_in_type = HDA_PCM_TYPE_SPDIF; |
7472 | break; | ||
4687 | } | 7473 | } |
4688 | } | 7474 | } |
4689 | 7475 | ||
@@ -4694,6 +7480,8 @@ static int ca0132_prepare_verbs(struct hda_codec *codec) | |||
4694 | struct ca0132_spec *spec = codec->spec; | 7480 | struct ca0132_spec *spec = codec->spec; |
4695 | 7481 | ||
4696 | spec->chip_init_verbs = ca0132_init_verbs0; | 7482 | spec->chip_init_verbs = ca0132_init_verbs0; |
7483 | if (spec->quirk == QUIRK_SBZ) | ||
7484 | spec->sbz_init_verbs = sbz_init_verbs; | ||
4697 | spec->spec_init_verbs = kzalloc(sizeof(struct hda_verb) * NUM_SPEC_VERBS, GFP_KERNEL); | 7485 | spec->spec_init_verbs = kzalloc(sizeof(struct hda_verb) * NUM_SPEC_VERBS, GFP_KERNEL); |
4698 | if (!spec->spec_init_verbs) | 7486 | if (!spec->spec_init_verbs) |
4699 | return -ENOMEM; | 7487 | return -ENOMEM; |
@@ -4757,9 +7545,46 @@ static int patch_ca0132(struct hda_codec *codec) | |||
4757 | else | 7545 | else |
4758 | spec->quirk = QUIRK_NONE; | 7546 | spec->quirk = QUIRK_NONE; |
4759 | 7547 | ||
7548 | /* Setup BAR Region 2 for Sound Blaster Z */ | ||
7549 | if (spec->quirk == QUIRK_SBZ) { | ||
7550 | spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20); | ||
7551 | if (spec->mem_base == NULL) { | ||
7552 | codec_warn(codec, "pci_iomap failed!"); | ||
7553 | codec_info(codec, "perhaps this is not an SBZ?"); | ||
7554 | spec->quirk = QUIRK_NONE; | ||
7555 | } | ||
7556 | } | ||
7557 | |||
4760 | spec->dsp_state = DSP_DOWNLOAD_INIT; | 7558 | spec->dsp_state = DSP_DOWNLOAD_INIT; |
4761 | spec->num_mixers = 1; | 7559 | spec->num_mixers = 1; |
4762 | spec->mixers[0] = ca0132_mixer; | 7560 | |
7561 | /* Set which mixers each quirk uses. */ | ||
7562 | switch (spec->quirk) { | ||
7563 | case QUIRK_SBZ: | ||
7564 | spec->mixers[0] = sbz_mixer; | ||
7565 | snd_hda_codec_set_name(codec, "Sound Blaster Z"); | ||
7566 | break; | ||
7567 | case QUIRK_R3DI: | ||
7568 | spec->mixers[0] = r3di_mixer; | ||
7569 | snd_hda_codec_set_name(codec, "Recon3Di"); | ||
7570 | break; | ||
7571 | default: | ||
7572 | spec->mixers[0] = ca0132_mixer; | ||
7573 | break; | ||
7574 | } | ||
7575 | |||
7576 | /* Setup whether or not to use alt functions/controls */ | ||
7577 | switch (spec->quirk) { | ||
7578 | case QUIRK_SBZ: | ||
7579 | case QUIRK_R3DI: | ||
7580 | spec->use_alt_controls = true; | ||
7581 | spec->use_alt_functions = true; | ||
7582 | break; | ||
7583 | default: | ||
7584 | spec->use_alt_controls = false; | ||
7585 | spec->use_alt_functions = false; | ||
7586 | break; | ||
7587 | } | ||
4763 | 7588 | ||
4764 | spec->base_init_verbs = ca0132_base_init_verbs; | 7589 | spec->base_init_verbs = ca0132_base_init_verbs; |
4765 | spec->base_exit_verbs = ca0132_base_exit_verbs; | 7590 | spec->base_exit_verbs = ca0132_base_exit_verbs; |