forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-09-20 cf4ce59b3b70238352c7f1729f0f7223214828ad
kernel/sound/pci/hda/patch_ca0132.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * HD audio interface patch for Creative CA0132 chip
34 *
....@@ -5,20 +6,6 @@
56 *
67 * Based on patch_ca0110.c
78 * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
8
- *
9
- * This driver is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; either version 2 of the License, or
12
- * (at your option) any later version.
13
- *
14
- * This driver is distributed in the hope that it will be useful,
15
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- * GNU General Public License for more details.
18
- *
19
- * You should have received a copy of the GNU General Public License
20
- * along with this program; if not, write to the Free Software
21
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
229 */
2310
2411 #include <linux/init.h>
....@@ -33,7 +20,7 @@
3320 #include <linux/pci.h>
3421 #include <asm/io.h>
3522 #include <sound/core.h>
36
-#include "hda_codec.h"
23
+#include <sound/hda_codec.h>
3724 #include "hda_local.h"
3825 #include "hda_auto_parser.h"
3926 #include "hda_jack.h"
....@@ -51,6 +38,8 @@
5138 #define FLOAT_ONE 0x3f800000
5239 #define FLOAT_TWO 0x40000000
5340 #define FLOAT_THREE 0x40400000
41
+#define FLOAT_FIVE 0x40a00000
42
+#define FLOAT_SIX 0x40c00000
5443 #define FLOAT_EIGHT 0x41000000
5544 #define FLOAT_MINUS_5 0xc0a00000
5645
....@@ -82,22 +71,22 @@
8271 #define SCP_GET 1
8372
8473 #define EFX_FILE "ctefx.bin"
85
-#define SBZ_EFX_FILE "ctefx-sbz.bin"
74
+#define DESKTOP_EFX_FILE "ctefx-desktop.bin"
8675 #define R3DI_EFX_FILE "ctefx-r3di.bin"
8776
8877 #ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP
8978 MODULE_FIRMWARE(EFX_FILE);
90
-MODULE_FIRMWARE(SBZ_EFX_FILE);
79
+MODULE_FIRMWARE(DESKTOP_EFX_FILE);
9180 MODULE_FIRMWARE(R3DI_EFX_FILE);
9281 #endif
9382
9483 static const char *const dirstr[2] = { "Playback", "Capture" };
9584
96
-#define NUM_OF_OUTPUTS 3
85
+#define NUM_OF_OUTPUTS 2
86
+static const char *const out_type_str[2] = { "Speakers", "Headphone" };
9787 enum {
9888 SPEAKER_OUT,
9989 HEADPHONE_OUT,
100
- SURROUND_OUT
10190 };
10291
10392 enum {
....@@ -153,7 +142,15 @@
153142 XBASS_XOVER,
154143 EQ_PRESET_ENUM,
155144 SMART_VOLUME_ENUM,
156
- MIC_BOOST_ENUM
145
+ MIC_BOOST_ENUM,
146
+ AE5_HEADPHONE_GAIN_ENUM,
147
+ AE5_SOUND_FILTER_ENUM,
148
+ ZXR_HEADPHONE_GAIN,
149
+ SPEAKER_CHANNEL_CFG_ENUM,
150
+ SPEAKER_FULL_RANGE_FRONT,
151
+ SPEAKER_FULL_RANGE_REAR,
152
+ BASS_REDIRECTION,
153
+ BASS_REDIRECTION_XOVER,
157154 #define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID)
158155 };
159156
....@@ -599,46 +596,108 @@
599596 }
600597 };
601598
602
-/* DSP command sequences for ca0132_alt_select_out */
603
-#define ALT_OUT_SET_MAX_COMMANDS 9 /* Max number of commands in sequence */
604
-struct ca0132_alt_out_set {
605
- char *name; /*preset name*/
606
- unsigned char commands;
607
- unsigned int mids[ALT_OUT_SET_MAX_COMMANDS];
608
- unsigned int reqs[ALT_OUT_SET_MAX_COMMANDS];
609
- unsigned int vals[ALT_OUT_SET_MAX_COMMANDS];
599
+/*
600
+ * DSP reqs for handling full-range speakers/bass redirection. If a speaker is
601
+ * set as not being full range, and bass redirection is enabled, all
602
+ * frequencies below the crossover frequency are redirected to the LFE
603
+ * channel. If the surround configuration has no LFE channel, this can't be
604
+ * enabled. X-Bass must be disabled when using these.
605
+ */
606
+enum speaker_range_reqs {
607
+ SPEAKER_BASS_REDIRECT = 0x15,
608
+ SPEAKER_BASS_REDIRECT_XOVER_FREQ = 0x16,
609
+ /* Between 0x16-0x1a are the X-Bass reqs. */
610
+ SPEAKER_FULL_RANGE_FRONT_L_R = 0x1a,
611
+ SPEAKER_FULL_RANGE_CENTER_LFE = 0x1b,
612
+ SPEAKER_FULL_RANGE_REAR_L_R = 0x1c,
613
+ SPEAKER_FULL_RANGE_SURROUND_L_R = 0x1d,
614
+ SPEAKER_BASS_REDIRECT_SUB_GAIN = 0x1e,
610615 };
611616
612
-static const struct ca0132_alt_out_set alt_out_presets[] = {
613
- { .name = "Line Out",
614
- .commands = 7,
615
- .mids = { 0x96, 0x96, 0x96, 0x8F,
616
- 0x96, 0x96, 0x96 },
617
- .reqs = { 0x19, 0x17, 0x18, 0x01,
618
- 0x1F, 0x15, 0x3A },
619
- .vals = { 0x3F000000, 0x42A00000, 0x00000000,
620
- 0x00000000, 0x00000000, 0x00000000,
621
- 0x00000000 }
617
+/*
618
+ * Definitions for the DSP req's to handle speaker tuning. These all belong to
619
+ * module ID 0x96, the output effects module.
620
+ */
621
+enum speaker_tuning_reqs {
622
+ /*
623
+ * Currently, this value is always set to 0.0f. However, on Windows,
624
+ * when selecting certain headphone profiles on the new Sound Blaster
625
+ * connect software, the QUERY_SPEAKER_EQ_ADDRESS req on mid 0x80 is
626
+ * sent. This gets the speaker EQ address area, which is then used to
627
+ * send over (presumably) an equalizer profile for the specific
628
+ * headphone setup. It is sent using the same method the DSP
629
+ * firmware is uploaded with, which I believe is why the 'ctspeq.bin'
630
+ * file exists in linux firmware tree but goes unused. It would also
631
+ * explain why the QUERY_SPEAKER_EQ_ADDRESS req is defined but unused.
632
+ * Once this profile is sent over, SPEAKER_TUNING_USE_SPEAKER_EQ is
633
+ * set to 1.0f.
634
+ */
635
+ SPEAKER_TUNING_USE_SPEAKER_EQ = 0x1f,
636
+ SPEAKER_TUNING_ENABLE_CENTER_EQ = 0x20,
637
+ SPEAKER_TUNING_FRONT_LEFT_VOL_LEVEL = 0x21,
638
+ SPEAKER_TUNING_FRONT_RIGHT_VOL_LEVEL = 0x22,
639
+ SPEAKER_TUNING_CENTER_VOL_LEVEL = 0x23,
640
+ SPEAKER_TUNING_LFE_VOL_LEVEL = 0x24,
641
+ SPEAKER_TUNING_REAR_LEFT_VOL_LEVEL = 0x25,
642
+ SPEAKER_TUNING_REAR_RIGHT_VOL_LEVEL = 0x26,
643
+ SPEAKER_TUNING_SURROUND_LEFT_VOL_LEVEL = 0x27,
644
+ SPEAKER_TUNING_SURROUND_RIGHT_VOL_LEVEL = 0x28,
645
+ /*
646
+ * Inversion is used when setting headphone virtualization to line
647
+ * out. Not sure why this is, but it's the only place it's ever used.
648
+ */
649
+ SPEAKER_TUNING_FRONT_LEFT_INVERT = 0x29,
650
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT = 0x2a,
651
+ SPEAKER_TUNING_CENTER_INVERT = 0x2b,
652
+ SPEAKER_TUNING_LFE_INVERT = 0x2c,
653
+ SPEAKER_TUNING_REAR_LEFT_INVERT = 0x2d,
654
+ SPEAKER_TUNING_REAR_RIGHT_INVERT = 0x2e,
655
+ SPEAKER_TUNING_SURROUND_LEFT_INVERT = 0x2f,
656
+ SPEAKER_TUNING_SURROUND_RIGHT_INVERT = 0x30,
657
+ /* Delay is used when setting surround speaker distance in Windows. */
658
+ SPEAKER_TUNING_FRONT_LEFT_DELAY = 0x31,
659
+ SPEAKER_TUNING_FRONT_RIGHT_DELAY = 0x32,
660
+ SPEAKER_TUNING_CENTER_DELAY = 0x33,
661
+ SPEAKER_TUNING_LFE_DELAY = 0x34,
662
+ SPEAKER_TUNING_REAR_LEFT_DELAY = 0x35,
663
+ SPEAKER_TUNING_REAR_RIGHT_DELAY = 0x36,
664
+ SPEAKER_TUNING_SURROUND_LEFT_DELAY = 0x37,
665
+ SPEAKER_TUNING_SURROUND_RIGHT_DELAY = 0x38,
666
+ /* Of these two, only mute seems to ever be used. */
667
+ SPEAKER_TUNING_MAIN_VOLUME = 0x39,
668
+ SPEAKER_TUNING_MUTE = 0x3a,
669
+};
670
+
671
+/* Surround output channel count configuration structures. */
672
+#define SPEAKER_CHANNEL_CFG_COUNT 5
673
+enum {
674
+ SPEAKER_CHANNELS_2_0,
675
+ SPEAKER_CHANNELS_2_1,
676
+ SPEAKER_CHANNELS_4_0,
677
+ SPEAKER_CHANNELS_4_1,
678
+ SPEAKER_CHANNELS_5_1,
679
+};
680
+
681
+struct ca0132_alt_speaker_channel_cfg {
682
+ char *name;
683
+ unsigned int val;
684
+};
685
+
686
+static const struct ca0132_alt_speaker_channel_cfg speaker_channel_cfgs[] = {
687
+ { .name = "2.0",
688
+ .val = FLOAT_ONE
622689 },
623
- { .name = "Headphone",
624
- .commands = 7,
625
- .mids = { 0x96, 0x96, 0x96, 0x8F,
626
- 0x96, 0x96, 0x96 },
627
- .reqs = { 0x19, 0x17, 0x18, 0x01,
628
- 0x1F, 0x15, 0x3A },
629
- .vals = { 0x3F000000, 0x42A00000, 0x00000000,
630
- 0x00000000, 0x00000000, 0x00000000,
631
- 0x00000000 }
690
+ { .name = "2.1",
691
+ .val = FLOAT_TWO
632692 },
633
- { .name = "Surround",
634
- .commands = 8,
635
- .mids = { 0x96, 0x8F, 0x96, 0x96,
636
- 0x96, 0x96, 0x96, 0x96 },
637
- .reqs = { 0x18, 0x01, 0x1F, 0x15,
638
- 0x3A, 0x1A, 0x1B, 0x1C },
639
- .vals = { 0x00000000, 0x00000000, 0x00000000,
640
- 0x00000000, 0x00000000, 0x00000000,
641
- 0x00000000, 0x00000000 }
693
+ { .name = "4.0",
694
+ .val = FLOAT_FIVE
695
+ },
696
+ { .name = "4.1",
697
+ .val = FLOAT_SIX
698
+ },
699
+ { .name = "5.1",
700
+ .val = FLOAT_EIGHT
642701 }
643702 };
644703
....@@ -667,6 +726,68 @@
667726 }
668727 };
669728
729
+/* Values for ca0113_mmio_command_set for selecting output. */
730
+#define AE_CA0113_OUT_SET_COMMANDS 6
731
+struct ae_ca0113_output_set {
732
+ unsigned int group[AE_CA0113_OUT_SET_COMMANDS];
733
+ unsigned int target[AE_CA0113_OUT_SET_COMMANDS];
734
+ unsigned int vals[NUM_OF_OUTPUTS][AE_CA0113_OUT_SET_COMMANDS];
735
+};
736
+
737
+static const struct ae_ca0113_output_set ae5_ca0113_output_presets = {
738
+ .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 },
739
+ .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 },
740
+ /* Speakers. */
741
+ .vals = { { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f },
742
+ /* Headphones. */
743
+ { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 } },
744
+};
745
+
746
+static const struct ae_ca0113_output_set ae7_ca0113_output_presets = {
747
+ .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 },
748
+ .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 },
749
+ /* Speakers. */
750
+ .vals = { { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f },
751
+ /* Headphones. */
752
+ { 0x3f, 0x3f, 0x00, 0x00, 0x02, 0x00 } },
753
+};
754
+
755
+/* ae5 ca0113 command sequences to set headphone gain levels. */
756
+#define AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS 4
757
+struct ae5_headphone_gain_set {
758
+ char *name;
759
+ unsigned int vals[AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS];
760
+};
761
+
762
+static const struct ae5_headphone_gain_set ae5_headphone_gain_presets[] = {
763
+ { .name = "Low (16-31",
764
+ .vals = { 0xff, 0x2c, 0xf5, 0x32 }
765
+ },
766
+ { .name = "Medium (32-149",
767
+ .vals = { 0x38, 0xa8, 0x3e, 0x4c }
768
+ },
769
+ { .name = "High (150-600",
770
+ .vals = { 0xff, 0xff, 0xff, 0x7f }
771
+ }
772
+};
773
+
774
+struct ae5_filter_set {
775
+ char *name;
776
+ unsigned int val;
777
+};
778
+
779
+static const struct ae5_filter_set ae5_filter_presets[] = {
780
+ { .name = "Slow Roll Off",
781
+ .val = 0xa0
782
+ },
783
+ { .name = "Minimum Phase",
784
+ .val = 0xc0
785
+ },
786
+ { .name = "Fast Roll Off",
787
+ .val = 0x80
788
+ }
789
+};
790
+
670791 enum hda_cmd_vendor_io {
671792 /* for DspIO node */
672793 VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000,
....@@ -686,6 +807,9 @@
686807 VENDOR_CHIPIO_DATA_LOW = 0x300,
687808 VENDOR_CHIPIO_DATA_HIGH = 0x400,
688809
810
+ VENDOR_CHIPIO_8051_WRITE_DIRECT = 0x500,
811
+ VENDOR_CHIPIO_8051_READ_DIRECT = 0xD00,
812
+
689813 VENDOR_CHIPIO_GET_PARAMETER = 0xF00,
690814 VENDOR_CHIPIO_STATUS = 0xF01,
691815 VENDOR_CHIPIO_HIC_POST_READ = 0x702,
....@@ -693,6 +817,9 @@
693817
694818 VENDOR_CHIPIO_8051_DATA_WRITE = 0x707,
695819 VENDOR_CHIPIO_8051_DATA_READ = 0xF07,
820
+ VENDOR_CHIPIO_8051_PMEM_READ = 0xF08,
821
+ VENDOR_CHIPIO_8051_IRAM_WRITE = 0x709,
822
+ VENDOR_CHIPIO_8051_IRAM_READ = 0xF09,
696823
697824 VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A,
698825 VENDOR_CHIPIO_CT_EXTENSIONS_GET = 0xF0A,
....@@ -798,6 +925,12 @@
798925 /* Port D output stage gain setting to use when 16 Ohm output
799926 * impedance is selected*/
800927 CONTROL_PARAM_PORTD_160OHM_GAIN = 10,
928
+
929
+ /*
930
+ * This control param name was found in the 8051 memory, and makes
931
+ * sense given the fact the AE-5 uses it and has the ASI flag set.
932
+ */
933
+ CONTROL_PARAM_ASI = 23,
801934
802935 /* Stream Control */
803936
....@@ -931,7 +1064,6 @@
9311064 unsigned int scp_resp_header;
9321065 unsigned int scp_resp_data[4];
9331066 unsigned int scp_resp_count;
934
- bool alt_firmware_present;
9351067 bool startup_check_entered;
9361068 bool dsp_reload;
9371069
....@@ -949,14 +1081,22 @@
9491081 /* ca0132_alt control related values */
9501082 unsigned char in_enum_val;
9511083 unsigned char out_enum_val;
1084
+ unsigned char channel_cfg_val;
1085
+ unsigned char speaker_range_val[2];
9521086 unsigned char mic_boost_enum_val;
9531087 unsigned char smart_volume_setting;
1088
+ unsigned char bass_redirection_val;
1089
+ long bass_redirect_xover_freq;
9541090 long fx_ctl_val[EFFECT_LEVEL_SLIDERS];
9551091 long xbass_xover_freq;
9561092 long eq_preset_val;
9571093 unsigned int tlv[4];
9581094 struct hda_vmaster_mute_hook vmaster_mute;
959
-
1095
+ /* AE-5 Control values */
1096
+ unsigned char ae5_headphone_gain_val;
1097
+ unsigned char ae5_filter_val;
1098
+ /* ZxR Control Values */
1099
+ unsigned char zxr_gain_set;
9601100
9611101 struct hda_codec *codec;
9621102 struct delayed_work unsol_hp_work;
....@@ -996,9 +1136,25 @@
9961136 QUIRK_ALIENWARE,
9971137 QUIRK_ALIENWARE_M17XR4,
9981138 QUIRK_SBZ,
1139
+ QUIRK_ZXR,
1140
+ QUIRK_ZXR_DBPRO,
9991141 QUIRK_R3DI,
10001142 QUIRK_R3D,
1143
+ QUIRK_AE5,
1144
+ QUIRK_AE7,
10011145 };
1146
+
1147
+#ifdef CONFIG_PCI
1148
+#define ca0132_quirk(spec) ((spec)->quirk)
1149
+#define ca0132_use_pci_mmio(spec) ((spec)->use_pci_mmio)
1150
+#define ca0132_use_alt_functions(spec) ((spec)->use_alt_functions)
1151
+#define ca0132_use_alt_controls(spec) ((spec)->use_alt_controls)
1152
+#else
1153
+#define ca0132_quirk(spec) ({ (void)(spec); QUIRK_NONE; })
1154
+#define ca0132_use_alt_functions(spec) ({ (void)(spec); false; })
1155
+#define ca0132_use_pci_mmio(spec) ({ (void)(spec); false; })
1156
+#define ca0132_use_alt_controls(spec) ({ (void)(spec); false; })
1157
+#endif
10021158
10031159 static const struct hda_pintbl alienware_pincfgs[] = {
10041160 { 0x0b, 0x90170110 }, /* Builtin Speaker */
....@@ -1029,6 +1185,21 @@
10291185 {}
10301186 };
10311187
1188
+/* Sound Blaster ZxR pin configs taken from Windows Driver */
1189
+static const struct hda_pintbl zxr_pincfgs[] = {
1190
+ { 0x0b, 0x01047110 }, /* Port G -- Lineout FRONT L/R */
1191
+ { 0x0c, 0x414510f0 }, /* SPDIF Out 1 - Disabled*/
1192
+ { 0x0d, 0x014510f0 }, /* Digital Out */
1193
+ { 0x0e, 0x41c520f0 }, /* SPDIF In - Disabled*/
1194
+ { 0x0f, 0x0122711f }, /* Port A -- BackPanel HP */
1195
+ { 0x10, 0x01017111 }, /* Port D -- Center/LFE */
1196
+ { 0x11, 0x01017114 }, /* Port B -- LineMicIn2 / Rear L/R */
1197
+ { 0x12, 0x01a271f0 }, /* Port C -- LineIn1 */
1198
+ { 0x13, 0x908700f0 }, /* What U Hear In*/
1199
+ { 0x18, 0x50d000f0 }, /* N/A */
1200
+ {}
1201
+};
1202
+
10321203 /* Recon3D pin configs taken from Windows Driver */
10331204 static const struct hda_pintbl r3d_pincfgs[] = {
10341205 { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */
....@@ -1039,6 +1210,21 @@
10391210 { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */
10401211 { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */
10411212 { 0x12, 0x02a090f0 }, /* Port C -- LineIn1 */
1213
+ { 0x13, 0x908700f0 }, /* What U Hear In*/
1214
+ { 0x18, 0x50d000f0 }, /* N/A */
1215
+ {}
1216
+};
1217
+
1218
+/* Sound Blaster AE-5 pin configs taken from Windows Driver */
1219
+static const struct hda_pintbl ae5_pincfgs[] = {
1220
+ { 0x0b, 0x01017010 }, /* Port G -- Lineout FRONT L/R */
1221
+ { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
1222
+ { 0x0d, 0x014510f0 }, /* Digital Out */
1223
+ { 0x0e, 0x01c510f0 }, /* SPDIF In */
1224
+ { 0x0f, 0x01017114 }, /* Port A -- Rear L/R. */
1225
+ { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */
1226
+ { 0x11, 0x012170ff }, /* Port B -- LineMicIn2 / Rear Headphone */
1227
+ { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */
10421228 { 0x13, 0x908700f0 }, /* What U Hear In*/
10431229 { 0x18, 0x50d000f0 }, /* N/A */
10441230 {}
....@@ -1059,6 +1245,20 @@
10591245 {}
10601246 };
10611247
1248
+static const struct hda_pintbl ae7_pincfgs[] = {
1249
+ { 0x0b, 0x01017010 },
1250
+ { 0x0c, 0x014510f0 },
1251
+ { 0x0d, 0x414510f0 },
1252
+ { 0x0e, 0x01c520f0 },
1253
+ { 0x0f, 0x01017114 },
1254
+ { 0x10, 0x01017011 },
1255
+ { 0x11, 0x018170ff },
1256
+ { 0x12, 0x01a170f0 },
1257
+ { 0x13, 0x908700f0 },
1258
+ { 0x18, 0x500000f0 },
1259
+ {}
1260
+};
1261
+
10621262 static const struct snd_pci_quirk ca0132_quirks[] = {
10631263 SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4),
10641264 SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
....@@ -1066,12 +1266,213 @@
10661266 SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
10671267 SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ),
10681268 SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ),
1269
+ SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", QUIRK_SBZ),
1270
+ SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_SBZ),
10691271 SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
10701272 SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
10711273 SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
10721274 SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
1275
+ SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI),
1276
+ SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI),
10731277 SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
1278
+ SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
1279
+ SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5),
1280
+ SND_PCI_QUIRK(0x1102, 0x0191, "Sound Blaster AE-5 Plus", QUIRK_AE5),
1281
+ SND_PCI_QUIRK(0x1102, 0x0081, "Sound Blaster AE-7", QUIRK_AE7),
10741282 {}
1283
+};
1284
+
1285
+/* Output selection quirk info structures. */
1286
+#define MAX_QUIRK_MMIO_GPIO_SET_VALS 3
1287
+#define MAX_QUIRK_SCP_SET_VALS 2
1288
+struct ca0132_alt_out_set_info {
1289
+ unsigned int dac2port; /* ParamID 0x0d value. */
1290
+
1291
+ bool has_hda_gpio;
1292
+ char hda_gpio_pin;
1293
+ char hda_gpio_set;
1294
+
1295
+ unsigned int mmio_gpio_count;
1296
+ char mmio_gpio_pin[MAX_QUIRK_MMIO_GPIO_SET_VALS];
1297
+ char mmio_gpio_set[MAX_QUIRK_MMIO_GPIO_SET_VALS];
1298
+
1299
+ unsigned int scp_cmds_count;
1300
+ unsigned int scp_cmd_mid[MAX_QUIRK_SCP_SET_VALS];
1301
+ unsigned int scp_cmd_req[MAX_QUIRK_SCP_SET_VALS];
1302
+ unsigned int scp_cmd_val[MAX_QUIRK_SCP_SET_VALS];
1303
+
1304
+ bool has_chipio_write;
1305
+ unsigned int chipio_write_addr;
1306
+ unsigned int chipio_write_data;
1307
+};
1308
+
1309
+struct ca0132_alt_out_set_quirk_data {
1310
+ int quirk_id;
1311
+
1312
+ bool has_headphone_gain;
1313
+ bool is_ae_series;
1314
+
1315
+ struct ca0132_alt_out_set_info out_set_info[NUM_OF_OUTPUTS];
1316
+};
1317
+
1318
+static const struct ca0132_alt_out_set_quirk_data quirk_out_set_data[] = {
1319
+ { .quirk_id = QUIRK_R3DI,
1320
+ .has_headphone_gain = false,
1321
+ .is_ae_series = false,
1322
+ .out_set_info = {
1323
+ /* Speakers. */
1324
+ { .dac2port = 0x24,
1325
+ .has_hda_gpio = true,
1326
+ .hda_gpio_pin = 2,
1327
+ .hda_gpio_set = 1,
1328
+ .mmio_gpio_count = 0,
1329
+ .scp_cmds_count = 0,
1330
+ .has_chipio_write = false,
1331
+ },
1332
+ /* Headphones. */
1333
+ { .dac2port = 0x21,
1334
+ .has_hda_gpio = true,
1335
+ .hda_gpio_pin = 2,
1336
+ .hda_gpio_set = 0,
1337
+ .mmio_gpio_count = 0,
1338
+ .scp_cmds_count = 0,
1339
+ .has_chipio_write = false,
1340
+ } },
1341
+ },
1342
+ { .quirk_id = QUIRK_R3D,
1343
+ .has_headphone_gain = false,
1344
+ .is_ae_series = false,
1345
+ .out_set_info = {
1346
+ /* Speakers. */
1347
+ { .dac2port = 0x24,
1348
+ .has_hda_gpio = false,
1349
+ .mmio_gpio_count = 1,
1350
+ .mmio_gpio_pin = { 1 },
1351
+ .mmio_gpio_set = { 1 },
1352
+ .scp_cmds_count = 0,
1353
+ .has_chipio_write = false,
1354
+ },
1355
+ /* Headphones. */
1356
+ { .dac2port = 0x21,
1357
+ .has_hda_gpio = false,
1358
+ .mmio_gpio_count = 1,
1359
+ .mmio_gpio_pin = { 1 },
1360
+ .mmio_gpio_set = { 0 },
1361
+ .scp_cmds_count = 0,
1362
+ .has_chipio_write = false,
1363
+ } },
1364
+ },
1365
+ { .quirk_id = QUIRK_SBZ,
1366
+ .has_headphone_gain = false,
1367
+ .is_ae_series = false,
1368
+ .out_set_info = {
1369
+ /* Speakers. */
1370
+ { .dac2port = 0x18,
1371
+ .has_hda_gpio = false,
1372
+ .mmio_gpio_count = 3,
1373
+ .mmio_gpio_pin = { 7, 4, 1 },
1374
+ .mmio_gpio_set = { 0, 1, 1 },
1375
+ .scp_cmds_count = 0,
1376
+ .has_chipio_write = false, },
1377
+ /* Headphones. */
1378
+ { .dac2port = 0x12,
1379
+ .has_hda_gpio = false,
1380
+ .mmio_gpio_count = 3,
1381
+ .mmio_gpio_pin = { 7, 4, 1 },
1382
+ .mmio_gpio_set = { 1, 1, 0 },
1383
+ .scp_cmds_count = 0,
1384
+ .has_chipio_write = false,
1385
+ } },
1386
+ },
1387
+ { .quirk_id = QUIRK_ZXR,
1388
+ .has_headphone_gain = true,
1389
+ .is_ae_series = false,
1390
+ .out_set_info = {
1391
+ /* Speakers. */
1392
+ { .dac2port = 0x24,
1393
+ .has_hda_gpio = false,
1394
+ .mmio_gpio_count = 3,
1395
+ .mmio_gpio_pin = { 2, 3, 5 },
1396
+ .mmio_gpio_set = { 1, 1, 0 },
1397
+ .scp_cmds_count = 0,
1398
+ .has_chipio_write = false,
1399
+ },
1400
+ /* Headphones. */
1401
+ { .dac2port = 0x21,
1402
+ .has_hda_gpio = false,
1403
+ .mmio_gpio_count = 3,
1404
+ .mmio_gpio_pin = { 2, 3, 5 },
1405
+ .mmio_gpio_set = { 0, 1, 1 },
1406
+ .scp_cmds_count = 0,
1407
+ .has_chipio_write = false,
1408
+ } },
1409
+ },
1410
+ { .quirk_id = QUIRK_AE5,
1411
+ .has_headphone_gain = true,
1412
+ .is_ae_series = true,
1413
+ .out_set_info = {
1414
+ /* Speakers. */
1415
+ { .dac2port = 0xa4,
1416
+ .has_hda_gpio = false,
1417
+ .mmio_gpio_count = 0,
1418
+ .scp_cmds_count = 2,
1419
+ .scp_cmd_mid = { 0x96, 0x96 },
1420
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1421
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1422
+ .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO },
1423
+ .has_chipio_write = true,
1424
+ .chipio_write_addr = 0x0018b03c,
1425
+ .chipio_write_data = 0x00000012
1426
+ },
1427
+ /* Headphones. */
1428
+ { .dac2port = 0xa1,
1429
+ .has_hda_gpio = false,
1430
+ .mmio_gpio_count = 0,
1431
+ .scp_cmds_count = 2,
1432
+ .scp_cmd_mid = { 0x96, 0x96 },
1433
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1434
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1435
+ .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE },
1436
+ .has_chipio_write = true,
1437
+ .chipio_write_addr = 0x0018b03c,
1438
+ .chipio_write_data = 0x00000012
1439
+ } },
1440
+ },
1441
+ { .quirk_id = QUIRK_AE7,
1442
+ .has_headphone_gain = true,
1443
+ .is_ae_series = true,
1444
+ .out_set_info = {
1445
+ /* Speakers. */
1446
+ { .dac2port = 0x58,
1447
+ .has_hda_gpio = false,
1448
+ .mmio_gpio_count = 1,
1449
+ .mmio_gpio_pin = { 0 },
1450
+ .mmio_gpio_set = { 1 },
1451
+ .scp_cmds_count = 2,
1452
+ .scp_cmd_mid = { 0x96, 0x96 },
1453
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1454
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1455
+ .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO },
1456
+ .has_chipio_write = true,
1457
+ .chipio_write_addr = 0x0018b03c,
1458
+ .chipio_write_data = 0x00000000
1459
+ },
1460
+ /* Headphones. */
1461
+ { .dac2port = 0x58,
1462
+ .has_hda_gpio = false,
1463
+ .mmio_gpio_count = 1,
1464
+ .mmio_gpio_pin = { 0 },
1465
+ .mmio_gpio_set = { 1 },
1466
+ .scp_cmds_count = 2,
1467
+ .scp_cmd_mid = { 0x96, 0x96 },
1468
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1469
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1470
+ .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE },
1471
+ .has_chipio_write = true,
1472
+ .chipio_write_addr = 0x0018b03c,
1473
+ .chipio_write_data = 0x00000010
1474
+ } },
1475
+ }
10751476 };
10761477
10771478 /*
....@@ -1456,6 +1857,20 @@
14561857 }
14571858
14581859 /*
1860
+ * Writes to the 8051's internal address space directly instead of indirectly,
1861
+ * giving access to the special function registers located at addresses
1862
+ * 0x80-0xFF.
1863
+ */
1864
+static void chipio_8051_write_direct(struct hda_codec *codec,
1865
+ unsigned int addr, unsigned int data)
1866
+{
1867
+ unsigned int verb;
1868
+
1869
+ verb = VENDOR_CHIPIO_8051_WRITE_DIRECT | data;
1870
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, verb, addr);
1871
+}
1872
+
1873
+/*
14591874 * Enable clocks.
14601875 */
14611876 static void chipio_enable_clocks(struct hda_codec *codec)
....@@ -1798,6 +2213,7 @@
17982213 * Prepare and send the SCP message to DSP
17992214 * @codec: the HDA codec
18002215 * @mod_id: ID of the DSP module to send the command
2216
+ * @src_id: ID of the source
18012217 * @req: ID of request to send to the DSP module
18022218 * @dir: SET or GET
18032219 * @data: pointer to the data to send with the request, request specific
....@@ -1916,7 +2332,7 @@
19162332 static int dspio_alloc_dma_chan(struct hda_codec *codec, unsigned int *dma_chan)
19172333 {
19182334 int status = 0;
1919
- unsigned int size = sizeof(dma_chan);
2335
+ unsigned int size = sizeof(*dma_chan);
19202336
19212337 codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n");
19222338 status = dspio_scp(codec, MASTERCONTROL, 0x20,
....@@ -2572,7 +2988,7 @@
25722988 u32 magic;
25732989 u32 chip_addr;
25742990 u32 count;
2575
- u32 data[0];
2991
+ u32 data[];
25762992 };
25772993
25782994 static const u32 g_magic_value = 0x4c46584d;
....@@ -2595,7 +3011,7 @@
25953011
25963012 static size_t dsp_sizeof(const struct dsp_image_seg *p)
25973013 {
2598
- return sizeof(*p) + p->count*sizeof(u32);
3014
+ return struct_size(p, data, p->count);
25993015 }
26003016
26013017 static const struct dsp_image_seg *get_next_seg_ptr(
....@@ -2701,7 +3117,7 @@
27013117 }
27023118
27033119 data = fls->data;
2704
- chip_addx = fls->chip_addr,
3120
+ chip_addx = fls->chip_addr;
27053121 words_to_write = fls->count;
27063122
27073123 if (!words_to_write)
....@@ -2976,7 +3392,7 @@
29763392 {
29773393 struct ca0132_spec *spec = codec->spec;
29783394 codec_dbg(codec, "---- dspload_post_setup ------\n");
2979
- if (!spec->use_alt_functions) {
3395
+ if (!ca0132_use_alt_functions(spec)) {
29803396 /*set DSP speaker to 2.0 configuration*/
29813397 chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080);
29823398 chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000);
....@@ -3091,7 +3507,9 @@
30913507 }
30923508
30933509 /*
3094
- * Setup GPIO for the other variants of Core3D.
3510
+ * ca0113 related functions. The ca0113 acts as the HDA bus for the pci-e
3511
+ * based cards, and has a second mmio region, region2, that's used for special
3512
+ * commands.
30953513 */
30963514
30973515 /*
....@@ -3099,8 +3517,11 @@
30993517 * the mmio address 0x320 is used to set GPIO pins. The format for the data
31003518 * The first eight bits are just the number of the pin. So far, I've only seen
31013519 * this number go to 7.
3520
+ * AE-5 note: The AE-5 seems to use pins 2 and 3 to somehow set the color value
3521
+ * of the on-card LED. It seems to use pin 2 for data, then toggles 3 to on and
3522
+ * then off to send that bit.
31023523 */
3103
-static void ca0132_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin,
3524
+static void ca0113_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin,
31043525 bool enable)
31053526 {
31063527 struct ca0132_spec *spec = codec->spec;
....@@ -3113,6 +3534,89 @@
31133534 }
31143535
31153536 /*
3537
+ * Special pci region2 commands that are only used by the AE-5. They follow
3538
+ * a set format, and require reads at certain points to seemingly 'clear'
3539
+ * the response data. My first tests didn't do these reads, and would cause
3540
+ * the card to get locked up until the memory was read. These commands
3541
+ * seem to work with three distinct values that I've taken to calling group,
3542
+ * target-id, and value.
3543
+ */
3544
+static void ca0113_mmio_command_set(struct hda_codec *codec, unsigned int group,
3545
+ unsigned int target, unsigned int value)
3546
+{
3547
+ struct ca0132_spec *spec = codec->spec;
3548
+ unsigned int write_val;
3549
+
3550
+ writel(0x0000007e, spec->mem_base + 0x210);
3551
+ readl(spec->mem_base + 0x210);
3552
+ writel(0x0000005a, spec->mem_base + 0x210);
3553
+ readl(spec->mem_base + 0x210);
3554
+ readl(spec->mem_base + 0x210);
3555
+
3556
+ writel(0x00800005, spec->mem_base + 0x20c);
3557
+ writel(group, spec->mem_base + 0x804);
3558
+
3559
+ writel(0x00800005, spec->mem_base + 0x20c);
3560
+ write_val = (target & 0xff);
3561
+ write_val |= (value << 8);
3562
+
3563
+
3564
+ writel(write_val, spec->mem_base + 0x204);
3565
+ /*
3566
+ * Need delay here or else it goes too fast and works inconsistently.
3567
+ */
3568
+ msleep(20);
3569
+
3570
+ readl(spec->mem_base + 0x860);
3571
+ readl(spec->mem_base + 0x854);
3572
+ readl(spec->mem_base + 0x840);
3573
+
3574
+ writel(0x00800004, spec->mem_base + 0x20c);
3575
+ writel(0x00000000, spec->mem_base + 0x210);
3576
+ readl(spec->mem_base + 0x210);
3577
+ readl(spec->mem_base + 0x210);
3578
+}
3579
+
3580
+/*
3581
+ * This second type of command is used for setting the sound filter type.
3582
+ */
3583
+static void ca0113_mmio_command_set_type2(struct hda_codec *codec,
3584
+ unsigned int group, unsigned int target, unsigned int value)
3585
+{
3586
+ struct ca0132_spec *spec = codec->spec;
3587
+ unsigned int write_val;
3588
+
3589
+ writel(0x0000007e, spec->mem_base + 0x210);
3590
+ readl(spec->mem_base + 0x210);
3591
+ writel(0x0000005a, spec->mem_base + 0x210);
3592
+ readl(spec->mem_base + 0x210);
3593
+ readl(spec->mem_base + 0x210);
3594
+
3595
+ writel(0x00800003, spec->mem_base + 0x20c);
3596
+ writel(group, spec->mem_base + 0x804);
3597
+
3598
+ writel(0x00800005, spec->mem_base + 0x20c);
3599
+ write_val = (target & 0xff);
3600
+ write_val |= (value << 8);
3601
+
3602
+
3603
+ writel(write_val, spec->mem_base + 0x204);
3604
+ msleep(20);
3605
+ readl(spec->mem_base + 0x860);
3606
+ readl(spec->mem_base + 0x854);
3607
+ readl(spec->mem_base + 0x840);
3608
+
3609
+ writel(0x00800004, spec->mem_base + 0x20c);
3610
+ writel(0x00000000, spec->mem_base + 0x210);
3611
+ readl(spec->mem_base + 0x210);
3612
+ readl(spec->mem_base + 0x210);
3613
+}
3614
+
3615
+/*
3616
+ * Setup GPIO for the other variants of Core3D.
3617
+ */
3618
+
3619
+/*
31163620 * Sets up the GPIO pins so that they are discoverable. If this isn't done,
31173621 * the card shows as having no GPIO pins.
31183622 */
....@@ -3120,8 +3624,10 @@
31203624 {
31213625 struct ca0132_spec *spec = codec->spec;
31223626
3123
- switch (spec->quirk) {
3627
+ switch (ca0132_quirk(spec)) {
31243628 case QUIRK_SBZ:
3629
+ case QUIRK_AE5:
3630
+ case QUIRK_AE7:
31253631 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
31263632 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
31273633 snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23);
....@@ -3129,6 +3635,8 @@
31293635 case QUIRK_R3DI:
31303636 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
31313637 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5B);
3638
+ break;
3639
+ default:
31323640 break;
31333641 }
31343642
....@@ -3139,7 +3647,7 @@
31393647 {
31403648 struct ca0132_spec *spec = codec->spec;
31413649
3142
- switch (spec->quirk) {
3650
+ switch (ca0132_quirk(spec)) {
31433651 case QUIRK_SBZ:
31443652 snd_hda_codec_write(codec, 0x01, 0,
31453653 AC_VERB_SET_GPIO_DIRECTION, 0x07);
....@@ -3157,6 +3665,8 @@
31573665 AC_VERB_SET_GPIO_MASK, 0x1F);
31583666 snd_hda_codec_write(codec, 0x01, 0,
31593667 AC_VERB_SET_GPIO_DATA, 0x0C);
3668
+ break;
3669
+ default:
31603670 break;
31613671 }
31623672 }
....@@ -3217,26 +3727,6 @@
32173727 break;
32183728 case R3DI_FRONT_MIC:
32193729 cur_gpio |= (1 << R3DI_MIC_SELECT_BIT);
3220
- break;
3221
- }
3222
- snd_hda_codec_write(codec, codec->core.afg, 0,
3223
- AC_VERB_SET_GPIO_DATA, cur_gpio);
3224
-}
3225
-
3226
-static void r3di_gpio_out_set(struct hda_codec *codec,
3227
- enum r3di_out_select cur_out)
3228
-{
3229
- unsigned int cur_gpio;
3230
-
3231
- /* Get the current GPIO Data setup */
3232
- cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0);
3233
-
3234
- switch (cur_out) {
3235
- case R3DI_HEADPHONE_OUT:
3236
- cur_gpio &= ~(1 << R3DI_OUT_SELECT_BIT);
3237
- break;
3238
- case R3DI_LINE_OUT:
3239
- cur_gpio |= (1 << R3DI_OUT_SELECT_BIT);
32403730 break;
32413731 }
32423732 snd_hda_codec_write(codec, codec->core.afg, 0,
....@@ -3550,7 +4040,7 @@
35504040 /* The following are for tuning of products */
35514041 #ifdef ENABLE_TUNING_CONTROLS
35524042
3553
-static unsigned int voice_focus_vals_lookup[] = {
4043
+static const unsigned int voice_focus_vals_lookup[] = {
35544044 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000,
35554045 0x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000,
35564046 0x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000,
....@@ -3580,7 +4070,7 @@
35804070 0x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000
35814071 };
35824072
3583
-static unsigned int mic_svm_vals_lookup[] = {
4073
+static const unsigned int mic_svm_vals_lookup[] = {
35844074 0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
35854075 0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
35864076 0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
....@@ -3600,7 +4090,7 @@
36004090 0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
36014091 };
36024092
3603
-static unsigned int equalizer_vals_lookup[] = {
4093
+static const unsigned int equalizer_vals_lookup[] = {
36044094 0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
36054095 0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
36064096 0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
....@@ -3613,14 +4103,16 @@
36134103 };
36144104
36154105 static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
3616
- unsigned int *lookup, int idx)
4106
+ const unsigned int *lookup, int idx)
36174107 {
36184108 int i = 0;
36194109
36204110 for (i = 0; i < TUNING_CTLS_COUNT; i++)
36214111 if (nid == ca0132_tuning_ctls[i].nid)
3622
- break;
4112
+ goto found;
36234113
4114
+ return -EINVAL;
4115
+found:
36244116 snd_hda_power_up(codec);
36254117 dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20,
36264118 ca0132_tuning_ctls[i].req,
....@@ -3931,24 +4423,221 @@
39314423 return err < 0 ? err : 0;
39324424 }
39334425
4426
+static int ae5_headphone_gain_set(struct hda_codec *codec, long val);
4427
+static int zxr_headphone_gain_set(struct hda_codec *codec, long val);
4428
+static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
4429
+
4430
+static void ae5_mmio_select_out(struct hda_codec *codec)
4431
+{
4432
+ struct ca0132_spec *spec = codec->spec;
4433
+ const struct ae_ca0113_output_set *out_cmds;
4434
+ unsigned int i;
4435
+
4436
+ if (ca0132_quirk(spec) == QUIRK_AE5)
4437
+ out_cmds = &ae5_ca0113_output_presets;
4438
+ else
4439
+ out_cmds = &ae7_ca0113_output_presets;
4440
+
4441
+ for (i = 0; i < AE_CA0113_OUT_SET_COMMANDS; i++)
4442
+ ca0113_mmio_command_set(codec, out_cmds->group[i],
4443
+ out_cmds->target[i],
4444
+ out_cmds->vals[spec->cur_out_type][i]);
4445
+}
4446
+
4447
+static int ca0132_alt_set_full_range_speaker(struct hda_codec *codec)
4448
+{
4449
+ struct ca0132_spec *spec = codec->spec;
4450
+ int quirk = ca0132_quirk(spec);
4451
+ unsigned int tmp;
4452
+ int err;
4453
+
4454
+ /* 2.0/4.0 setup has no LFE channel, so setting full-range does nothing. */
4455
+ if (spec->channel_cfg_val == SPEAKER_CHANNELS_4_0
4456
+ || spec->channel_cfg_val == SPEAKER_CHANNELS_2_0)
4457
+ return 0;
4458
+
4459
+ /* Set front L/R full range. Zero for full-range, one for redirection. */
4460
+ tmp = spec->speaker_range_val[0] ? FLOAT_ZERO : FLOAT_ONE;
4461
+ err = dspio_set_uint_param(codec, 0x96,
4462
+ SPEAKER_FULL_RANGE_FRONT_L_R, tmp);
4463
+ if (err < 0)
4464
+ return err;
4465
+
4466
+ /* When setting full-range rear, both rear and center/lfe are set. */
4467
+ tmp = spec->speaker_range_val[1] ? FLOAT_ZERO : FLOAT_ONE;
4468
+ err = dspio_set_uint_param(codec, 0x96,
4469
+ SPEAKER_FULL_RANGE_CENTER_LFE, tmp);
4470
+ if (err < 0)
4471
+ return err;
4472
+
4473
+ err = dspio_set_uint_param(codec, 0x96,
4474
+ SPEAKER_FULL_RANGE_REAR_L_R, tmp);
4475
+ if (err < 0)
4476
+ return err;
4477
+
4478
+ /*
4479
+ * Only the AE series cards set this value when setting full-range,
4480
+ * and it's always 1.0f.
4481
+ */
4482
+ if (quirk == QUIRK_AE5 || quirk == QUIRK_AE7) {
4483
+ err = dspio_set_uint_param(codec, 0x96,
4484
+ SPEAKER_FULL_RANGE_SURROUND_L_R, FLOAT_ONE);
4485
+ if (err < 0)
4486
+ return err;
4487
+ }
4488
+
4489
+ return 0;
4490
+}
4491
+
4492
+static int ca0132_alt_surround_set_bass_redirection(struct hda_codec *codec,
4493
+ bool val)
4494
+{
4495
+ struct ca0132_spec *spec = codec->spec;
4496
+ unsigned int tmp;
4497
+ int err;
4498
+
4499
+ if (val && spec->channel_cfg_val != SPEAKER_CHANNELS_4_0 &&
4500
+ spec->channel_cfg_val != SPEAKER_CHANNELS_2_0)
4501
+ tmp = FLOAT_ONE;
4502
+ else
4503
+ tmp = FLOAT_ZERO;
4504
+
4505
+ err = dspio_set_uint_param(codec, 0x96, SPEAKER_BASS_REDIRECT, tmp);
4506
+ if (err < 0)
4507
+ return err;
4508
+
4509
+ /* If it is enabled, make sure to set the crossover frequency. */
4510
+ if (tmp) {
4511
+ tmp = float_xbass_xover_lookup[spec->xbass_xover_freq];
4512
+ err = dspio_set_uint_param(codec, 0x96,
4513
+ SPEAKER_BASS_REDIRECT_XOVER_FREQ, tmp);
4514
+ if (err < 0)
4515
+ return err;
4516
+ }
4517
+
4518
+ return 0;
4519
+}
4520
+
4521
+/*
4522
+ * These are the commands needed to setup output on each of the different card
4523
+ * types.
4524
+ */
4525
+static void ca0132_alt_select_out_get_quirk_data(struct hda_codec *codec,
4526
+ const struct ca0132_alt_out_set_quirk_data **quirk_data)
4527
+{
4528
+ struct ca0132_spec *spec = codec->spec;
4529
+ int quirk = ca0132_quirk(spec);
4530
+ unsigned int i;
4531
+
4532
+ *quirk_data = NULL;
4533
+ for (i = 0; i < ARRAY_SIZE(quirk_out_set_data); i++) {
4534
+ if (quirk_out_set_data[i].quirk_id == quirk) {
4535
+ *quirk_data = &quirk_out_set_data[i];
4536
+ return;
4537
+ }
4538
+ }
4539
+}
4540
+
4541
+static int ca0132_alt_select_out_quirk_set(struct hda_codec *codec)
4542
+{
4543
+ const struct ca0132_alt_out_set_quirk_data *quirk_data;
4544
+ const struct ca0132_alt_out_set_info *out_info;
4545
+ struct ca0132_spec *spec = codec->spec;
4546
+ unsigned int i, gpio_data;
4547
+ int err;
4548
+
4549
+ ca0132_alt_select_out_get_quirk_data(codec, &quirk_data);
4550
+ if (!quirk_data)
4551
+ return 0;
4552
+
4553
+ out_info = &quirk_data->out_set_info[spec->cur_out_type];
4554
+ if (quirk_data->is_ae_series)
4555
+ ae5_mmio_select_out(codec);
4556
+
4557
+ if (out_info->has_hda_gpio) {
4558
+ gpio_data = snd_hda_codec_read(codec, codec->core.afg, 0,
4559
+ AC_VERB_GET_GPIO_DATA, 0);
4560
+
4561
+ if (out_info->hda_gpio_set)
4562
+ gpio_data |= (1 << out_info->hda_gpio_pin);
4563
+ else
4564
+ gpio_data &= ~(1 << out_info->hda_gpio_pin);
4565
+
4566
+ snd_hda_codec_write(codec, codec->core.afg, 0,
4567
+ AC_VERB_SET_GPIO_DATA, gpio_data);
4568
+ }
4569
+
4570
+ if (out_info->mmio_gpio_count) {
4571
+ for (i = 0; i < out_info->mmio_gpio_count; i++) {
4572
+ ca0113_mmio_gpio_set(codec, out_info->mmio_gpio_pin[i],
4573
+ out_info->mmio_gpio_set[i]);
4574
+ }
4575
+ }
4576
+
4577
+ if (out_info->scp_cmds_count) {
4578
+ for (i = 0; i < out_info->scp_cmds_count; i++) {
4579
+ err = dspio_set_uint_param(codec,
4580
+ out_info->scp_cmd_mid[i],
4581
+ out_info->scp_cmd_req[i],
4582
+ out_info->scp_cmd_val[i]);
4583
+ if (err < 0)
4584
+ return err;
4585
+ }
4586
+ }
4587
+
4588
+ chipio_set_control_param(codec, 0x0d, out_info->dac2port);
4589
+
4590
+ if (out_info->has_chipio_write) {
4591
+ chipio_write(codec, out_info->chipio_write_addr,
4592
+ out_info->chipio_write_data);
4593
+ }
4594
+
4595
+ if (quirk_data->has_headphone_gain) {
4596
+ if (spec->cur_out_type != HEADPHONE_OUT) {
4597
+ if (quirk_data->is_ae_series)
4598
+ ae5_headphone_gain_set(codec, 2);
4599
+ else
4600
+ zxr_headphone_gain_set(codec, 0);
4601
+ } else {
4602
+ if (quirk_data->is_ae_series)
4603
+ ae5_headphone_gain_set(codec,
4604
+ spec->ae5_headphone_gain_val);
4605
+ else
4606
+ zxr_headphone_gain_set(codec,
4607
+ spec->zxr_gain_set);
4608
+ }
4609
+ }
4610
+
4611
+ return 0;
4612
+}
4613
+
4614
+static void ca0132_set_out_node_pincfg(struct hda_codec *codec, hda_nid_t nid,
4615
+ bool out_enable, bool hp_enable)
4616
+{
4617
+ unsigned int pin_ctl;
4618
+
4619
+ pin_ctl = snd_hda_codec_read(codec, nid, 0,
4620
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4621
+
4622
+ pin_ctl = hp_enable ? pin_ctl | PIN_HP_AMP : pin_ctl & ~PIN_HP_AMP;
4623
+ pin_ctl = out_enable ? pin_ctl | PIN_OUT : pin_ctl & ~PIN_OUT;
4624
+ snd_hda_set_pin_ctl(codec, nid, pin_ctl);
4625
+}
4626
+
39344627 /*
39354628 * This function behaves similarly to the ca0132_select_out funciton above,
39364629 * except with a few differences. It adds the ability to select the current
39374630 * output with an enumerated control "output source" if the auto detect
39384631 * mute switch is set to off. If the auto detect mute switch is enabled, it
39394632 * will detect either headphone or lineout(SPEAKER_OUT) from jack detection.
3940
- * It also adds the ability to auto-detect the front headphone port. The only
3941
- * way to select surround is to disable auto detect, and set Surround with the
3942
- * enumerated control.
4633
+ * It also adds the ability to auto-detect the front headphone port.
39434634 */
39444635 static int ca0132_alt_select_out(struct hda_codec *codec)
39454636 {
39464637 struct ca0132_spec *spec = codec->spec;
3947
- unsigned int pin_ctl;
4638
+ unsigned int tmp, outfx_set;
39484639 int jack_present;
39494640 int auto_jack;
3950
- unsigned int i;
3951
- unsigned int tmp;
39524641 int err;
39534642 /* Default Headphone is rear headphone */
39544643 hda_nid_t headphone_nid = spec->out_pins[1];
....@@ -3975,156 +4664,112 @@
39754664 } else
39764665 spec->cur_out_type = spec->out_enum_val;
39774666
3978
- /* Begin DSP output switch */
3979
- tmp = FLOAT_ONE;
3980
- err = dspio_set_uint_param(codec, 0x96, 0x3A, tmp);
4667
+ outfx_set = spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID];
4668
+
4669
+ /* Begin DSP output switch, mute DSP volume. */
4670
+ err = dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_MUTE, FLOAT_ONE);
39814671 if (err < 0)
4672
+ goto exit;
4673
+
4674
+ if (ca0132_alt_select_out_quirk_set(codec) < 0)
39824675 goto exit;
39834676
39844677 switch (spec->cur_out_type) {
39854678 case SPEAKER_OUT:
39864679 codec_dbg(codec, "%s speaker\n", __func__);
3987
- /*speaker out config*/
3988
- switch (spec->quirk) {
3989
- case QUIRK_SBZ:
3990
- ca0132_mmio_gpio_set(codec, 7, false);
3991
- ca0132_mmio_gpio_set(codec, 4, true);
3992
- ca0132_mmio_gpio_set(codec, 1, true);
3993
- chipio_set_control_param(codec, 0x0D, 0x18);
3994
- break;
3995
- case QUIRK_R3DI:
3996
- chipio_set_control_param(codec, 0x0D, 0x24);
3997
- r3di_gpio_out_set(codec, R3DI_LINE_OUT);
3998
- break;
3999
- case QUIRK_R3D:
4000
- chipio_set_control_param(codec, 0x0D, 0x24);
4001
- ca0132_mmio_gpio_set(codec, 1, true);
4002
- break;
4003
- }
40044680
4005
- /* disable headphone node */
4006
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
4007
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4008
- snd_hda_set_pin_ctl(codec, spec->out_pins[1],
4009
- pin_ctl & ~PIN_HP);
4010
- /* enable line-out node */
4011
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
4012
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4013
- snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4014
- pin_ctl | PIN_OUT);
40154681 /* Enable EAPD */
40164682 snd_hda_codec_write(codec, spec->out_pins[0], 0,
40174683 AC_VERB_SET_EAPD_BTLENABLE, 0x01);
40184684
4019
- /* If PlayEnhancement is enabled, set different source */
4020
- if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4021
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
4685
+ /* Disable headphone node. */
4686
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[1], 0, 0);
4687
+ /* Set front L-R to output. */
4688
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 1, 0);
4689
+ /* Set Center/LFE to output. */
4690
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 1, 0);
4691
+ /* Set rear surround to output. */
4692
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 1, 0);
4693
+
4694
+ /*
4695
+ * Without PlayEnhancement being enabled, if we've got a 2.0
4696
+ * setup, set it to floating point eight to disable any DSP
4697
+ * processing effects.
4698
+ */
4699
+ if (!outfx_set && spec->channel_cfg_val == SPEAKER_CHANNELS_2_0)
4700
+ tmp = FLOAT_EIGHT;
40224701 else
4023
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT);
4702
+ tmp = speaker_channel_cfgs[spec->channel_cfg_val].val;
4703
+
4704
+ err = dspio_set_uint_param(codec, 0x80, 0x04, tmp);
4705
+ if (err < 0)
4706
+ goto exit;
4707
+
40244708 break;
40254709 case HEADPHONE_OUT:
40264710 codec_dbg(codec, "%s hp\n", __func__);
4027
- /* Headphone out config*/
4028
- switch (spec->quirk) {
4029
- case QUIRK_SBZ:
4030
- ca0132_mmio_gpio_set(codec, 7, true);
4031
- ca0132_mmio_gpio_set(codec, 4, true);
4032
- ca0132_mmio_gpio_set(codec, 1, false);
4033
- chipio_set_control_param(codec, 0x0D, 0x12);
4034
- break;
4035
- case QUIRK_R3DI:
4036
- chipio_set_control_param(codec, 0x0D, 0x21);
4037
- r3di_gpio_out_set(codec, R3DI_HEADPHONE_OUT);
4038
- break;
4039
- case QUIRK_R3D:
4040
- chipio_set_control_param(codec, 0x0D, 0x21);
4041
- ca0132_mmio_gpio_set(codec, 0x1, false);
4042
- break;
4043
- }
4044
-
40454711 snd_hda_codec_write(codec, spec->out_pins[0], 0,
40464712 AC_VERB_SET_EAPD_BTLENABLE, 0x00);
40474713
4048
- /* disable speaker*/
4049
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
4050
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4051
- snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4052
- pin_ctl & ~PIN_HP);
4714
+ /* Disable all speaker nodes. */
4715
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 0, 0);
4716
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 0, 0);
4717
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 0, 0);
40534718
40544719 /* enable headphone, either front or rear */
4055
-
40564720 if (snd_hda_jack_detect(codec, spec->unsol_tag_front_hp))
40574721 headphone_nid = spec->out_pins[2];
40584722 else if (snd_hda_jack_detect(codec, spec->unsol_tag_hp))
40594723 headphone_nid = spec->out_pins[1];
40604724
4061
- pin_ctl = snd_hda_codec_read(codec, headphone_nid, 0,
4062
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4063
- snd_hda_set_pin_ctl(codec, headphone_nid,
4064
- pin_ctl | PIN_HP);
4725
+ ca0132_set_out_node_pincfg(codec, headphone_nid, 1, 1);
40654726
4066
- if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4067
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
4727
+ if (outfx_set)
4728
+ err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
40684729 else
4069
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO);
4070
- break;
4071
- case SURROUND_OUT:
4072
- codec_dbg(codec, "%s surround\n", __func__);
4073
- /* Surround out config*/
4074
- switch (spec->quirk) {
4075
- case QUIRK_SBZ:
4076
- ca0132_mmio_gpio_set(codec, 7, false);
4077
- ca0132_mmio_gpio_set(codec, 4, true);
4078
- ca0132_mmio_gpio_set(codec, 1, true);
4079
- chipio_set_control_param(codec, 0x0D, 0x18);
4080
- break;
4081
- case QUIRK_R3DI:
4082
- chipio_set_control_param(codec, 0x0D, 0x24);
4083
- r3di_gpio_out_set(codec, R3DI_LINE_OUT);
4084
- break;
4085
- case QUIRK_R3D:
4086
- ca0132_mmio_gpio_set(codec, 1, true);
4087
- chipio_set_control_param(codec, 0x0D, 0x24);
4088
- break;
4089
- }
4090
- /* enable line out node */
4091
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
4092
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4093
- snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4094
- pin_ctl | PIN_OUT);
4095
- /* Disable headphone out */
4096
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
4097
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4098
- snd_hda_set_pin_ctl(codec, spec->out_pins[1],
4099
- pin_ctl & ~PIN_HP);
4100
- /* Enable EAPD on line out */
4101
- snd_hda_codec_write(codec, spec->out_pins[0], 0,
4102
- AC_VERB_SET_EAPD_BTLENABLE, 0x01);
4103
- /* enable center/lfe out node */
4104
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[2], 0,
4105
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4106
- snd_hda_set_pin_ctl(codec, spec->out_pins[2],
4107
- pin_ctl | PIN_OUT);
4108
- /* Now set rear surround node as out. */
4109
- pin_ctl = snd_hda_codec_read(codec, spec->out_pins[3], 0,
4110
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4111
- snd_hda_set_pin_ctl(codec, spec->out_pins[3],
4112
- pin_ctl | PIN_OUT);
4730
+ err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO);
41134731
4114
- if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4115
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
4116
- else
4117
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT);
4732
+ if (err < 0)
4733
+ goto exit;
41184734 break;
41194735 }
4736
+ /*
4737
+ * If output effects are enabled, set the X-Bass effect value again to
4738
+ * make sure that it's properly enabled/disabled for speaker
4739
+ * configurations with an LFE channel.
4740
+ */
4741
+ if (outfx_set)
4742
+ ca0132_effects_set(codec, X_BASS,
4743
+ spec->effects_switch[X_BASS - EFFECT_START_NID]);
41204744
4121
- /* run through the output dsp commands for line-out */
4122
- for (i = 0; i < alt_out_presets[spec->cur_out_type].commands; i++) {
4123
- err = dspio_set_uint_param(codec,
4124
- alt_out_presets[spec->cur_out_type].mids[i],
4125
- alt_out_presets[spec->cur_out_type].reqs[i],
4126
- alt_out_presets[spec->cur_out_type].vals[i]);
4745
+ /* Set speaker EQ bypass attenuation to 0. */
4746
+ err = dspio_set_uint_param(codec, 0x8f, 0x01, FLOAT_ZERO);
4747
+ if (err < 0)
4748
+ goto exit;
41274749
4750
+ /*
4751
+ * Although unused on all cards but the AE series, this is always set
4752
+ * to zero when setting the output.
4753
+ */
4754
+ err = dspio_set_uint_param(codec, 0x96,
4755
+ SPEAKER_TUNING_USE_SPEAKER_EQ, FLOAT_ZERO);
4756
+ if (err < 0)
4757
+ goto exit;
4758
+
4759
+ if (spec->cur_out_type == SPEAKER_OUT)
4760
+ err = ca0132_alt_surround_set_bass_redirection(codec,
4761
+ spec->bass_redirection_val);
4762
+ else
4763
+ err = ca0132_alt_surround_set_bass_redirection(codec, 0);
4764
+
4765
+ /* Unmute DSP now that we're done with output selection. */
4766
+ err = dspio_set_uint_param(codec, 0x96,
4767
+ SPEAKER_TUNING_MUTE, FLOAT_ZERO);
4768
+ if (err < 0)
4769
+ goto exit;
4770
+
4771
+ if (spec->cur_out_type == SPEAKER_OUT) {
4772
+ err = ca0132_alt_set_full_range_speaker(codec);
41284773 if (err < 0)
41294774 goto exit;
41304775 }
....@@ -4141,7 +4786,7 @@
41414786 to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
41424787 struct hda_jack_tbl *jack;
41434788
4144
- if (spec->use_alt_functions)
4789
+ if (ca0132_use_alt_functions(spec))
41454790 ca0132_alt_select_out(spec->codec);
41464791 else
41474792 ca0132_select_out(spec->codec);
....@@ -4155,7 +4800,6 @@
41554800
41564801 static void ca0132_set_dmic(struct hda_codec *codec, int enable);
41574802 static int ca0132_mic_boost_set(struct hda_codec *codec, long val);
4158
-static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
41594803 static void resume_mic1(struct hda_codec *codec, unsigned int oldval);
41604804 static int stop_mic1(struct hda_codec *codec);
41614805 static int ca0132_cvoice_switch_set(struct hda_codec *codec);
....@@ -4226,14 +4870,14 @@
42264870
42274871 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
42284872 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4229
- if (spec->quirk == QUIRK_R3DI)
4873
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
42304874 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
42314875
42324876
42334877 if (spec->in_enum_val == REAR_LINE_IN)
42344878 tmp = FLOAT_ZERO;
42354879 else {
4236
- if (spec->quirk == QUIRK_SBZ)
4880
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
42374881 tmp = FLOAT_THREE;
42384882 else
42394883 tmp = FLOAT_ONE;
....@@ -4245,7 +4889,7 @@
42454889 codec_dbg(codec, "%s: on.", __func__);
42464890 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000);
42474891 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000);
4248
- if (spec->quirk == QUIRK_R3DI)
4892
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
42494893 chipio_set_conn_rate(codec, 0x0F, SR_16_000);
42504894
42514895 if (spec->effects_switch[VOICE_FOCUS - EFFECT_START_NID])
....@@ -4341,15 +4985,31 @@
43414985
43424986 switch (spec->cur_mic_type) {
43434987 case REAR_MIC:
4344
- switch (spec->quirk) {
4988
+ switch (ca0132_quirk(spec)) {
43454989 case QUIRK_SBZ:
43464990 case QUIRK_R3D:
4347
- ca0132_mmio_gpio_set(codec, 0, false);
4991
+ ca0113_mmio_gpio_set(codec, 0, false);
4992
+ tmp = FLOAT_THREE;
4993
+ break;
4994
+ case QUIRK_ZXR:
43484995 tmp = FLOAT_THREE;
43494996 break;
43504997 case QUIRK_R3DI:
43514998 r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
43524999 tmp = FLOAT_ONE;
5000
+ break;
5001
+ case QUIRK_AE5:
5002
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
5003
+ tmp = FLOAT_THREE;
5004
+ break;
5005
+ case QUIRK_AE7:
5006
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
5007
+ tmp = FLOAT_THREE;
5008
+ chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
5009
+ SR_96_000);
5010
+ chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
5011
+ SR_96_000);
5012
+ dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
43535013 break;
43545014 default:
43555015 tmp = FLOAT_ONE;
....@@ -4358,60 +5018,95 @@
43585018
43595019 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
43605020 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4361
- if (spec->quirk == QUIRK_R3DI)
5021
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
43625022 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
43635023
43645024 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
43655025
43665026 chipio_set_stream_control(codec, 0x03, 1);
43675027 chipio_set_stream_control(codec, 0x04, 1);
4368
-
4369
- if (spec->quirk == QUIRK_SBZ) {
5028
+ switch (ca0132_quirk(spec)) {
5029
+ case QUIRK_SBZ:
43705030 chipio_write(codec, 0x18B098, 0x0000000C);
43715031 chipio_write(codec, 0x18B09C, 0x0000000C);
5032
+ break;
5033
+ case QUIRK_ZXR:
5034
+ chipio_write(codec, 0x18B098, 0x0000000C);
5035
+ chipio_write(codec, 0x18B09C, 0x000000CC);
5036
+ break;
5037
+ case QUIRK_AE5:
5038
+ chipio_write(codec, 0x18B098, 0x0000000C);
5039
+ chipio_write(codec, 0x18B09C, 0x0000004C);
5040
+ break;
5041
+ default:
5042
+ break;
43725043 }
43735044 ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
43745045 break;
43755046 case REAR_LINE_IN:
43765047 ca0132_mic_boost_set(codec, 0);
4377
- switch (spec->quirk) {
5048
+ switch (ca0132_quirk(spec)) {
43785049 case QUIRK_SBZ:
43795050 case QUIRK_R3D:
4380
- ca0132_mmio_gpio_set(codec, 0, false);
5051
+ ca0113_mmio_gpio_set(codec, 0, false);
43815052 break;
43825053 case QUIRK_R3DI:
43835054 r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
5055
+ break;
5056
+ case QUIRK_AE5:
5057
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
5058
+ break;
5059
+ case QUIRK_AE7:
5060
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
5061
+ chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
5062
+ SR_96_000);
5063
+ chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
5064
+ SR_96_000);
5065
+ dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
5066
+ break;
5067
+ default:
43845068 break;
43855069 }
43865070
43875071 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
43885072 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4389
- if (spec->quirk == QUIRK_R3DI)
5073
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
43905074 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
43915075
4392
- tmp = FLOAT_ZERO;
5076
+ if (ca0132_quirk(spec) == QUIRK_AE7)
5077
+ tmp = FLOAT_THREE;
5078
+ else
5079
+ tmp = FLOAT_ZERO;
43935080 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
43945081
4395
- if (spec->quirk == QUIRK_SBZ) {
5082
+ switch (ca0132_quirk(spec)) {
5083
+ case QUIRK_SBZ:
5084
+ case QUIRK_AE5:
43965085 chipio_write(codec, 0x18B098, 0x00000000);
43975086 chipio_write(codec, 0x18B09C, 0x00000000);
5087
+ break;
5088
+ default:
5089
+ break;
43985090 }
4399
-
44005091 chipio_set_stream_control(codec, 0x03, 1);
44015092 chipio_set_stream_control(codec, 0x04, 1);
44025093 break;
44035094 case FRONT_MIC:
4404
- switch (spec->quirk) {
5095
+ switch (ca0132_quirk(spec)) {
44055096 case QUIRK_SBZ:
44065097 case QUIRK_R3D:
4407
- ca0132_mmio_gpio_set(codec, 0, true);
4408
- ca0132_mmio_gpio_set(codec, 5, false);
5098
+ ca0113_mmio_gpio_set(codec, 0, true);
5099
+ ca0113_mmio_gpio_set(codec, 5, false);
44095100 tmp = FLOAT_THREE;
44105101 break;
44115102 case QUIRK_R3DI:
44125103 r3di_gpio_mic_set(codec, R3DI_FRONT_MIC);
44135104 tmp = FLOAT_ONE;
44145105 break;
5106
+ case QUIRK_AE5:
5107
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
5108
+ tmp = FLOAT_THREE;
5109
+ break;
44155110 default:
44165111 tmp = FLOAT_ONE;
44175112 break;
....@@ -4419,7 +5114,7 @@
44195114
44205115 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
44215116 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4422
- if (spec->quirk == QUIRK_R3DI)
5117
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
44235118 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
44245119
44255120 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
....@@ -4427,9 +5122,17 @@
44275122 chipio_set_stream_control(codec, 0x03, 1);
44285123 chipio_set_stream_control(codec, 0x04, 1);
44295124
4430
- if (spec->quirk == QUIRK_SBZ) {
5125
+ switch (ca0132_quirk(spec)) {
5126
+ case QUIRK_SBZ:
44315127 chipio_write(codec, 0x18B098, 0x0000000C);
44325128 chipio_write(codec, 0x18B09C, 0x000000CC);
5129
+ break;
5130
+ case QUIRK_AE5:
5131
+ chipio_write(codec, 0x18B098, 0x0000000C);
5132
+ chipio_write(codec, 0x18B09C, 0x0000004C);
5133
+ break;
5134
+ default:
5135
+ break;
44335136 }
44345137 ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
44355138 break;
....@@ -4438,7 +5141,6 @@
44385141
44395142 snd_hda_power_down_pm(codec);
44405143 return 0;
4441
-
44425144 }
44435145
44445146 /*
....@@ -4497,7 +5199,7 @@
44975199 static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val)
44985200 {
44995201 struct ca0132_spec *spec = codec->spec;
4500
- unsigned int on, tmp;
5202
+ unsigned int on, tmp, channel_cfg;
45015203 int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
45025204 int err = 0;
45035205 int idx = nid - EFFECT_START_NID;
....@@ -4510,6 +5212,12 @@
45105212 /* if PE if off, turn off out effects. */
45115213 if (!spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
45125214 val = 0;
5215
+ if (spec->cur_out_type == SPEAKER_OUT && nid == X_BASS) {
5216
+ channel_cfg = spec->channel_cfg_val;
5217
+ if (channel_cfg != SPEAKER_CHANNELS_2_0 &&
5218
+ channel_cfg != SPEAKER_CHANNELS_4_0)
5219
+ val = 0;
5220
+ }
45135221 }
45145222
45155223 /* for in effect, qualify with CrystalVoice */
....@@ -4523,7 +5231,7 @@
45235231 val = 0;
45245232
45255233 /* If Voice Focus on SBZ, set to two channel. */
4526
- if ((nid == VOICE_FOCUS) && (spec->use_pci_mmio)
5234
+ if ((nid == VOICE_FOCUS) && ca0132_use_pci_mmio(spec)
45275235 && (spec->cur_mic_type != REAR_LINE_IN)) {
45285236 if (spec->effects_switch[CRYSTAL_VOICE -
45295237 EFFECT_START_NID]) {
....@@ -4542,7 +5250,7 @@
45425250 * For SBZ noise reduction, there's an extra command
45435251 * to module ID 0x47. No clue why.
45445252 */
4545
- if ((nid == NOISE_REDUCTION) && (spec->use_pci_mmio)
5253
+ if ((nid == NOISE_REDUCTION) && ca0132_use_pci_mmio(spec)
45465254 && (spec->cur_mic_type != REAR_LINE_IN)) {
45475255 if (spec->effects_switch[CRYSTAL_VOICE -
45485256 EFFECT_START_NID]) {
....@@ -4558,7 +5266,7 @@
45585266 }
45595267
45605268 /* If rear line in disable effects. */
4561
- if (spec->use_alt_functions &&
5269
+ if (ca0132_use_alt_functions(spec) &&
45625270 spec->in_enum_val == REAR_LINE_IN)
45635271 val = 0;
45645272 }
....@@ -4588,7 +5296,7 @@
45885296 codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n",
45895297 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]);
45905298
4591
- if (spec->use_alt_functions)
5299
+ if (ca0132_use_alt_functions(spec))
45925300 ca0132_alt_select_out(codec);
45935301
45945302 i = OUT_EFFECT_START_NID - EFFECT_START_NID;
....@@ -4648,7 +5356,7 @@
46485356
46495357 /* set correct vipsource */
46505358 oldval = stop_mic1(codec);
4651
- if (spec->use_alt_functions)
5359
+ if (ca0132_use_alt_functions(spec))
46525360 ret |= ca0132_alt_set_vipsource(codec, 1);
46535361 else
46545362 ret |= ca0132_set_vipsource(codec, 1);
....@@ -4681,6 +5389,27 @@
46815389 return ret;
46825390 }
46835391
5392
+static int ae5_headphone_gain_set(struct hda_codec *codec, long val)
5393
+{
5394
+ unsigned int i;
5395
+
5396
+ for (i = 0; i < 4; i++)
5397
+ ca0113_mmio_command_set(codec, 0x48, 0x11 + i,
5398
+ ae5_headphone_gain_presets[val].vals[i]);
5399
+ return 0;
5400
+}
5401
+
5402
+/*
5403
+ * gpio pin 1 is a relay that switches on/off, apparently setting the headphone
5404
+ * amplifier to handle a 600 ohm load.
5405
+ */
5406
+static int zxr_headphone_gain_set(struct hda_codec *codec, long val)
5407
+{
5408
+ ca0113_mmio_gpio_set(codec, 1, val);
5409
+
5410
+ return 0;
5411
+}
5412
+
46845413 static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol,
46855414 struct snd_ctl_elem_value *ucontrol)
46865415 {
....@@ -4696,7 +5425,7 @@
46965425 auto_jack =
46975426 spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
46985427 if (!auto_jack) {
4699
- if (spec->use_alt_functions)
5428
+ if (ca0132_use_alt_functions(spec))
47005429 ca0132_alt_select_out(codec);
47015430 else
47025431 ca0132_select_out(codec);
....@@ -4713,7 +5442,7 @@
47135442 }
47145443
47155444 if (nid == VNID_HP_ASEL) {
4716
- if (spec->use_alt_functions)
5445
+ if (ca0132_use_alt_functions(spec))
47175446 ca0132_alt_select_out(codec);
47185447 else
47195448 ca0132_select_out(codec);
....@@ -4744,6 +5473,18 @@
47445473 return ret;
47455474 }
47465475 /* End of control change helpers. */
5476
+
5477
+static void ca0132_alt_bass_redirection_xover_set(struct hda_codec *codec,
5478
+ long idx)
5479
+{
5480
+ snd_hda_power_up(codec);
5481
+
5482
+ dspio_set_param(codec, 0x96, 0x20, SPEAKER_BASS_REDIRECT_XOVER_FREQ,
5483
+ &(float_xbass_xover_lookup[idx]), sizeof(unsigned int));
5484
+
5485
+ snd_hda_power_down(codec);
5486
+}
5487
+
47475488 /*
47485489 * Below I've added controls to mess with the effect levels, I've only enabled
47495490 * them on the Sound Blaster Z, but they would probably also work on the
....@@ -4752,6 +5493,7 @@
47525493 */
47535494
47545495 /* Sets DSP effect level from the sliders above the controls */
5496
+
47555497 static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid,
47565498 const unsigned int *lookup, int idx)
47575499 {
....@@ -4797,8 +5539,13 @@
47975539 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
47985540 struct ca0132_spec *spec = codec->spec;
47995541 long *valp = ucontrol->value.integer.value;
5542
+ hda_nid_t nid = get_amp_nid(kcontrol);
48005543
4801
- *valp = spec->xbass_xover_freq;
5544
+ if (nid == BASS_REDIRECTION_XOVER)
5545
+ *valp = spec->bass_redirect_xover_freq;
5546
+ else
5547
+ *valp = spec->xbass_xover_freq;
5548
+
48025549 return 0;
48035550 }
48045551
....@@ -4852,16 +5599,25 @@
48525599 struct ca0132_spec *spec = codec->spec;
48535600 hda_nid_t nid = get_amp_nid(kcontrol);
48545601 long *valp = ucontrol->value.integer.value;
5602
+ long *cur_val;
48555603 int idx;
48565604
5605
+ if (nid == BASS_REDIRECTION_XOVER)
5606
+ cur_val = &spec->bass_redirect_xover_freq;
5607
+ else
5608
+ cur_val = &spec->xbass_xover_freq;
5609
+
48575610 /* any change? */
4858
- if (spec->xbass_xover_freq == *valp)
5611
+ if (*cur_val == *valp)
48595612 return 0;
48605613
4861
- spec->xbass_xover_freq = *valp;
5614
+ *cur_val = *valp;
48625615
48635616 idx = *valp;
4864
- ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx);
5617
+ if (nid == BASS_REDIRECTION_XOVER)
5618
+ ca0132_alt_bass_redirection_xover_set(codec, *cur_val);
5619
+ else
5620
+ ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx);
48655621
48665622 return 0;
48675623 }
....@@ -4945,6 +5701,112 @@
49455701 return 1;
49465702 }
49475703
5704
+/*
5705
+ * Sound BlasterX AE-5 Headphone Gain Controls.
5706
+ */
5707
+#define AE5_HEADPHONE_GAIN_MAX 3
5708
+static int ae5_headphone_gain_info(struct snd_kcontrol *kcontrol,
5709
+ struct snd_ctl_elem_info *uinfo)
5710
+{
5711
+ char *sfx = " Ohms)";
5712
+ char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
5713
+
5714
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5715
+ uinfo->count = 1;
5716
+ uinfo->value.enumerated.items = AE5_HEADPHONE_GAIN_MAX;
5717
+ if (uinfo->value.enumerated.item >= AE5_HEADPHONE_GAIN_MAX)
5718
+ uinfo->value.enumerated.item = AE5_HEADPHONE_GAIN_MAX - 1;
5719
+ sprintf(namestr, "%s %s",
5720
+ ae5_headphone_gain_presets[uinfo->value.enumerated.item].name,
5721
+ sfx);
5722
+ strcpy(uinfo->value.enumerated.name, namestr);
5723
+ return 0;
5724
+}
5725
+
5726
+static int ae5_headphone_gain_get(struct snd_kcontrol *kcontrol,
5727
+ struct snd_ctl_elem_value *ucontrol)
5728
+{
5729
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5730
+ struct ca0132_spec *spec = codec->spec;
5731
+
5732
+ ucontrol->value.enumerated.item[0] = spec->ae5_headphone_gain_val;
5733
+ return 0;
5734
+}
5735
+
5736
+static int ae5_headphone_gain_put(struct snd_kcontrol *kcontrol,
5737
+ struct snd_ctl_elem_value *ucontrol)
5738
+{
5739
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5740
+ struct ca0132_spec *spec = codec->spec;
5741
+ int sel = ucontrol->value.enumerated.item[0];
5742
+ unsigned int items = AE5_HEADPHONE_GAIN_MAX;
5743
+
5744
+ if (sel >= items)
5745
+ return 0;
5746
+
5747
+ codec_dbg(codec, "ae5_headphone_gain: boost=%d\n",
5748
+ sel);
5749
+
5750
+ spec->ae5_headphone_gain_val = sel;
5751
+
5752
+ if (spec->out_enum_val == HEADPHONE_OUT)
5753
+ ae5_headphone_gain_set(codec, spec->ae5_headphone_gain_val);
5754
+
5755
+ return 1;
5756
+}
5757
+
5758
+/*
5759
+ * Sound BlasterX AE-5 sound filter enumerated control.
5760
+ */
5761
+#define AE5_SOUND_FILTER_MAX 3
5762
+
5763
+static int ae5_sound_filter_info(struct snd_kcontrol *kcontrol,
5764
+ struct snd_ctl_elem_info *uinfo)
5765
+{
5766
+ char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
5767
+
5768
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5769
+ uinfo->count = 1;
5770
+ uinfo->value.enumerated.items = AE5_SOUND_FILTER_MAX;
5771
+ if (uinfo->value.enumerated.item >= AE5_SOUND_FILTER_MAX)
5772
+ uinfo->value.enumerated.item = AE5_SOUND_FILTER_MAX - 1;
5773
+ sprintf(namestr, "%s",
5774
+ ae5_filter_presets[uinfo->value.enumerated.item].name);
5775
+ strcpy(uinfo->value.enumerated.name, namestr);
5776
+ return 0;
5777
+}
5778
+
5779
+static int ae5_sound_filter_get(struct snd_kcontrol *kcontrol,
5780
+ struct snd_ctl_elem_value *ucontrol)
5781
+{
5782
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5783
+ struct ca0132_spec *spec = codec->spec;
5784
+
5785
+ ucontrol->value.enumerated.item[0] = spec->ae5_filter_val;
5786
+ return 0;
5787
+}
5788
+
5789
+static int ae5_sound_filter_put(struct snd_kcontrol *kcontrol,
5790
+ struct snd_ctl_elem_value *ucontrol)
5791
+{
5792
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5793
+ struct ca0132_spec *spec = codec->spec;
5794
+ int sel = ucontrol->value.enumerated.item[0];
5795
+ unsigned int items = AE5_SOUND_FILTER_MAX;
5796
+
5797
+ if (sel >= items)
5798
+ return 0;
5799
+
5800
+ codec_dbg(codec, "ae5_sound_filter: %s\n",
5801
+ ae5_filter_presets[sel].name);
5802
+
5803
+ spec->ae5_filter_val = sel;
5804
+
5805
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07,
5806
+ ae5_filter_presets[sel].val);
5807
+
5808
+ return 1;
5809
+}
49485810
49495811 /*
49505812 * Input Select Control for alternative ca0132 codecs. This exists because
....@@ -4982,6 +5844,13 @@
49825844 int sel = ucontrol->value.enumerated.item[0];
49835845 unsigned int items = IN_SRC_NUM_OF_INPUTS;
49845846
5847
+ /*
5848
+ * The AE-7 has no front microphone, so limit items to 2: rear mic and
5849
+ * line-in.
5850
+ */
5851
+ if (ca0132_quirk(spec) == QUIRK_AE7)
5852
+ items = 2;
5853
+
49855854 if (sel >= items)
49865855 return 0;
49875856
....@@ -5005,7 +5874,7 @@
50055874 if (uinfo->value.enumerated.item >= NUM_OF_OUTPUTS)
50065875 uinfo->value.enumerated.item = NUM_OF_OUTPUTS - 1;
50075876 strcpy(uinfo->value.enumerated.name,
5008
- alt_out_presets[uinfo->value.enumerated.item].name);
5877
+ out_type_str[uinfo->value.enumerated.item]);
50095878 return 0;
50105879 }
50115880
....@@ -5032,13 +5901,61 @@
50325901 return 0;
50335902
50345903 codec_dbg(codec, "ca0132_alt_output_select: sel=%d, preset=%s\n",
5035
- sel, alt_out_presets[sel].name);
5904
+ sel, out_type_str[sel]);
50365905
50375906 spec->out_enum_val = sel;
50385907
50395908 auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
50405909
50415910 if (!auto_jack)
5911
+ ca0132_alt_select_out(codec);
5912
+
5913
+ return 1;
5914
+}
5915
+
5916
+/* Select surround output type: 2.1, 4.0, 4.1, or 5.1. */
5917
+static int ca0132_alt_speaker_channel_cfg_get_info(struct snd_kcontrol *kcontrol,
5918
+ struct snd_ctl_elem_info *uinfo)
5919
+{
5920
+ unsigned int items = SPEAKER_CHANNEL_CFG_COUNT;
5921
+
5922
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5923
+ uinfo->count = 1;
5924
+ uinfo->value.enumerated.items = items;
5925
+ if (uinfo->value.enumerated.item >= items)
5926
+ uinfo->value.enumerated.item = items - 1;
5927
+ strcpy(uinfo->value.enumerated.name,
5928
+ speaker_channel_cfgs[uinfo->value.enumerated.item].name);
5929
+ return 0;
5930
+}
5931
+
5932
+static int ca0132_alt_speaker_channel_cfg_get(struct snd_kcontrol *kcontrol,
5933
+ struct snd_ctl_elem_value *ucontrol)
5934
+{
5935
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5936
+ struct ca0132_spec *spec = codec->spec;
5937
+
5938
+ ucontrol->value.enumerated.item[0] = spec->channel_cfg_val;
5939
+ return 0;
5940
+}
5941
+
5942
+static int ca0132_alt_speaker_channel_cfg_put(struct snd_kcontrol *kcontrol,
5943
+ struct snd_ctl_elem_value *ucontrol)
5944
+{
5945
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5946
+ struct ca0132_spec *spec = codec->spec;
5947
+ int sel = ucontrol->value.enumerated.item[0];
5948
+ unsigned int items = SPEAKER_CHANNEL_CFG_COUNT;
5949
+
5950
+ if (sel >= items)
5951
+ return 0;
5952
+
5953
+ codec_dbg(codec, "ca0132_alt_speaker_channels: sel=%d, channels=%s\n",
5954
+ sel, speaker_channel_cfgs[sel].name);
5955
+
5956
+ spec->channel_cfg_val = sel;
5957
+
5958
+ if (spec->out_enum_val == SPEAKER_OUT)
50425959 ca0132_alt_select_out(codec);
50435960
50445961 return 1;
....@@ -5265,6 +6182,21 @@
52656182 return 0;
52666183 }
52676184
6185
+ if (nid == ZXR_HEADPHONE_GAIN) {
6186
+ *valp = spec->zxr_gain_set;
6187
+ return 0;
6188
+ }
6189
+
6190
+ if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) {
6191
+ *valp = spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT];
6192
+ return 0;
6193
+ }
6194
+
6195
+ if (nid == BASS_REDIRECTION) {
6196
+ *valp = spec->bass_redirection_val;
6197
+ return 0;
6198
+ }
6199
+
52686200 return 0;
52696201 }
52706202
....@@ -5321,7 +6253,7 @@
53216253 /* mic boost */
53226254 if (nid == spec->input_pins[0]) {
53236255 spec->cur_mic_boost = *valp;
5324
- if (spec->use_alt_functions) {
6256
+ if (ca0132_use_alt_functions(spec)) {
53256257 if (spec->in_enum_val != REAR_LINE_IN)
53266258 changed = ca0132_mic_boost_set(codec, *valp);
53276259 } else {
....@@ -5331,6 +6263,32 @@
53316263 }
53326264
53336265 goto exit;
6266
+ }
6267
+
6268
+ if (nid == ZXR_HEADPHONE_GAIN) {
6269
+ spec->zxr_gain_set = *valp;
6270
+ if (spec->cur_out_type == HEADPHONE_OUT)
6271
+ changed = zxr_headphone_gain_set(codec, *valp);
6272
+ else
6273
+ changed = 0;
6274
+
6275
+ goto exit;
6276
+ }
6277
+
6278
+ if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) {
6279
+ spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT] = *valp;
6280
+ if (spec->cur_out_type == SPEAKER_OUT)
6281
+ ca0132_alt_set_full_range_speaker(codec);
6282
+
6283
+ changed = 0;
6284
+ }
6285
+
6286
+ if (nid == BASS_REDIRECTION) {
6287
+ spec->bass_redirection_val = *valp;
6288
+ if (spec->cur_out_type == SPEAKER_OUT)
6289
+ ca0132_alt_surround_set_bass_redirection(codec, *valp);
6290
+
6291
+ changed = 0;
53346292 }
53356293
53366294 exit:
....@@ -5491,7 +6449,7 @@
54916449 int ch = get_amp_channels(kcontrol);
54926450 long *valp = ucontrol->value.integer.value;
54936451 hda_nid_t vnid = 0;
5494
- int changed = 1;
6452
+ int changed;
54956453
54966454 switch (nid) {
54976455 case 0x02:
....@@ -5607,7 +6565,7 @@
56076565 /* If using alt_controls, add FX: prefix. But, don't add FX:
56086566 * prefix to OutFX or InFX enable controls.
56096567 */
5610
- if ((spec->use_alt_controls) && (nid <= IN_EFFECT_END_NID))
6568
+ if (ca0132_use_alt_controls(spec) && (nid <= IN_EFFECT_END_NID))
56116569 sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]);
56126570 else
56136571 sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
....@@ -5674,6 +6632,81 @@
56746632 }
56756633
56766634 /*
6635
+ * Add a control for selecting channel count on speaker output. Setting this
6636
+ * allows the DSP to do bass redirection and channel upmixing on surround
6637
+ * configurations.
6638
+ */
6639
+static int ca0132_alt_add_speaker_channel_cfg_enum(struct hda_codec *codec)
6640
+{
6641
+ struct snd_kcontrol_new knew =
6642
+ HDA_CODEC_MUTE_MONO("Surround Channel Config",
6643
+ SPEAKER_CHANNEL_CFG_ENUM, 1, 0, HDA_OUTPUT);
6644
+ knew.info = ca0132_alt_speaker_channel_cfg_get_info;
6645
+ knew.get = ca0132_alt_speaker_channel_cfg_get;
6646
+ knew.put = ca0132_alt_speaker_channel_cfg_put;
6647
+ return snd_hda_ctl_add(codec, SPEAKER_CHANNEL_CFG_ENUM,
6648
+ snd_ctl_new1(&knew, codec));
6649
+}
6650
+
6651
+/*
6652
+ * Full range front stereo and rear surround switches. When these are set to
6653
+ * full range, the lower frequencies from these channels are no longer
6654
+ * redirected to the LFE channel.
6655
+ */
6656
+static int ca0132_alt_add_front_full_range_switch(struct hda_codec *codec)
6657
+{
6658
+ struct snd_kcontrol_new knew =
6659
+ CA0132_CODEC_MUTE_MONO("Full-Range Front Speakers",
6660
+ SPEAKER_FULL_RANGE_FRONT, 1, HDA_OUTPUT);
6661
+
6662
+ return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_FRONT,
6663
+ snd_ctl_new1(&knew, codec));
6664
+}
6665
+
6666
+static int ca0132_alt_add_rear_full_range_switch(struct hda_codec *codec)
6667
+{
6668
+ struct snd_kcontrol_new knew =
6669
+ CA0132_CODEC_MUTE_MONO("Full-Range Rear Speakers",
6670
+ SPEAKER_FULL_RANGE_REAR, 1, HDA_OUTPUT);
6671
+
6672
+ return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_REAR,
6673
+ snd_ctl_new1(&knew, codec));
6674
+}
6675
+
6676
+/*
6677
+ * Bass redirection redirects audio below the crossover frequency to the LFE
6678
+ * channel on speakers that are set as not being full-range. On configurations
6679
+ * without an LFE channel, it does nothing. Bass redirection seems to be the
6680
+ * replacement for X-Bass on configurations with an LFE channel.
6681
+ */
6682
+static int ca0132_alt_add_bass_redirection_crossover(struct hda_codec *codec)
6683
+{
6684
+ const char *namestr = "Bass Redirection Crossover";
6685
+ struct snd_kcontrol_new knew =
6686
+ HDA_CODEC_VOLUME_MONO(namestr, BASS_REDIRECTION_XOVER, 1, 0,
6687
+ HDA_OUTPUT);
6688
+
6689
+ knew.tlv.c = NULL;
6690
+ knew.info = ca0132_alt_xbass_xover_slider_info;
6691
+ knew.get = ca0132_alt_xbass_xover_slider_ctl_get;
6692
+ knew.put = ca0132_alt_xbass_xover_slider_put;
6693
+
6694
+ return snd_hda_ctl_add(codec, BASS_REDIRECTION_XOVER,
6695
+ snd_ctl_new1(&knew, codec));
6696
+}
6697
+
6698
+static int ca0132_alt_add_bass_redirection_switch(struct hda_codec *codec)
6699
+{
6700
+ const char *namestr = "Bass Redirection";
6701
+ struct snd_kcontrol_new knew =
6702
+ CA0132_CODEC_MUTE_MONO(namestr, BASS_REDIRECTION, 1,
6703
+ HDA_OUTPUT);
6704
+
6705
+ return snd_hda_ctl_add(codec, BASS_REDIRECTION,
6706
+ snd_ctl_new1(&knew, codec));
6707
+}
6708
+
6709
+/*
56776710 * Create an Input Source enumerated control for the alternate ca0132 codecs
56786711 * because the front microphone has no auto-detect, and Line-in has to be set
56796712 * somehow.
....@@ -5708,10 +6741,54 @@
57086741 }
57096742
57106743 /*
5711
- * Need to create slave controls for the alternate codecs that have surround
6744
+ * Add headphone gain enumerated control for the AE-5. This switches between
6745
+ * three modes, low, medium, and high. When non-headphone outputs are selected,
6746
+ * it is automatically set to high. This is the same behavior as Windows.
6747
+ */
6748
+static int ae5_add_headphone_gain_enum(struct hda_codec *codec)
6749
+{
6750
+ struct snd_kcontrol_new knew =
6751
+ HDA_CODEC_MUTE_MONO("AE-5: Headphone Gain",
6752
+ AE5_HEADPHONE_GAIN_ENUM, 1, 0, HDA_OUTPUT);
6753
+ knew.info = ae5_headphone_gain_info;
6754
+ knew.get = ae5_headphone_gain_get;
6755
+ knew.put = ae5_headphone_gain_put;
6756
+ return snd_hda_ctl_add(codec, AE5_HEADPHONE_GAIN_ENUM,
6757
+ snd_ctl_new1(&knew, codec));
6758
+}
6759
+
6760
+/*
6761
+ * Add sound filter enumerated control for the AE-5. This adds three different
6762
+ * settings: Slow Roll Off, Minimum Phase, and Fast Roll Off. From what I've
6763
+ * read into it, it changes the DAC's interpolation filter.
6764
+ */
6765
+static int ae5_add_sound_filter_enum(struct hda_codec *codec)
6766
+{
6767
+ struct snd_kcontrol_new knew =
6768
+ HDA_CODEC_MUTE_MONO("AE-5: Sound Filter",
6769
+ AE5_SOUND_FILTER_ENUM, 1, 0, HDA_OUTPUT);
6770
+ knew.info = ae5_sound_filter_info;
6771
+ knew.get = ae5_sound_filter_get;
6772
+ knew.put = ae5_sound_filter_put;
6773
+ return snd_hda_ctl_add(codec, AE5_SOUND_FILTER_ENUM,
6774
+ snd_ctl_new1(&knew, codec));
6775
+}
6776
+
6777
+static int zxr_add_headphone_gain_switch(struct hda_codec *codec)
6778
+{
6779
+ struct snd_kcontrol_new knew =
6780
+ CA0132_CODEC_MUTE_MONO("ZxR: 600 Ohm Gain",
6781
+ ZXR_HEADPHONE_GAIN, 1, HDA_OUTPUT);
6782
+
6783
+ return snd_hda_ctl_add(codec, ZXR_HEADPHONE_GAIN,
6784
+ snd_ctl_new1(&knew, codec));
6785
+}
6786
+
6787
+/*
6788
+ * Need to create follower controls for the alternate codecs that have surround
57126789 * capabilities.
57136790 */
5714
-static const char * const ca0132_alt_slave_pfxs[] = {
6791
+static const char * const ca0132_alt_follower_pfxs[] = {
57156792 "Front", "Surround", "Center", "LFE", NULL,
57166793 };
57176794
....@@ -5839,18 +6916,19 @@
58396916 if (err < 0)
58406917 return err;
58416918 }
5842
- /* Setup vmaster with surround slaves for desktop ca0132 devices */
5843
- if (spec->use_alt_functions) {
6919
+ /* Setup vmaster with surround followers for desktop ca0132 devices */
6920
+ if (ca0132_use_alt_functions(spec)) {
58446921 snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT,
58456922 spec->tlv);
58466923 snd_hda_add_vmaster(codec, "Master Playback Volume",
5847
- spec->tlv, ca0132_alt_slave_pfxs,
6924
+ spec->tlv, ca0132_alt_follower_pfxs,
58486925 "Playback Volume");
58496926 err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
5850
- NULL, ca0132_alt_slave_pfxs,
6927
+ NULL, ca0132_alt_follower_pfxs,
58516928 "Playback Switch",
58526929 true, &spec->vmaster_mute.sw_kctl);
5853
-
6930
+ if (err < 0)
6931
+ return err;
58546932 }
58556933
58566934 /* Add in and out effects controls.
....@@ -5859,7 +6937,7 @@
58596937 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
58606938 for (i = 0; i < num_fx; i++) {
58616939 /* Desktop cards break if Echo Cancellation is used. */
5862
- if (spec->use_pci_mmio) {
6940
+ if (ca0132_use_pci_mmio(spec)) {
58636941 if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID +
58646942 OUT_EFFECTS_COUNT))
58656943 continue;
....@@ -5876,9 +6954,15 @@
58766954 * EQ presets, and Smart Volume presets. Also, change names to add FX
58776955 * prefix, and change PlayEnhancement and CrystalVoice to match.
58786956 */
5879
- if (spec->use_alt_controls) {
5880
- ca0132_alt_add_svm_enum(codec);
5881
- add_ca0132_alt_eq_presets(codec);
6957
+ if (ca0132_use_alt_controls(spec)) {
6958
+ err = ca0132_alt_add_svm_enum(codec);
6959
+ if (err < 0)
6960
+ return err;
6961
+
6962
+ err = add_ca0132_alt_eq_presets(codec);
6963
+ if (err < 0)
6964
+ return err;
6965
+
58826966 err = add_fx_switch(codec, PLAY_ENHANCEMENT,
58836967 "Enable OutFX", 0);
58846968 if (err < 0)
....@@ -5915,18 +6999,67 @@
59156999 if (err < 0)
59167000 return err;
59177001 }
5918
- add_voicefx(codec);
7002
+ err = add_voicefx(codec);
7003
+ if (err < 0)
7004
+ return err;
59197005
59207006 /*
59217007 * If the codec uses alt_functions, you need the enumerated controls
59227008 * to select the new outputs and inputs, plus add the new mic boost
59237009 * setting control.
59247010 */
5925
- if (spec->use_alt_functions) {
5926
- ca0132_alt_add_output_enum(codec);
5927
- ca0132_alt_add_input_enum(codec);
5928
- ca0132_alt_add_mic_boost_enum(codec);
7011
+ if (ca0132_use_alt_functions(spec)) {
7012
+ err = ca0132_alt_add_output_enum(codec);
7013
+ if (err < 0)
7014
+ return err;
7015
+ err = ca0132_alt_add_speaker_channel_cfg_enum(codec);
7016
+ if (err < 0)
7017
+ return err;
7018
+ err = ca0132_alt_add_front_full_range_switch(codec);
7019
+ if (err < 0)
7020
+ return err;
7021
+ err = ca0132_alt_add_rear_full_range_switch(codec);
7022
+ if (err < 0)
7023
+ return err;
7024
+ err = ca0132_alt_add_bass_redirection_crossover(codec);
7025
+ if (err < 0)
7026
+ return err;
7027
+ err = ca0132_alt_add_bass_redirection_switch(codec);
7028
+ if (err < 0)
7029
+ return err;
7030
+ err = ca0132_alt_add_mic_boost_enum(codec);
7031
+ if (err < 0)
7032
+ return err;
7033
+ /*
7034
+ * ZxR only has microphone input, there is no front panel
7035
+ * header on the card, and aux-in is handled by the DBPro board.
7036
+ */
7037
+ if (ca0132_quirk(spec) != QUIRK_ZXR) {
7038
+ err = ca0132_alt_add_input_enum(codec);
7039
+ if (err < 0)
7040
+ return err;
7041
+ }
59297042 }
7043
+
7044
+ switch (ca0132_quirk(spec)) {
7045
+ case QUIRK_AE5:
7046
+ case QUIRK_AE7:
7047
+ err = ae5_add_headphone_gain_enum(codec);
7048
+ if (err < 0)
7049
+ return err;
7050
+ err = ae5_add_sound_filter_enum(codec);
7051
+ if (err < 0)
7052
+ return err;
7053
+ break;
7054
+ case QUIRK_ZXR:
7055
+ err = zxr_add_headphone_gain_switch(codec);
7056
+ if (err < 0)
7057
+ return err;
7058
+ break;
7059
+ default:
7060
+ break;
7061
+ }
7062
+
59307063 #ifdef ENABLE_TUNING_CONTROLS
59317064 add_tuning_ctls(codec);
59327065 #endif
....@@ -5952,8 +7085,29 @@
59527085 return err;
59537086 }
59547087
5955
- if (spec->use_alt_functions)
7088
+ if (ca0132_use_alt_functions(spec))
59567089 ca0132_alt_add_chmap_ctls(codec);
7090
+
7091
+ return 0;
7092
+}
7093
+
7094
+static int dbpro_build_controls(struct hda_codec *codec)
7095
+{
7096
+ struct ca0132_spec *spec = codec->spec;
7097
+ int err = 0;
7098
+
7099
+ if (spec->dig_out) {
7100
+ err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
7101
+ spec->dig_out);
7102
+ if (err < 0)
7103
+ return err;
7104
+ }
7105
+
7106
+ if (spec->dig_in) {
7107
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
7108
+ if (err < 0)
7109
+ return err;
7110
+ }
59577111
59587112 return 0;
59597113 }
....@@ -6009,7 +7163,7 @@
60097163 info = snd_hda_codec_pcm_new(codec, "CA0132 Analog");
60107164 if (!info)
60117165 return -ENOMEM;
6012
- if (spec->use_alt_functions) {
7166
+ if (ca0132_use_alt_functions(spec)) {
60137167 info->own_chmap = true;
60147168 info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap
60157169 = ca0132_alt_chmaps;
....@@ -6023,7 +7177,7 @@
60237177 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
60247178
60257179 /* With the DSP enabled, desktops don't use this ADC. */
6026
- if (!spec->use_alt_functions) {
7180
+ if (!ca0132_use_alt_functions(spec)) {
60277181 info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
60287182 if (!info)
60297183 return -ENOMEM;
....@@ -6039,6 +7193,40 @@
60397193 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
60407194 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
60417195 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[2];
7196
+
7197
+ if (!spec->dig_out && !spec->dig_in)
7198
+ return 0;
7199
+
7200
+ info = snd_hda_codec_pcm_new(codec, "CA0132 Digital");
7201
+ if (!info)
7202
+ return -ENOMEM;
7203
+ info->pcm_type = HDA_PCM_TYPE_SPDIF;
7204
+ if (spec->dig_out) {
7205
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
7206
+ ca0132_pcm_digital_playback;
7207
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
7208
+ }
7209
+ if (spec->dig_in) {
7210
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] =
7211
+ ca0132_pcm_digital_capture;
7212
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
7213
+ }
7214
+
7215
+ return 0;
7216
+}
7217
+
7218
+static int dbpro_build_pcms(struct hda_codec *codec)
7219
+{
7220
+ struct ca0132_spec *spec = codec->spec;
7221
+ struct hda_pcm *info;
7222
+
7223
+ info = snd_hda_codec_pcm_new(codec, "CA0132 Alt Analog");
7224
+ if (!info)
7225
+ return -ENOMEM;
7226
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
7227
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
7228
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
7229
+
60427230
60437231 if (!spec->dig_out && !spec->dig_in)
60447232 return 0;
....@@ -6187,7 +7375,7 @@
61877375 * Bit 6: set to select Data2, clear for Data1
61887376 * Bit 7: set to enable DMic, clear for AMic
61897377 */
6190
- if (spec->quirk == QUIRK_ALIENWARE_M17XR4)
7378
+ if (ca0132_quirk(spec) == QUIRK_ALIENWARE_M17XR4)
61917379 val = 0x33;
61927380 else
61937381 val = 0x23;
....@@ -6241,69 +7429,110 @@
62417429 }
62427430
62437431 /*
6244
- * Recon3D r3d_setup_defaults sub functions.
7432
+ * Default speaker tuning values setup for alternative codecs.
62457433 */
7434
+static const unsigned int sbz_default_delay_values[] = {
7435
+ /* Non-zero values are floating point 0.000198. */
7436
+ 0x394f9e38, 0x394f9e38, 0x00000000, 0x00000000, 0x00000000, 0x00000000
7437
+};
62467438
6247
-static void r3d_dsp_scp_startup(struct hda_codec *codec)
7439
+static const unsigned int zxr_default_delay_values[] = {
7440
+ /* Non-zero values are floating point 0.000220. */
7441
+ 0x00000000, 0x00000000, 0x3966afcd, 0x3966afcd, 0x3966afcd, 0x3966afcd
7442
+};
7443
+
7444
+static const unsigned int ae5_default_delay_values[] = {
7445
+ /* Non-zero values are floating point 0.000100. */
7446
+ 0x00000000, 0x00000000, 0x38d1b717, 0x38d1b717, 0x38d1b717, 0x38d1b717
7447
+};
7448
+
7449
+/*
7450
+ * If we never change these, probably only need them on initialization.
7451
+ */
7452
+static void ca0132_alt_init_speaker_tuning(struct hda_codec *codec)
62487453 {
6249
- unsigned int tmp;
7454
+ struct ca0132_spec *spec = codec->spec;
7455
+ unsigned int i, tmp, start_req, end_req;
7456
+ const unsigned int *values;
62507457
6251
- tmp = 0x00000000;
6252
- dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7458
+ switch (ca0132_quirk(spec)) {
7459
+ case QUIRK_SBZ:
7460
+ values = sbz_default_delay_values;
7461
+ break;
7462
+ case QUIRK_ZXR:
7463
+ values = zxr_default_delay_values;
7464
+ break;
7465
+ case QUIRK_AE5:
7466
+ case QUIRK_AE7:
7467
+ values = ae5_default_delay_values;
7468
+ break;
7469
+ default:
7470
+ values = sbz_default_delay_values;
7471
+ break;
7472
+ }
62537473
6254
- tmp = 0x00000001;
6255
- dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
6256
-
6257
- tmp = 0x00000004;
6258
- dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
6259
-
6260
- tmp = 0x00000005;
6261
- dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
6262
-
6263
- tmp = 0x00000000;
6264
- dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
6265
-
6266
-}
6267
-
6268
-static void r3d_dsp_initial_mic_setup(struct hda_codec *codec)
6269
-{
6270
- unsigned int tmp;
6271
-
6272
- /* Mic 1 Setup */
6273
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
6274
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
6275
- /* This ConnPointID is unique to Recon3Di. Haven't seen it elsewhere */
6276
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
6277
- tmp = FLOAT_ONE;
6278
- dspio_set_uint_param(codec, 0x80, 0x00, tmp);
6279
-
6280
- /* Mic 2 Setup, even though it isn't connected on SBZ */
6281
- chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000);
6282
- chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000);
6283
- chipio_set_conn_rate(codec, 0x0F, SR_96_000);
62847474 tmp = FLOAT_ZERO;
6285
- dspio_set_uint_param(codec, 0x80, 0x01, tmp);
7475
+ dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_ENABLE_CENTER_EQ, tmp);
7476
+
7477
+ start_req = SPEAKER_TUNING_FRONT_LEFT_VOL_LEVEL;
7478
+ end_req = SPEAKER_TUNING_REAR_RIGHT_VOL_LEVEL;
7479
+ for (i = start_req; i < end_req + 1; i++)
7480
+ dspio_set_uint_param(codec, 0x96, i, tmp);
7481
+
7482
+ start_req = SPEAKER_TUNING_FRONT_LEFT_INVERT;
7483
+ end_req = SPEAKER_TUNING_REAR_RIGHT_INVERT;
7484
+ for (i = start_req; i < end_req + 1; i++)
7485
+ dspio_set_uint_param(codec, 0x96, i, tmp);
7486
+
7487
+
7488
+ for (i = 0; i < 6; i++)
7489
+ dspio_set_uint_param(codec, 0x96,
7490
+ SPEAKER_TUNING_FRONT_LEFT_DELAY + i, values[i]);
62867491 }
62877492
62887493 /*
6289
- * Initialize Sound Blaster Z analog microphones.
7494
+ * Creates a dummy stream to bind the output to. This seems to have to be done
7495
+ * after changing the main outputs source and destination streams.
62907496 */
6291
-static void sbz_init_analog_mics(struct hda_codec *codec)
7497
+static void ca0132_alt_create_dummy_stream(struct hda_codec *codec)
62927498 {
7499
+ struct ca0132_spec *spec = codec->spec;
7500
+ unsigned int stream_format;
7501
+
7502
+ stream_format = snd_hdac_calc_stream_format(48000, 2,
7503
+ SNDRV_PCM_FORMAT_S32_LE, 32, 0);
7504
+
7505
+ snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id,
7506
+ 0, stream_format);
7507
+
7508
+ snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
7509
+}
7510
+
7511
+/*
7512
+ * Initialize mic for non-chromebook ca0132 implementations.
7513
+ */
7514
+static void ca0132_alt_init_analog_mics(struct hda_codec *codec)
7515
+{
7516
+ struct ca0132_spec *spec = codec->spec;
62937517 unsigned int tmp;
62947518
62957519 /* Mic 1 Setup */
62967520 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
62977521 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
6298
- tmp = FLOAT_THREE;
7522
+ if (ca0132_quirk(spec) == QUIRK_R3DI) {
7523
+ chipio_set_conn_rate(codec, 0x0F, SR_96_000);
7524
+ tmp = FLOAT_ONE;
7525
+ } else
7526
+ tmp = FLOAT_THREE;
62997527 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
63007528
6301
- /* Mic 2 Setup, even though it isn't connected on SBZ */
7529
+ /* Mic 2 setup (not present on desktop cards) */
63027530 chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000);
63037531 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000);
7532
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
7533
+ chipio_set_conn_rate(codec, 0x0F, SR_96_000);
63047534 tmp = FLOAT_ZERO;
63057535 dspio_set_uint_param(codec, 0x80, 0x01, tmp);
6306
-
63077536 }
63087537
63097538 /*
....@@ -6336,7 +7565,6 @@
63367565 codec_dbg(codec, "Connect Streams exited, mutex released.\n");
63377566
63387567 mutex_unlock(&spec->chipio_mutex);
6339
-
63407568 }
63417569
63427570 /*
....@@ -6363,19 +7591,29 @@
63637591 chipio_set_stream_channels(codec, 0x0C, 6);
63647592 chipio_set_stream_control(codec, 0x0C, 1);
63657593 /* No clue what these control */
6366
- chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0);
6367
- chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1);
6368
- chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2);
6369
- chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3);
6370
- chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4);
6371
- chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5);
6372
- chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6);
6373
- chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7);
6374
- chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8);
6375
- chipio_write_no_mutex(codec, 0x190054, 0x0001edc9);
6376
- chipio_write_no_mutex(codec, 0x190058, 0x0001eaca);
6377
- chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb);
6378
-
7594
+ if (ca0132_quirk(spec) == QUIRK_SBZ) {
7595
+ chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0);
7596
+ chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1);
7597
+ chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2);
7598
+ chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3);
7599
+ chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4);
7600
+ chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5);
7601
+ chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6);
7602
+ chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7);
7603
+ chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8);
7604
+ chipio_write_no_mutex(codec, 0x190054, 0x0001edc9);
7605
+ chipio_write_no_mutex(codec, 0x190058, 0x0001eaca);
7606
+ chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb);
7607
+ } else if (ca0132_quirk(spec) == QUIRK_ZXR) {
7608
+ chipio_write_no_mutex(codec, 0x190038, 0x000140c2);
7609
+ chipio_write_no_mutex(codec, 0x19003c, 0x000141c3);
7610
+ chipio_write_no_mutex(codec, 0x190040, 0x000150c4);
7611
+ chipio_write_no_mutex(codec, 0x190044, 0x000151c5);
7612
+ chipio_write_no_mutex(codec, 0x190050, 0x000142c8);
7613
+ chipio_write_no_mutex(codec, 0x190054, 0x000143c9);
7614
+ chipio_write_no_mutex(codec, 0x190058, 0x000152ca);
7615
+ chipio_write_no_mutex(codec, 0x19005c, 0x000153cb);
7616
+ }
63797617 chipio_write_no_mutex(codec, 0x19042c, 0x00000001);
63807618
63817619 codec_dbg(codec, "Startup Data exited, mutex released.\n");
....@@ -6383,35 +7621,59 @@
63837621 }
63847622
63857623 /*
6386
- * Sound Blaster Z uses these after DSP is loaded. Weird SCP commands
6387
- * without a 0x20 source like normal.
7624
+ * Custom DSP SCP commands where the src value is 0x00 instead of 0x20. This is
7625
+ * done after the DSP is loaded.
63887626 */
6389
-static void sbz_dsp_scp_startup(struct hda_codec *codec)
7627
+static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec)
63907628 {
6391
- unsigned int tmp;
7629
+ struct ca0132_spec *spec = codec->spec;
7630
+ unsigned int tmp, i;
63927631
6393
- tmp = 0x00000003;
6394
- dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
6395
-
6396
- tmp = 0x00000000;
6397
- dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
6398
-
6399
- tmp = 0x00000001;
6400
- dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
6401
-
6402
- tmp = 0x00000004;
6403
- dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
6404
-
6405
- tmp = 0x00000005;
6406
- dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
6407
-
6408
- tmp = 0x00000000;
6409
- dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
6410
-
7632
+ /*
7633
+ * Gotta run these twice, or else mic works inconsistently. Not clear
7634
+ * why this is, but multiple tests have confirmed it.
7635
+ */
7636
+ for (i = 0; i < 2; i++) {
7637
+ switch (ca0132_quirk(spec)) {
7638
+ case QUIRK_SBZ:
7639
+ case QUIRK_AE5:
7640
+ case QUIRK_AE7:
7641
+ tmp = 0x00000003;
7642
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7643
+ tmp = 0x00000000;
7644
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7645
+ tmp = 0x00000001;
7646
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
7647
+ tmp = 0x00000004;
7648
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7649
+ tmp = 0x00000005;
7650
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7651
+ tmp = 0x00000000;
7652
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7653
+ break;
7654
+ case QUIRK_R3D:
7655
+ case QUIRK_R3DI:
7656
+ tmp = 0x00000000;
7657
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7658
+ tmp = 0x00000001;
7659
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
7660
+ tmp = 0x00000004;
7661
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7662
+ tmp = 0x00000005;
7663
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7664
+ tmp = 0x00000000;
7665
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7666
+ break;
7667
+ default:
7668
+ break;
7669
+ }
7670
+ msleep(100);
7671
+ }
64117672 }
64127673
6413
-static void sbz_dsp_initial_mic_setup(struct hda_codec *codec)
7674
+static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec)
64147675 {
7676
+ struct ca0132_spec *spec = codec->spec;
64157677 unsigned int tmp;
64167678
64177679 chipio_set_stream_control(codec, 0x03, 0);
....@@ -6426,8 +7688,369 @@
64267688 chipio_set_stream_control(codec, 0x03, 1);
64277689 chipio_set_stream_control(codec, 0x04, 1);
64287690
6429
- chipio_write(codec, 0x18b098, 0x0000000c);
6430
- chipio_write(codec, 0x18b09C, 0x0000000c);
7691
+ switch (ca0132_quirk(spec)) {
7692
+ case QUIRK_SBZ:
7693
+ chipio_write(codec, 0x18b098, 0x0000000c);
7694
+ chipio_write(codec, 0x18b09C, 0x0000000c);
7695
+ break;
7696
+ case QUIRK_AE5:
7697
+ chipio_write(codec, 0x18b098, 0x0000000c);
7698
+ chipio_write(codec, 0x18b09c, 0x0000004c);
7699
+ break;
7700
+ default:
7701
+ break;
7702
+ }
7703
+}
7704
+
7705
+static void ae5_post_dsp_register_set(struct hda_codec *codec)
7706
+{
7707
+ struct ca0132_spec *spec = codec->spec;
7708
+
7709
+ chipio_8051_write_direct(codec, 0x93, 0x10);
7710
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7711
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
7712
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7713
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
7714
+
7715
+ writeb(0xff, spec->mem_base + 0x304);
7716
+ writeb(0xff, spec->mem_base + 0x304);
7717
+ writeb(0xff, spec->mem_base + 0x304);
7718
+ writeb(0xff, spec->mem_base + 0x304);
7719
+ writeb(0x00, spec->mem_base + 0x100);
7720
+ writeb(0xff, spec->mem_base + 0x304);
7721
+ writeb(0x00, spec->mem_base + 0x100);
7722
+ writeb(0xff, spec->mem_base + 0x304);
7723
+ writeb(0x00, spec->mem_base + 0x100);
7724
+ writeb(0xff, spec->mem_base + 0x304);
7725
+ writeb(0x00, spec->mem_base + 0x100);
7726
+ writeb(0xff, spec->mem_base + 0x304);
7727
+
7728
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x3f);
7729
+ ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
7730
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7731
+}
7732
+
7733
+static void ae5_post_dsp_param_setup(struct hda_codec *codec)
7734
+{
7735
+ /*
7736
+ * Param3 in the 8051's memory is represented by the ascii string 'mch'
7737
+ * which seems to be 'multichannel'. This is also mentioned in the
7738
+ * AE-5's registry values in Windows.
7739
+ */
7740
+ chipio_set_control_param(codec, 3, 0);
7741
+ /*
7742
+ * I believe ASI is 'audio serial interface' and that it's used to
7743
+ * change colors on the external LED strip connected to the AE-5.
7744
+ */
7745
+ chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1);
7746
+
7747
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83);
7748
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
7749
+
7750
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7751
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92);
7752
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7753
+ VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa);
7754
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7755
+ VENDOR_CHIPIO_8051_DATA_WRITE, 0x22);
7756
+}
7757
+
7758
+static void ae5_post_dsp_pll_setup(struct hda_codec *codec)
7759
+{
7760
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7761
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41);
7762
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7763
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8);
7764
+
7765
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7766
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x45);
7767
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7768
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcc);
7769
+
7770
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7771
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x40);
7772
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7773
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcb);
7774
+
7775
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7776
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7777
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7778
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7779
+
7780
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7781
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x51);
7782
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7783
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0x8d);
7784
+}
7785
+
7786
+static void ae5_post_dsp_stream_setup(struct hda_codec *codec)
7787
+{
7788
+ struct ca0132_spec *spec = codec->spec;
7789
+
7790
+ mutex_lock(&spec->chipio_mutex);
7791
+
7792
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81);
7793
+
7794
+ chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000);
7795
+
7796
+ chipio_set_stream_channels(codec, 0x0C, 6);
7797
+ chipio_set_stream_control(codec, 0x0C, 1);
7798
+
7799
+ chipio_set_stream_source_dest(codec, 0x5, 0x43, 0x0);
7800
+
7801
+ chipio_set_stream_source_dest(codec, 0x18, 0x9, 0xd0);
7802
+ chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
7803
+ chipio_set_stream_channels(codec, 0x18, 6);
7804
+ chipio_set_stream_control(codec, 0x18, 1);
7805
+
7806
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4);
7807
+
7808
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7809
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7810
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7811
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7812
+
7813
+ ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80);
7814
+
7815
+ mutex_unlock(&spec->chipio_mutex);
7816
+}
7817
+
7818
+static void ae5_post_dsp_startup_data(struct hda_codec *codec)
7819
+{
7820
+ struct ca0132_spec *spec = codec->spec;
7821
+
7822
+ mutex_lock(&spec->chipio_mutex);
7823
+
7824
+ chipio_write_no_mutex(codec, 0x189000, 0x0001f101);
7825
+ chipio_write_no_mutex(codec, 0x189004, 0x0001f101);
7826
+ chipio_write_no_mutex(codec, 0x189024, 0x00014004);
7827
+ chipio_write_no_mutex(codec, 0x189028, 0x0002000f);
7828
+
7829
+ ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
7830
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
7831
+ ca0113_mmio_command_set(codec, 0x48, 0x0b, 0x12);
7832
+ ca0113_mmio_command_set(codec, 0x48, 0x04, 0x00);
7833
+ ca0113_mmio_command_set(codec, 0x48, 0x06, 0x48);
7834
+ ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
7835
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7836
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7837
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7838
+ ca0113_mmio_gpio_set(codec, 0, true);
7839
+ ca0113_mmio_gpio_set(codec, 1, true);
7840
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x80);
7841
+
7842
+ chipio_write_no_mutex(codec, 0x18b03c, 0x00000012);
7843
+
7844
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7845
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7846
+
7847
+ mutex_unlock(&spec->chipio_mutex);
7848
+}
7849
+
7850
+static const unsigned int ae7_port_set_data[] = {
7851
+ 0x0001e0c0, 0x0001e1c1, 0x0001e4c2, 0x0001e5c3, 0x0001e2c4, 0x0001e3c5,
7852
+ 0x0001e8c6, 0x0001e9c7, 0x0001ecc8, 0x0001edc9, 0x0001eaca, 0x0001ebcb
7853
+};
7854
+
7855
+static void ae7_post_dsp_setup_ports(struct hda_codec *codec)
7856
+{
7857
+ struct ca0132_spec *spec = codec->spec;
7858
+ unsigned int i, count, addr;
7859
+
7860
+ mutex_lock(&spec->chipio_mutex);
7861
+
7862
+ chipio_set_stream_channels(codec, 0x0c, 6);
7863
+ chipio_set_stream_control(codec, 0x0c, 1);
7864
+
7865
+ count = ARRAY_SIZE(ae7_port_set_data);
7866
+ addr = 0x190030;
7867
+ for (i = 0; i < count; i++) {
7868
+ chipio_write_no_mutex(codec, addr, ae7_port_set_data[i]);
7869
+
7870
+ /* Addresses are incremented by 4-bytes. */
7871
+ addr += 0x04;
7872
+ }
7873
+
7874
+ /*
7875
+ * Port setting always ends with a write of 0x1 to address 0x19042c.
7876
+ */
7877
+ chipio_write_no_mutex(codec, 0x19042c, 0x00000001);
7878
+
7879
+ ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
7880
+ ca0113_mmio_command_set(codec, 0x48, 0x0d, 0x40);
7881
+ ca0113_mmio_command_set(codec, 0x48, 0x17, 0x00);
7882
+ ca0113_mmio_command_set(codec, 0x48, 0x19, 0x00);
7883
+ ca0113_mmio_command_set(codec, 0x48, 0x11, 0xff);
7884
+ ca0113_mmio_command_set(codec, 0x48, 0x12, 0xff);
7885
+ ca0113_mmio_command_set(codec, 0x48, 0x13, 0xff);
7886
+ ca0113_mmio_command_set(codec, 0x48, 0x14, 0x7f);
7887
+
7888
+ mutex_unlock(&spec->chipio_mutex);
7889
+}
7890
+
7891
+static void ae7_post_dsp_asi_stream_setup(struct hda_codec *codec)
7892
+{
7893
+ struct ca0132_spec *spec = codec->spec;
7894
+
7895
+ mutex_lock(&spec->chipio_mutex);
7896
+
7897
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81);
7898
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
7899
+
7900
+ chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000);
7901
+ chipio_set_stream_channels(codec, 0x0c, 6);
7902
+ chipio_set_stream_control(codec, 0x0c, 1);
7903
+
7904
+ chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00);
7905
+ chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0);
7906
+
7907
+ chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
7908
+ chipio_set_stream_channels(codec, 0x18, 6);
7909
+ chipio_set_stream_control(codec, 0x18, 1);
7910
+
7911
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4);
7912
+
7913
+ mutex_unlock(&spec->chipio_mutex);
7914
+}
7915
+
7916
+static void ae7_post_dsp_pll_setup(struct hda_codec *codec)
7917
+{
7918
+ static const unsigned int addr[] = {
7919
+ 0x41, 0x45, 0x40, 0x43, 0x51
7920
+ };
7921
+ static const unsigned int data[] = {
7922
+ 0xc8, 0xcc, 0xcb, 0xc7, 0x8d
7923
+ };
7924
+ unsigned int i;
7925
+
7926
+ for (i = 0; i < ARRAY_SIZE(addr); i++) {
7927
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7928
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, addr[i]);
7929
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7930
+ VENDOR_CHIPIO_PLL_PMU_WRITE, data[i]);
7931
+ }
7932
+}
7933
+
7934
+static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec)
7935
+{
7936
+ struct ca0132_spec *spec = codec->spec;
7937
+ static const unsigned int target[] = {
7938
+ 0x0b, 0x04, 0x06, 0x0a, 0x0c, 0x11, 0x12, 0x13, 0x14
7939
+ };
7940
+ static const unsigned int data[] = {
7941
+ 0x12, 0x00, 0x48, 0x05, 0x5f, 0xff, 0xff, 0xff, 0x7f
7942
+ };
7943
+ unsigned int i;
7944
+
7945
+ mutex_lock(&spec->chipio_mutex);
7946
+
7947
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7948
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7949
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7950
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7951
+
7952
+ chipio_write_no_mutex(codec, 0x189000, 0x0001f101);
7953
+ chipio_write_no_mutex(codec, 0x189004, 0x0001f101);
7954
+ chipio_write_no_mutex(codec, 0x189024, 0x00014004);
7955
+ chipio_write_no_mutex(codec, 0x189028, 0x0002000f);
7956
+
7957
+ ae7_post_dsp_pll_setup(codec);
7958
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
7959
+
7960
+ for (i = 0; i < ARRAY_SIZE(target); i++)
7961
+ ca0113_mmio_command_set(codec, 0x48, target[i], data[i]);
7962
+
7963
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
7964
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7965
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7966
+
7967
+ chipio_set_stream_source_dest(codec, 0x21, 0x64, 0x56);
7968
+ chipio_set_stream_channels(codec, 0x21, 2);
7969
+ chipio_set_conn_rate_no_mutex(codec, 0x56, SR_8_000);
7970
+
7971
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_NODE_ID, 0x09);
7972
+ /*
7973
+ * In the 8051's memory, this param is referred to as 'n2sid', which I
7974
+ * believe is 'node to streamID'. It seems to be a way to assign a
7975
+ * stream to a given HDA node.
7976
+ */
7977
+ chipio_set_control_param_no_mutex(codec, 0x20, 0x21);
7978
+
7979
+ chipio_write_no_mutex(codec, 0x18b038, 0x00000088);
7980
+
7981
+ /*
7982
+ * Now, at this point on Windows, an actual stream is setup and
7983
+ * seemingly sends data to the HDA node 0x09, which is the digital
7984
+ * audio input node. This is left out here, because obviously I don't
7985
+ * know what data is being sent. Interestingly, the AE-5 seems to go
7986
+ * through the motions of getting here and never actually takes this
7987
+ * step, but the AE-7 does.
7988
+ */
7989
+
7990
+ ca0113_mmio_gpio_set(codec, 0, 1);
7991
+ ca0113_mmio_gpio_set(codec, 1, 1);
7992
+
7993
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
7994
+ chipio_write_no_mutex(codec, 0x18b03c, 0x00000000);
7995
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7996
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7997
+
7998
+ chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00);
7999
+ chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0);
8000
+
8001
+ chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
8002
+ chipio_set_stream_channels(codec, 0x18, 6);
8003
+
8004
+ /*
8005
+ * Runs again, this has been repeated a few times, but I'm just
8006
+ * following what the Windows driver does.
8007
+ */
8008
+ ae7_post_dsp_pll_setup(codec);
8009
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
8010
+
8011
+ mutex_unlock(&spec->chipio_mutex);
8012
+}
8013
+
8014
+/*
8015
+ * The Windows driver has commands that seem to setup ASI, which I believe to
8016
+ * be some sort of audio serial interface. My current speculation is that it's
8017
+ * related to communicating with the new DAC.
8018
+ */
8019
+static void ae7_post_dsp_asi_setup(struct hda_codec *codec)
8020
+{
8021
+ chipio_8051_write_direct(codec, 0x93, 0x10);
8022
+
8023
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8024
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
8025
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8026
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
8027
+
8028
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
8029
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
8030
+
8031
+ chipio_set_control_param(codec, 3, 3);
8032
+ chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1);
8033
+
8034
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83);
8035
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
8036
+ snd_hda_codec_write(codec, 0x17, 0, 0x794, 0x00);
8037
+
8038
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8039
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92);
8040
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8041
+ VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa);
8042
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8043
+ VENDOR_CHIPIO_8051_DATA_WRITE, 0x22);
8044
+
8045
+ ae7_post_dsp_pll_setup(codec);
8046
+ ae7_post_dsp_asi_stream_setup(codec);
8047
+
8048
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8049
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
8050
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8051
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
8052
+
8053
+ ae7_post_dsp_asi_setup_ports(codec);
64318054 }
64328055
64338056 /*
....@@ -6488,9 +8111,8 @@
64888111 if (spec->dsp_state != DSP_DOWNLOADED)
64898112 return;
64908113
6491
- r3d_dsp_scp_startup(codec);
6492
-
6493
- r3d_dsp_initial_mic_setup(codec);
8114
+ ca0132_alt_dsp_scp_startup(codec);
8115
+ ca0132_alt_init_analog_mics(codec);
64948116
64958117 /*remove DSP headroom*/
64968118 tmp = FLOAT_ZERO;
....@@ -6504,8 +8126,14 @@
65048126 /* Set speaker source? */
65058127 dspio_set_uint_param(codec, 0x32, 0x00, tmp);
65068128
6507
- if (spec->quirk == QUIRK_R3DI)
8129
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
65088130 r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED);
8131
+
8132
+ /* Disable mute on Center/LFE. */
8133
+ if (ca0132_quirk(spec) == QUIRK_R3D) {
8134
+ ca0113_mmio_gpio_set(codec, 2, false);
8135
+ ca0113_mmio_gpio_set(codec, 4, true);
8136
+ }
65098137
65108138 /* Setup effect defaults */
65118139 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
....@@ -6526,19 +8154,16 @@
65268154 static void sbz_setup_defaults(struct hda_codec *codec)
65278155 {
65288156 struct ca0132_spec *spec = codec->spec;
6529
- unsigned int tmp, stream_format;
8157
+ unsigned int tmp;
65308158 int num_fx;
65318159 int idx, i;
65328160
65338161 if (spec->dsp_state != DSP_DOWNLOADED)
65348162 return;
65358163
6536
- sbz_dsp_scp_startup(codec);
6537
-
6538
- sbz_init_analog_mics(codec);
6539
-
8164
+ ca0132_alt_dsp_scp_startup(codec);
8165
+ ca0132_alt_init_analog_mics(codec);
65408166 sbz_connect_streams(codec);
6541
-
65428167 sbz_chipio_startup_data(codec);
65438168
65448169 chipio_set_stream_control(codec, 0x03, 1);
....@@ -6564,8 +8189,7 @@
65648189 /* Set speaker source? */
65658190 dspio_set_uint_param(codec, 0x32, 0x00, tmp);
65668191
6567
- sbz_dsp_initial_mic_setup(codec);
6568
-
8192
+ ca0132_alt_dsp_initial_mic_setup(codec);
65698193
65708194 /* out, in effects + voicefx */
65718195 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
....@@ -6578,23 +8202,163 @@
65788202 }
65798203 }
65808204
8205
+ ca0132_alt_init_speaker_tuning(codec);
8206
+
8207
+ ca0132_alt_create_dummy_stream(codec);
8208
+}
8209
+
8210
+/*
8211
+ * Setup default parameters for the Sound BlasterX AE-5 DSP.
8212
+ */
8213
+static void ae5_setup_defaults(struct hda_codec *codec)
8214
+{
8215
+ struct ca0132_spec *spec = codec->spec;
8216
+ unsigned int tmp;
8217
+ int num_fx;
8218
+ int idx, i;
8219
+
8220
+ if (spec->dsp_state != DSP_DOWNLOADED)
8221
+ return;
8222
+
8223
+ ca0132_alt_dsp_scp_startup(codec);
8224
+ ca0132_alt_init_analog_mics(codec);
8225
+ chipio_set_stream_control(codec, 0x03, 1);
8226
+ chipio_set_stream_control(codec, 0x04, 1);
8227
+
8228
+ /* New, unknown SCP req's */
8229
+ tmp = FLOAT_ZERO;
8230
+ dspio_set_uint_param(codec, 0x96, 0x29, tmp);
8231
+ dspio_set_uint_param(codec, 0x96, 0x2a, tmp);
8232
+ dspio_set_uint_param(codec, 0x80, 0x0d, tmp);
8233
+ dspio_set_uint_param(codec, 0x80, 0x0e, tmp);
8234
+
8235
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
8236
+ ca0113_mmio_gpio_set(codec, 0, false);
8237
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
8238
+
8239
+ /* Internal loopback off */
8240
+ tmp = FLOAT_ONE;
8241
+ dspio_set_uint_param(codec, 0x37, 0x08, tmp);
8242
+ dspio_set_uint_param(codec, 0x37, 0x10, tmp);
8243
+
8244
+ /*remove DSP headroom*/
8245
+ tmp = FLOAT_ZERO;
8246
+ dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
8247
+
8248
+ /* set WUH source */
8249
+ tmp = FLOAT_TWO;
8250
+ dspio_set_uint_param(codec, 0x31, 0x00, tmp);
8251
+ chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
8252
+
8253
+ /* Set speaker source? */
8254
+ dspio_set_uint_param(codec, 0x32, 0x00, tmp);
8255
+
8256
+ ca0132_alt_dsp_initial_mic_setup(codec);
8257
+ ae5_post_dsp_register_set(codec);
8258
+ ae5_post_dsp_param_setup(codec);
8259
+ ae5_post_dsp_pll_setup(codec);
8260
+ ae5_post_dsp_stream_setup(codec);
8261
+ ae5_post_dsp_startup_data(codec);
8262
+
8263
+ /* out, in effects + voicefx */
8264
+ num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
8265
+ for (idx = 0; idx < num_fx; idx++) {
8266
+ for (i = 0; i <= ca0132_effects[idx].params; i++) {
8267
+ dspio_set_uint_param(codec,
8268
+ ca0132_effects[idx].mid,
8269
+ ca0132_effects[idx].reqs[i],
8270
+ ca0132_effects[idx].def_vals[i]);
8271
+ }
8272
+ }
8273
+
8274
+ ca0132_alt_init_speaker_tuning(codec);
8275
+
8276
+ ca0132_alt_create_dummy_stream(codec);
8277
+}
8278
+
8279
+/*
8280
+ * Setup default parameters for the Sound Blaster AE-7 DSP.
8281
+ */
8282
+static void ae7_setup_defaults(struct hda_codec *codec)
8283
+{
8284
+ struct ca0132_spec *spec = codec->spec;
8285
+ unsigned int tmp;
8286
+ int num_fx;
8287
+ int idx, i;
8288
+
8289
+ if (spec->dsp_state != DSP_DOWNLOADED)
8290
+ return;
8291
+
8292
+ ca0132_alt_dsp_scp_startup(codec);
8293
+ ca0132_alt_init_analog_mics(codec);
8294
+ ae7_post_dsp_setup_ports(codec);
8295
+
8296
+ tmp = FLOAT_ZERO;
8297
+ dspio_set_uint_param(codec, 0x96,
8298
+ SPEAKER_TUNING_FRONT_LEFT_INVERT, tmp);
8299
+ dspio_set_uint_param(codec, 0x96,
8300
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT, tmp);
8301
+
8302
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
8303
+
8304
+ /* New, unknown SCP req's */
8305
+ dspio_set_uint_param(codec, 0x80, 0x0d, tmp);
8306
+ dspio_set_uint_param(codec, 0x80, 0x0e, tmp);
8307
+
8308
+ ca0113_mmio_gpio_set(codec, 0, false);
8309
+
8310
+ /* Internal loopback off */
8311
+ tmp = FLOAT_ONE;
8312
+ dspio_set_uint_param(codec, 0x37, 0x08, tmp);
8313
+ dspio_set_uint_param(codec, 0x37, 0x10, tmp);
8314
+
8315
+ /*remove DSP headroom*/
8316
+ tmp = FLOAT_ZERO;
8317
+ dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
8318
+
8319
+ /* set WUH source */
8320
+ tmp = FLOAT_TWO;
8321
+ dspio_set_uint_param(codec, 0x31, 0x00, tmp);
8322
+ chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
8323
+
8324
+ /* Set speaker source? */
8325
+ dspio_set_uint_param(codec, 0x32, 0x00, tmp);
8326
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
8327
+
65818328 /*
6582
- * Have to make a stream to bind the sound output to, otherwise
6583
- * you'll get dead audio. Before I did this, it would bind to an
6584
- * audio input, and would never work
8329
+ * This is the second time we've called this, but this is seemingly
8330
+ * what Windows does.
65858331 */
6586
- stream_format = snd_hdac_calc_stream_format(48000, 2,
6587
- SNDRV_PCM_FORMAT_S32_LE, 32, 0);
8332
+ ca0132_alt_init_analog_mics(codec);
65888333
6589
- snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id,
6590
- 0, stream_format);
8334
+ ae7_post_dsp_asi_setup(codec);
65918335
6592
- snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
8336
+ /*
8337
+ * Not sure why, but these are both set to 1. They're only set to 0
8338
+ * upon shutdown.
8339
+ */
8340
+ ca0113_mmio_gpio_set(codec, 0, true);
8341
+ ca0113_mmio_gpio_set(codec, 1, true);
65938342
6594
- snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id,
6595
- 0, stream_format);
8343
+ /* Volume control related. */
8344
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x04);
8345
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x04);
8346
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x80);
65968347
6597
- snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
8348
+ /* out, in effects + voicefx */
8349
+ num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
8350
+ for (idx = 0; idx < num_fx; idx++) {
8351
+ for (i = 0; i <= ca0132_effects[idx].params; i++) {
8352
+ dspio_set_uint_param(codec,
8353
+ ca0132_effects[idx].mid,
8354
+ ca0132_effects[idx].reqs[i],
8355
+ ca0132_effects[idx].def_vals[i]);
8356
+ }
8357
+ }
8358
+
8359
+ ca0132_alt_init_speaker_tuning(codec);
8360
+
8361
+ ca0132_alt_create_dummy_stream(codec);
65988362 }
65998363
66008364 /*
....@@ -6604,7 +8368,7 @@
66048368 {
66058369 struct ca0132_spec *spec = codec->spec;
66068370
6607
- if (spec->use_alt_functions) {
8371
+ if (ca0132_use_alt_functions(spec)) {
66088372 chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1);
66098373 chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1);
66108374 chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1);
....@@ -6637,7 +8401,7 @@
66378401 {
66388402 struct ca0132_spec *spec = codec->spec;
66398403
6640
- if (spec->use_alt_functions) {
8404
+ if (ca0132_use_alt_functions(spec)) {
66418405 chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
66428406 chipio_set_conn_rate(codec, 0x0B, SR_48_000);
66438407 chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0);
....@@ -6668,42 +8432,37 @@
66688432 bool dsp_loaded = false;
66698433 struct ca0132_spec *spec = codec->spec;
66708434 const struct dsp_image_seg *dsp_os_image;
6671
- const struct firmware *fw_entry;
8435
+ const struct firmware *fw_entry = NULL;
66728436 /*
66738437 * Alternate firmwares for different variants. The Recon3Di apparently
66748438 * can use the default firmware, but I'll leave the option in case
66758439 * it needs it again.
66768440 */
6677
- switch (spec->quirk) {
8441
+ switch (ca0132_quirk(spec)) {
66788442 case QUIRK_SBZ:
6679
- if (request_firmware(&fw_entry, SBZ_EFX_FILE,
6680
- codec->card->dev) != 0) {
6681
- codec_dbg(codec, "SBZ alt firmware not detected. ");
6682
- spec->alt_firmware_present = false;
6683
- } else {
6684
- codec_dbg(codec, "Sound Blaster Z firmware selected.");
6685
- spec->alt_firmware_present = true;
6686
- }
8443
+ case QUIRK_R3D:
8444
+ case QUIRK_AE5:
8445
+ if (request_firmware(&fw_entry, DESKTOP_EFX_FILE,
8446
+ codec->card->dev) != 0)
8447
+ codec_dbg(codec, "Desktop firmware not found.");
8448
+ else
8449
+ codec_dbg(codec, "Desktop firmware selected.");
66878450 break;
66888451 case QUIRK_R3DI:
66898452 if (request_firmware(&fw_entry, R3DI_EFX_FILE,
6690
- codec->card->dev) != 0) {
8453
+ codec->card->dev) != 0)
66918454 codec_dbg(codec, "Recon3Di alt firmware not detected.");
6692
- spec->alt_firmware_present = false;
6693
- } else {
8455
+ else
66948456 codec_dbg(codec, "Recon3Di firmware selected.");
6695
- spec->alt_firmware_present = true;
6696
- }
66978457 break;
66988458 default:
6699
- spec->alt_firmware_present = false;
67008459 break;
67018460 }
67028461 /*
67038462 * Use default ctefx.bin if no alt firmware is detected, or if none
67048463 * exists for your particular codec.
67058464 */
6706
- if (!spec->alt_firmware_present) {
8465
+ if (!fw_entry) {
67078466 codec_dbg(codec, "Default firmware selected.");
67088467 if (request_firmware(&fw_entry, EFX_FILE,
67098468 codec->card->dev) != 0)
....@@ -6746,7 +8505,7 @@
67468505 }
67478506
67488507 /* For codecs using alt functions, this is already done earlier */
6749
- if (spec->dsp_state == DSP_DOWNLOADED && (!spec->use_alt_functions))
8508
+ if (spec->dsp_state == DSP_DOWNLOADED && !ca0132_use_alt_functions(spec))
67508509 ca0132_set_dsp_msr(codec, true);
67518510 }
67528511
....@@ -6784,7 +8543,7 @@
67848543 {
67858544 struct ca0132_spec *spec = codec->spec;
67868545
6787
- if (spec->use_alt_functions)
8546
+ if (ca0132_use_alt_functions(spec))
67888547 ca0132_alt_select_in(codec);
67898548 else
67908549 ca0132_select_mic(codec);
....@@ -6799,7 +8558,7 @@
67998558 snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP,
68008559 ca0132_process_dsp_response);
68018560 /* Front headphone jack detection */
6802
- if (spec->use_alt_functions)
8561
+ if (ca0132_use_alt_functions(spec))
68038562 snd_hda_jack_detect_enable_callback(codec,
68048563 spec->unsol_tag_front_hp, hp_callback);
68058564 }
....@@ -6809,14 +8568,14 @@
68098568 */
68108569
68118570 /* Sends before DSP download. */
6812
-static struct hda_verb ca0132_base_init_verbs[] = {
8571
+static const struct hda_verb ca0132_base_init_verbs[] = {
68138572 /*enable ct extension*/
68148573 {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1},
68158574 {}
68168575 };
68178576
68188577 /* Send at exit. */
6819
-static struct hda_verb ca0132_base_exit_verbs[] = {
8578
+static const struct hda_verb ca0132_base_exit_verbs[] = {
68208579 /*set afg to D3*/
68218580 {0x01, AC_VERB_SET_POWER_STATE, 0x03},
68228581 /*disable ct extension*/
....@@ -6826,7 +8585,7 @@
68268585
68278586 /* Other verbs tables. Sends after DSP download. */
68288587
6829
-static struct hda_verb ca0132_init_verbs0[] = {
8588
+static const struct hda_verb ca0132_init_verbs0[] = {
68308589 /* chip init verbs */
68318590 {0x15, 0x70D, 0xF0},
68328591 {0x15, 0x70E, 0xFE},
....@@ -6859,7 +8618,7 @@
68598618 };
68608619
68618620 /* Extra init verbs for desktop cards. */
6862
-static struct hda_verb ca0132_init_verbs1[] = {
8621
+static const struct hda_verb ca0132_init_verbs1[] = {
68638622 {0x15, 0x70D, 0x20},
68648623 {0x15, 0x70E, 0x19},
68658624 {0x15, 0x707, 0x00},
....@@ -6889,7 +8648,7 @@
68898648 mutex_init(&spec->chipio_mutex);
68908649
68918650 spec->cur_out_type = SPEAKER_OUT;
6892
- if (!spec->use_alt_functions)
8651
+ if (!ca0132_use_alt_functions(spec))
68938652 spec->cur_mic_type = DIGITAL_MIC;
68948653 else
68958654 spec->cur_mic_type = REAR_MIC;
....@@ -6915,15 +8674,29 @@
69158674 * Sets defaults for the effect slider controls, only for alternative
69168675 * ca0132 codecs. Also sets x-bass crossover frequency to 80hz.
69178676 */
6918
- if (spec->use_alt_controls) {
8677
+ if (ca0132_use_alt_controls(spec)) {
8678
+ /* Set speakers to default to full range. */
8679
+ spec->speaker_range_val[0] = 1;
8680
+ spec->speaker_range_val[1] = 1;
8681
+
69198682 spec->xbass_xover_freq = 8;
69208683 for (i = 0; i < EFFECT_LEVEL_SLIDERS; i++)
69218684 spec->fx_ctl_val[i] = effect_slider_defaults[i];
8685
+
8686
+ spec->bass_redirect_xover_freq = 8;
69228687 }
69238688
69248689 spec->voicefx_val = 0;
69258690 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1;
69268691 spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0;
8692
+
8693
+ /*
8694
+ * The ZxR doesn't have a front panel header, and it's line-in is on
8695
+ * the daughter board. So, there is no input enum control, and we need
8696
+ * to make sure that spec->in_enum_val is set properly.
8697
+ */
8698
+ if (ca0132_quirk(spec) == QUIRK_ZXR)
8699
+ spec->in_enum_val = REAR_MIC;
69278700
69288701 #ifdef ENABLE_TUNING_CONTROLS
69298702 ca0132_init_tuning_defaults(codec);
....@@ -6952,32 +8725,32 @@
69528725 for (i = 0; i < 8; i++)
69538726 writeb(0xb3, spec->mem_base + 0x304);
69548727
6955
- ca0132_mmio_gpio_set(codec, 0, false);
6956
- ca0132_mmio_gpio_set(codec, 1, false);
6957
- ca0132_mmio_gpio_set(codec, 4, true);
6958
- ca0132_mmio_gpio_set(codec, 5, false);
6959
- ca0132_mmio_gpio_set(codec, 7, false);
8728
+ ca0113_mmio_gpio_set(codec, 0, false);
8729
+ ca0113_mmio_gpio_set(codec, 1, false);
8730
+ ca0113_mmio_gpio_set(codec, 4, true);
8731
+ ca0113_mmio_gpio_set(codec, 5, false);
8732
+ ca0113_mmio_gpio_set(codec, 7, false);
69608733 }
69618734
69628735 static void sbz_set_pin_ctl_default(struct hda_codec *codec)
69638736 {
6964
- hda_nid_t pins[5] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
8737
+ static const hda_nid_t pins[] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
69658738 unsigned int i;
69668739
69678740 snd_hda_codec_write(codec, 0x11, 0,
69688741 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40);
69698742
6970
- for (i = 0; i < 5; i++)
8743
+ for (i = 0; i < ARRAY_SIZE(pins); i++)
69718744 snd_hda_codec_write(codec, pins[i], 0,
69728745 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00);
69738746 }
69748747
69758748 static void ca0132_clear_unsolicited(struct hda_codec *codec)
69768749 {
6977
- hda_nid_t pins[7] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
8750
+ static const hda_nid_t pins[] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
69788751 unsigned int i;
69798752
6980
- for (i = 0; i < 7; i++) {
8753
+ for (i = 0; i < ARRAY_SIZE(pins); i++) {
69818754 snd_hda_codec_write(codec, pins[i], 0,
69828755 AC_VERB_SET_UNSOLICITED_ENABLE, 0x00);
69838756 }
....@@ -6997,6 +8770,16 @@
69978770 if (data >= 0)
69988771 snd_hda_codec_write(codec, 0x01, 0,
69998772 AC_VERB_SET_GPIO_DATA, data);
8773
+}
8774
+
8775
+static void zxr_dbpro_power_state_shutdown(struct hda_codec *codec)
8776
+{
8777
+ static const hda_nid_t pins[] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01};
8778
+ unsigned int i;
8779
+
8780
+ for (i = 0; i < ARRAY_SIZE(pins); i++)
8781
+ snd_hda_codec_write(codec, pins[i], 0,
8782
+ AC_VERB_SET_POWER_STATE, 0x03);
70008783 }
70018784
70028785 static void sbz_exit_chip(struct hda_codec *codec)
....@@ -7039,6 +8822,87 @@
70398822 ca0132_clear_unsolicited(codec);
70408823 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
70418824 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b);
8825
+}
8826
+
8827
+static void ae5_exit_chip(struct hda_codec *codec)
8828
+{
8829
+ chipio_set_stream_control(codec, 0x03, 0);
8830
+ chipio_set_stream_control(codec, 0x04, 0);
8831
+
8832
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
8833
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
8834
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
8835
+ ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
8836
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
8837
+ ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x00);
8838
+ ca0113_mmio_gpio_set(codec, 0, false);
8839
+ ca0113_mmio_gpio_set(codec, 1, false);
8840
+
8841
+ snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
8842
+ snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
8843
+
8844
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
8845
+
8846
+ chipio_set_stream_control(codec, 0x18, 0);
8847
+ chipio_set_stream_control(codec, 0x0c, 0);
8848
+
8849
+ snd_hda_codec_write(codec, 0x01, 0, 0x724, 0x83);
8850
+}
8851
+
8852
+static void ae7_exit_chip(struct hda_codec *codec)
8853
+{
8854
+ chipio_set_stream_control(codec, 0x18, 0);
8855
+ chipio_set_stream_source_dest(codec, 0x21, 0xc8, 0xc8);
8856
+ chipio_set_stream_channels(codec, 0x21, 0);
8857
+ chipio_set_control_param(codec, CONTROL_PARAM_NODE_ID, 0x09);
8858
+ chipio_set_control_param(codec, 0x20, 0x01);
8859
+
8860
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
8861
+
8862
+ chipio_set_stream_control(codec, 0x18, 0);
8863
+ chipio_set_stream_control(codec, 0x0c, 0);
8864
+
8865
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
8866
+ snd_hda_codec_write(codec, 0x15, 0, 0x724, 0x83);
8867
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
8868
+ ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
8869
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x00);
8870
+ ca0113_mmio_gpio_set(codec, 0, false);
8871
+ ca0113_mmio_gpio_set(codec, 1, false);
8872
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
8873
+
8874
+ snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
8875
+ snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
8876
+}
8877
+
8878
+static void zxr_exit_chip(struct hda_codec *codec)
8879
+{
8880
+ chipio_set_stream_control(codec, 0x03, 0);
8881
+ chipio_set_stream_control(codec, 0x04, 0);
8882
+ chipio_set_stream_control(codec, 0x14, 0);
8883
+ chipio_set_stream_control(codec, 0x0C, 0);
8884
+
8885
+ chipio_set_conn_rate(codec, 0x41, SR_192_000);
8886
+ chipio_set_conn_rate(codec, 0x91, SR_192_000);
8887
+
8888
+ chipio_write(codec, 0x18a020, 0x00000083);
8889
+
8890
+ snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
8891
+ snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
8892
+
8893
+ ca0132_clear_unsolicited(codec);
8894
+ sbz_set_pin_ctl_default(codec);
8895
+ snd_hda_codec_write(codec, 0x0B, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x00);
8896
+
8897
+ ca0113_mmio_gpio_set(codec, 5, false);
8898
+ ca0113_mmio_gpio_set(codec, 2, false);
8899
+ ca0113_mmio_gpio_set(codec, 3, false);
8900
+ ca0113_mmio_gpio_set(codec, 0, false);
8901
+ ca0113_mmio_gpio_set(codec, 4, true);
8902
+ ca0113_mmio_gpio_set(codec, 0, true);
8903
+ ca0113_mmio_gpio_set(codec, 5, true);
8904
+ ca0113_mmio_gpio_set(codec, 2, false);
8905
+ ca0113_mmio_gpio_set(codec, 3, false);
70428906 }
70438907
70448908 static void ca0132_exit_chip(struct hda_codec *codec)
....@@ -7144,11 +9008,6 @@
71449008 writel(0x00820680, spec->mem_base + 0x01C);
71459009 writel(0x00820680, spec->mem_base + 0x01C);
71469010
7147
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfc);
7148
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfd);
7149
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfe);
7150
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xff);
7151
-
71529011 chipio_write(codec, 0x18b0a4, 0x000000c2);
71539012
71549013 snd_hda_codec_write(codec, 0x11, 0,
....@@ -7157,12 +9016,6 @@
71579016
71589017 static void r3d_pre_dsp_setup(struct hda_codec *codec)
71599018 {
7160
-
7161
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfc);
7162
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfd);
7163
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xfe);
7164
- snd_hda_codec_write(codec, 0x15, 0, 0xd00, 0xff);
7165
-
71669019 chipio_write(codec, 0x18b0a4, 0x000000c2);
71679020
71689021 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
....@@ -7205,27 +9058,220 @@
72059058 * what they do, or if they're necessary. Could possibly
72069059 * be removed. Figure they're better to leave in.
72079060 */
9061
+static const unsigned int ca0113_mmio_init_address_sbz[] = {
9062
+ 0x400, 0x408, 0x40c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c,
9063
+ 0xc0c, 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04
9064
+};
9065
+
9066
+static const unsigned int ca0113_mmio_init_data_sbz[] = {
9067
+ 0x00000030, 0x00000000, 0x00000003, 0x00000003, 0x00000003,
9068
+ 0x00000003, 0x000000c1, 0x000000f1, 0x00000001, 0x000000c7,
9069
+ 0x000000c1, 0x00000080
9070
+};
9071
+
9072
+static const unsigned int ca0113_mmio_init_data_zxr[] = {
9073
+ 0x00000030, 0x00000000, 0x00000000, 0x00000003, 0x00000003,
9074
+ 0x00000003, 0x00000001, 0x000000f1, 0x00000001, 0x000000c7,
9075
+ 0x000000c1, 0x00000080
9076
+};
9077
+
9078
+static const unsigned int ca0113_mmio_init_address_ae5[] = {
9079
+ 0x400, 0x42c, 0x46c, 0x4ac, 0x4ec, 0x43c, 0x47c, 0x4bc, 0x4fc, 0x408,
9080
+ 0x100, 0x410, 0x40c, 0x100, 0x100, 0x830, 0x86c, 0x800, 0x86c, 0x800,
9081
+ 0x804, 0x20c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c, 0xc0c,
9082
+ 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04, 0x01c
9083
+};
9084
+
9085
+static const unsigned int ca0113_mmio_init_data_ae5[] = {
9086
+ 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
9087
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
9088
+ 0x00000600, 0x00000014, 0x00000001, 0x0000060f, 0x0000070f,
9089
+ 0x00000aff, 0x00000000, 0x0000006b, 0x00000001, 0x0000006b,
9090
+ 0x00000057, 0x00800000, 0x00880680, 0x00000080, 0x00000030,
9091
+ 0x00000000, 0x00000000, 0x00000003, 0x00000003, 0x00000003,
9092
+ 0x00000001, 0x000000f1, 0x00000001, 0x000000c7, 0x000000c1,
9093
+ 0x00000080, 0x00880680
9094
+};
9095
+
9096
+static void ca0132_mmio_init_sbz(struct hda_codec *codec)
9097
+{
9098
+ struct ca0132_spec *spec = codec->spec;
9099
+ unsigned int tmp[2], i, count, cur_addr;
9100
+ const unsigned int *addr, *data;
9101
+
9102
+ addr = ca0113_mmio_init_address_sbz;
9103
+ for (i = 0; i < 3; i++)
9104
+ writel(0x00000000, spec->mem_base + addr[i]);
9105
+
9106
+ cur_addr = i;
9107
+ switch (ca0132_quirk(spec)) {
9108
+ case QUIRK_ZXR:
9109
+ tmp[0] = 0x00880480;
9110
+ tmp[1] = 0x00000080;
9111
+ break;
9112
+ case QUIRK_SBZ:
9113
+ tmp[0] = 0x00820680;
9114
+ tmp[1] = 0x00000083;
9115
+ break;
9116
+ case QUIRK_R3D:
9117
+ tmp[0] = 0x00880680;
9118
+ tmp[1] = 0x00000083;
9119
+ break;
9120
+ default:
9121
+ tmp[0] = 0x00000000;
9122
+ tmp[1] = 0x00000000;
9123
+ break;
9124
+ }
9125
+
9126
+ for (i = 0; i < 2; i++)
9127
+ writel(tmp[i], spec->mem_base + addr[cur_addr + i]);
9128
+
9129
+ cur_addr += i;
9130
+
9131
+ switch (ca0132_quirk(spec)) {
9132
+ case QUIRK_ZXR:
9133
+ count = ARRAY_SIZE(ca0113_mmio_init_data_zxr);
9134
+ data = ca0113_mmio_init_data_zxr;
9135
+ break;
9136
+ default:
9137
+ count = ARRAY_SIZE(ca0113_mmio_init_data_sbz);
9138
+ data = ca0113_mmio_init_data_sbz;
9139
+ break;
9140
+ }
9141
+
9142
+ for (i = 0; i < count; i++)
9143
+ writel(data[i], spec->mem_base + addr[cur_addr + i]);
9144
+}
9145
+
9146
+static void ca0132_mmio_init_ae5(struct hda_codec *codec)
9147
+{
9148
+ struct ca0132_spec *spec = codec->spec;
9149
+ const unsigned int *addr, *data;
9150
+ unsigned int i, count;
9151
+
9152
+ addr = ca0113_mmio_init_address_ae5;
9153
+ data = ca0113_mmio_init_data_ae5;
9154
+ count = ARRAY_SIZE(ca0113_mmio_init_data_ae5);
9155
+
9156
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9157
+ writel(0x00000680, spec->mem_base + 0x1c);
9158
+ writel(0x00880680, spec->mem_base + 0x1c);
9159
+ }
9160
+
9161
+ for (i = 0; i < count; i++) {
9162
+ /*
9163
+ * AE-7 shares all writes with the AE-5, except that it writes
9164
+ * a different value to 0x20c.
9165
+ */
9166
+ if (i == 21 && ca0132_quirk(spec) == QUIRK_AE7) {
9167
+ writel(0x00800001, spec->mem_base + addr[i]);
9168
+ continue;
9169
+ }
9170
+
9171
+ writel(data[i], spec->mem_base + addr[i]);
9172
+ }
9173
+
9174
+ if (ca0132_quirk(spec) == QUIRK_AE5)
9175
+ writel(0x00880680, spec->mem_base + 0x1c);
9176
+}
9177
+
72089178 static void ca0132_mmio_init(struct hda_codec *codec)
72099179 {
72109180 struct ca0132_spec *spec = codec->spec;
72119181
7212
- writel(0x00000000, spec->mem_base + 0x400);
7213
- writel(0x00000000, spec->mem_base + 0x408);
7214
- writel(0x00000000, spec->mem_base + 0x40C);
7215
- writel(0x00880680, spec->mem_base + 0x01C);
7216
- writel(0x00000083, spec->mem_base + 0xC0C);
7217
- writel(0x00000030, spec->mem_base + 0xC00);
7218
- writel(0x00000000, spec->mem_base + 0xC04);
7219
- writel(0x00000003, spec->mem_base + 0xC0C);
7220
- writel(0x00000003, spec->mem_base + 0xC0C);
7221
- writel(0x00000003, spec->mem_base + 0xC0C);
7222
- writel(0x00000003, spec->mem_base + 0xC0C);
7223
- writel(0x000000C1, spec->mem_base + 0xC08);
7224
- writel(0x000000F1, spec->mem_base + 0xC08);
7225
- writel(0x00000001, spec->mem_base + 0xC08);
7226
- writel(0x000000C7, spec->mem_base + 0xC08);
7227
- writel(0x000000C1, spec->mem_base + 0xC08);
7228
- writel(0x00000080, spec->mem_base + 0xC04);
9182
+ switch (ca0132_quirk(spec)) {
9183
+ case QUIRK_R3D:
9184
+ case QUIRK_SBZ:
9185
+ case QUIRK_ZXR:
9186
+ ca0132_mmio_init_sbz(codec);
9187
+ break;
9188
+ case QUIRK_AE5:
9189
+ ca0132_mmio_init_ae5(codec);
9190
+ break;
9191
+ default:
9192
+ break;
9193
+ }
9194
+}
9195
+
9196
+static const unsigned int ca0132_ae5_register_set_addresses[] = {
9197
+ 0x304, 0x304, 0x304, 0x304, 0x100, 0x304, 0x100, 0x304, 0x100, 0x304,
9198
+ 0x100, 0x304, 0x86c, 0x800, 0x86c, 0x800, 0x804
9199
+};
9200
+
9201
+static const unsigned char ca0132_ae5_register_set_data[] = {
9202
+ 0x0f, 0x0e, 0x1f, 0x0c, 0x3f, 0x08, 0x7f, 0x00, 0xff, 0x00, 0x6b,
9203
+ 0x01, 0x6b, 0x57
9204
+};
9205
+
9206
+/*
9207
+ * This function writes to some SFR's, does some region2 writes, and then
9208
+ * eventually resets the codec with the 0x7ff verb. Not quite sure why it does
9209
+ * what it does.
9210
+ */
9211
+static void ae5_register_set(struct hda_codec *codec)
9212
+{
9213
+ struct ca0132_spec *spec = codec->spec;
9214
+ unsigned int count = ARRAY_SIZE(ca0132_ae5_register_set_addresses);
9215
+ const unsigned int *addr = ca0132_ae5_register_set_addresses;
9216
+ const unsigned char *data = ca0132_ae5_register_set_data;
9217
+ unsigned int i, cur_addr;
9218
+ unsigned char tmp[3];
9219
+
9220
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9221
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9222
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41);
9223
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9224
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8);
9225
+ }
9226
+
9227
+ chipio_8051_write_direct(codec, 0x93, 0x10);
9228
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9229
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
9230
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9231
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
9232
+
9233
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9234
+ tmp[0] = 0x03;
9235
+ tmp[1] = 0x03;
9236
+ tmp[2] = 0x07;
9237
+ } else {
9238
+ tmp[0] = 0x0f;
9239
+ tmp[1] = 0x0f;
9240
+ tmp[2] = 0x0f;
9241
+ }
9242
+
9243
+ for (i = cur_addr = 0; i < 3; i++, cur_addr++)
9244
+ writeb(tmp[i], spec->mem_base + addr[cur_addr]);
9245
+
9246
+ /*
9247
+ * First writes are in single bytes, final are in 4 bytes. So, we use
9248
+ * writeb, then writel.
9249
+ */
9250
+ for (i = 0; cur_addr < 12; i++, cur_addr++)
9251
+ writeb(data[i], spec->mem_base + addr[cur_addr]);
9252
+
9253
+ for (; cur_addr < count; i++, cur_addr++)
9254
+ writel(data[i], spec->mem_base + addr[cur_addr]);
9255
+
9256
+ writel(0x00800001, spec->mem_base + 0x20c);
9257
+
9258
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9259
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
9260
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
9261
+ } else {
9262
+ ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
9263
+ }
9264
+
9265
+ chipio_8051_write_direct(codec, 0x90, 0x00);
9266
+ chipio_8051_write_direct(codec, 0x90, 0x10);
9267
+
9268
+ if (ca0132_quirk(spec) == QUIRK_AE5)
9269
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
9270
+
9271
+ chipio_write(codec, 0x18b0a4, 0x000000c2);
9272
+
9273
+ snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00);
9274
+ snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00);
72299275 }
72309276
72319277 /*
....@@ -7239,7 +9285,7 @@
72399285
72409286 ca0132_alt_vol_setup(codec);
72419287
7242
- switch (spec->quirk) {
9288
+ switch (ca0132_quirk(spec)) {
72439289 case QUIRK_SBZ:
72449290 codec_dbg(codec, "SBZ alt_init");
72459291 ca0132_gpio_init(codec);
....@@ -7260,6 +9306,36 @@
72609306 r3d_pre_dsp_setup(codec);
72619307 snd_hda_sequence_write(codec, spec->chip_init_verbs);
72629308 snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9309
+ break;
9310
+ case QUIRK_AE5:
9311
+ ca0132_gpio_init(codec);
9312
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9313
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49);
9314
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9315
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88);
9316
+ chipio_write(codec, 0x18b030, 0x00000020);
9317
+ snd_hda_sequence_write(codec, spec->chip_init_verbs);
9318
+ snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9319
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
9320
+ break;
9321
+ case QUIRK_AE7:
9322
+ ca0132_gpio_init(codec);
9323
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9324
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49);
9325
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9326
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88);
9327
+ snd_hda_sequence_write(codec, spec->chip_init_verbs);
9328
+ snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9329
+ chipio_write(codec, 0x18b008, 0x000000f8);
9330
+ chipio_write(codec, 0x18b008, 0x000000f0);
9331
+ chipio_write(codec, 0x18b030, 0x00000020);
9332
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
9333
+ break;
9334
+ case QUIRK_ZXR:
9335
+ snd_hda_sequence_write(codec, spec->chip_init_verbs);
9336
+ snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9337
+ break;
9338
+ default:
72639339 break;
72649340 }
72659341 }
....@@ -7287,7 +9363,7 @@
72879363 spec->dsp_reload = true;
72889364 spec->dsp_state = DSP_DOWNLOAD_INIT;
72899365 } else {
7290
- if (spec->quirk == QUIRK_SBZ)
9366
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
72919367 sbz_dsp_startup_check(codec);
72929368 return 0;
72939369 }
....@@ -7297,10 +9373,13 @@
72979373 spec->dsp_state = DSP_DOWNLOAD_INIT;
72989374 spec->curr_chip_addx = INVALID_CHIP_ADDRESS;
72999375
7300
- if (spec->use_pci_mmio)
9376
+ if (ca0132_use_pci_mmio(spec))
73019377 ca0132_mmio_init(codec);
73029378
73039379 snd_hda_power_up_pm(codec);
9380
+
9381
+ if (ca0132_quirk(spec) == QUIRK_AE5 || ca0132_quirk(spec) == QUIRK_AE7)
9382
+ ae5_register_set(codec);
73049383
73059384 ca0132_init_unsol(codec);
73069385 ca0132_init_params(codec);
....@@ -7308,20 +9387,27 @@
73089387
73099388 snd_hda_sequence_write(codec, spec->base_init_verbs);
73109389
7311
- if (spec->use_alt_functions)
9390
+ if (ca0132_use_alt_functions(spec))
73129391 ca0132_alt_init(codec);
73139392
73149393 ca0132_download_dsp(codec);
73159394
73169395 ca0132_refresh_widget_caps(codec);
73179396
7318
- switch (spec->quirk) {
9397
+ switch (ca0132_quirk(spec)) {
73199398 case QUIRK_R3DI:
73209399 case QUIRK_R3D:
73219400 r3d_setup_defaults(codec);
73229401 break;
73239402 case QUIRK_SBZ:
9403
+ case QUIRK_ZXR:
73249404 sbz_setup_defaults(codec);
9405
+ break;
9406
+ case QUIRK_AE5:
9407
+ ae5_setup_defaults(codec);
9408
+ break;
9409
+ case QUIRK_AE7:
9410
+ ae7_setup_defaults(codec);
73259411 break;
73269412 default:
73279413 ca0132_setup_defaults(codec);
....@@ -7340,7 +9426,7 @@
73409426
73419427 init_input(codec, cfg->dig_in_pin, spec->dig_in);
73429428
7343
- if (!spec->use_alt_functions) {
9429
+ if (!ca0132_use_alt_functions(spec)) {
73449430 snd_hda_sequence_write(codec, spec->chip_init_verbs);
73459431 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
73469432 VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D);
....@@ -7348,11 +9434,11 @@
73489434 VENDOR_CHIPIO_PARAM_EX_VALUE_SET, 0x20);
73499435 }
73509436
7351
- if (spec->quirk == QUIRK_SBZ)
9437
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
73529438 ca0132_gpio_setup(codec);
73539439
73549440 snd_hda_sequence_write(codec, spec->spec_init_verbs);
7355
- if (spec->use_alt_functions) {
9441
+ if (ca0132_use_alt_functions(spec)) {
73569442 ca0132_alt_select_out(codec);
73579443 ca0132_alt_select_in(codec);
73589444 } else {
....@@ -7376,21 +9462,47 @@
73769462 return 0;
73779463 }
73789464
9465
+static int dbpro_init(struct hda_codec *codec)
9466
+{
9467
+ struct ca0132_spec *spec = codec->spec;
9468
+ struct auto_pin_cfg *cfg = &spec->autocfg;
9469
+ unsigned int i;
9470
+
9471
+ init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
9472
+ init_input(codec, cfg->dig_in_pin, spec->dig_in);
9473
+
9474
+ for (i = 0; i < spec->num_inputs; i++)
9475
+ init_input(codec, spec->input_pins[i], spec->adcs[i]);
9476
+
9477
+ return 0;
9478
+}
9479
+
73799480 static void ca0132_free(struct hda_codec *codec)
73809481 {
73819482 struct ca0132_spec *spec = codec->spec;
73829483
73839484 cancel_delayed_work_sync(&spec->unsol_hp_work);
73849485 snd_hda_power_up(codec);
7385
- switch (spec->quirk) {
9486
+ switch (ca0132_quirk(spec)) {
73869487 case QUIRK_SBZ:
73879488 sbz_exit_chip(codec);
9489
+ break;
9490
+ case QUIRK_ZXR:
9491
+ zxr_exit_chip(codec);
73889492 break;
73899493 case QUIRK_R3D:
73909494 r3d_exit_chip(codec);
73919495 break;
9496
+ case QUIRK_AE5:
9497
+ ae5_exit_chip(codec);
9498
+ break;
9499
+ case QUIRK_AE7:
9500
+ ae7_exit_chip(codec);
9501
+ break;
73929502 case QUIRK_R3DI:
73939503 r3di_gpio_shutdown(codec);
9504
+ break;
9505
+ default:
73949506 break;
73959507 }
73969508
....@@ -7402,6 +9514,16 @@
74029514 if (spec->mem_base)
74039515 pci_iounmap(codec->bus->pci, spec->mem_base);
74049516 #endif
9517
+ kfree(spec->spec_init_verbs);
9518
+ kfree(codec->spec);
9519
+}
9520
+
9521
+static void dbpro_free(struct hda_codec *codec)
9522
+{
9523
+ struct ca0132_spec *spec = codec->spec;
9524
+
9525
+ zxr_dbpro_power_state_shutdown(codec);
9526
+
74059527 kfree(spec->spec_init_verbs);
74069528 kfree(codec->spec);
74079529 }
....@@ -7433,6 +9555,13 @@
74339555 .reboot_notify = ca0132_reboot_notify,
74349556 };
74359557
9558
+static const struct hda_codec_ops dbpro_patch_ops = {
9559
+ .build_controls = dbpro_build_controls,
9560
+ .build_pcms = dbpro_build_pcms,
9561
+ .init = dbpro_init,
9562
+ .free = dbpro_free,
9563
+};
9564
+
74369565 static void ca0132_config(struct hda_codec *codec)
74379566 {
74389567 struct ca0132_spec *spec = codec->spec;
....@@ -7444,16 +9573,46 @@
74449573 spec->multiout.dac_nids = spec->dacs;
74459574 spec->multiout.num_dacs = 3;
74469575
7447
- if (!spec->use_alt_functions)
9576
+ if (!ca0132_use_alt_functions(spec))
74489577 spec->multiout.max_channels = 2;
74499578 else
74509579 spec->multiout.max_channels = 6;
74519580
7452
- switch (spec->quirk) {
9581
+ switch (ca0132_quirk(spec)) {
74539582 case QUIRK_ALIENWARE:
7454
- codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n");
9583
+ codec_dbg(codec, "%s: QUIRK_ALIENWARE applied.\n", __func__);
74559584 snd_hda_apply_pincfgs(codec, alienware_pincfgs);
9585
+ break;
9586
+ case QUIRK_SBZ:
9587
+ codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__);
9588
+ snd_hda_apply_pincfgs(codec, sbz_pincfgs);
9589
+ break;
9590
+ case QUIRK_ZXR:
9591
+ codec_dbg(codec, "%s: QUIRK_ZXR applied.\n", __func__);
9592
+ snd_hda_apply_pincfgs(codec, zxr_pincfgs);
9593
+ break;
9594
+ case QUIRK_R3D:
9595
+ codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__);
9596
+ snd_hda_apply_pincfgs(codec, r3d_pincfgs);
9597
+ break;
9598
+ case QUIRK_R3DI:
9599
+ codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__);
9600
+ snd_hda_apply_pincfgs(codec, r3di_pincfgs);
9601
+ break;
9602
+ case QUIRK_AE5:
9603
+ codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__);
9604
+ snd_hda_apply_pincfgs(codec, ae5_pincfgs);
9605
+ break;
9606
+ case QUIRK_AE7:
9607
+ codec_dbg(codec, "%s: QUIRK_AE7 applied.\n", __func__);
9608
+ snd_hda_apply_pincfgs(codec, ae7_pincfgs);
9609
+ break;
9610
+ default:
9611
+ break;
9612
+ }
74569613
9614
+ switch (ca0132_quirk(spec)) {
9615
+ case QUIRK_ALIENWARE:
74579616 spec->num_outputs = 2;
74589617 spec->out_pins[0] = 0x0b; /* speaker out */
74599618 spec->out_pins[1] = 0x0f;
....@@ -7473,15 +9632,6 @@
74739632 break;
74749633 case QUIRK_SBZ:
74759634 case QUIRK_R3D:
7476
- if (spec->quirk == QUIRK_SBZ) {
7477
- codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__);
7478
- snd_hda_apply_pincfgs(codec, sbz_pincfgs);
7479
- }
7480
- if (spec->quirk == QUIRK_R3D) {
7481
- codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__);
7482
- snd_hda_apply_pincfgs(codec, r3d_pincfgs);
7483
- }
7484
-
74859635 spec->num_outputs = 2;
74869636 spec->out_pins[0] = 0x0B; /* Line out */
74879637 spec->out_pins[1] = 0x0F; /* Rear headphone out */
....@@ -7506,10 +9656,63 @@
75069656 spec->multiout.dig_out_nid = spec->dig_out;
75079657 spec->dig_in = 0x09;
75089658 break;
7509
- case QUIRK_R3DI:
7510
- codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__);
7511
- snd_hda_apply_pincfgs(codec, r3di_pincfgs);
9659
+ case QUIRK_ZXR:
9660
+ spec->num_outputs = 2;
9661
+ spec->out_pins[0] = 0x0B; /* Line out */
9662
+ spec->out_pins[1] = 0x0F; /* Rear headphone out */
9663
+ spec->out_pins[2] = 0x10; /* Center/LFE */
9664
+ spec->out_pins[3] = 0x11; /* Rear surround */
9665
+ spec->shared_out_nid = 0x2;
9666
+ spec->unsol_tag_hp = spec->out_pins[1];
9667
+ spec->unsol_tag_front_hp = spec->out_pins[2];
75129668
9669
+ spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
9670
+ spec->adcs[1] = 0x8; /* Not connected, no front mic */
9671
+ spec->adcs[2] = 0xa; /* what u hear */
9672
+
9673
+ spec->num_inputs = 2;
9674
+ spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
9675
+ spec->input_pins[1] = 0x13; /* What U Hear */
9676
+ spec->shared_mic_nid = 0x7;
9677
+ spec->unsol_tag_amic1 = spec->input_pins[0];
9678
+ break;
9679
+ case QUIRK_ZXR_DBPRO:
9680
+ spec->adcs[0] = 0x8; /* ZxR DBPro Aux In */
9681
+
9682
+ spec->num_inputs = 1;
9683
+ spec->input_pins[0] = 0x11; /* RCA Line-in */
9684
+
9685
+ spec->dig_out = 0x05;
9686
+ spec->multiout.dig_out_nid = spec->dig_out;
9687
+
9688
+ spec->dig_in = 0x09;
9689
+ break;
9690
+ case QUIRK_AE5:
9691
+ case QUIRK_AE7:
9692
+ spec->num_outputs = 2;
9693
+ spec->out_pins[0] = 0x0B; /* Line out */
9694
+ spec->out_pins[1] = 0x11; /* Rear headphone out */
9695
+ spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
9696
+ spec->out_pins[3] = 0x0F; /* Rear surround */
9697
+ spec->shared_out_nid = 0x2;
9698
+ spec->unsol_tag_hp = spec->out_pins[1];
9699
+ spec->unsol_tag_front_hp = spec->out_pins[2];
9700
+
9701
+ spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
9702
+ spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */
9703
+ spec->adcs[2] = 0xa; /* what u hear */
9704
+
9705
+ spec->num_inputs = 2;
9706
+ spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
9707
+ spec->input_pins[1] = 0x13; /* What U Hear */
9708
+ spec->shared_mic_nid = 0x7;
9709
+ spec->unsol_tag_amic1 = spec->input_pins[0];
9710
+
9711
+ /* SPDIF I/O */
9712
+ spec->dig_out = 0x05;
9713
+ spec->multiout.dig_out_nid = spec->dig_out;
9714
+ break;
9715
+ case QUIRK_R3DI:
75139716 spec->num_outputs = 2;
75149717 spec->out_pins[0] = 0x0B; /* Line out */
75159718 spec->out_pins[1] = 0x0F; /* Rear headphone out */
....@@ -7566,7 +9769,11 @@
75669769 struct ca0132_spec *spec = codec->spec;
75679770
75689771 spec->chip_init_verbs = ca0132_init_verbs0;
7569
- if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3D)
9772
+ /*
9773
+ * Since desktop cards use pci_mmio, this can be used to determine
9774
+ * whether or not to use these verbs instead of a separate bool.
9775
+ */
9776
+ if (ca0132_use_pci_mmio(spec))
75709777 spec->desktop_init_verbs = ca0132_init_verbs1;
75719778 spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS,
75729779 sizeof(struct hda_verb),
....@@ -7598,6 +9805,29 @@
75989805 return 0;
75999806 }
76009807
9808
+/*
9809
+ * The Sound Blaster ZxR shares the same PCI subsystem ID as some regular
9810
+ * Sound Blaster Z cards. However, they have different HDA codec subsystem
9811
+ * ID's. So, we check for the ZxR's subsystem ID, as well as the DBPro
9812
+ * daughter boards ID.
9813
+ */
9814
+static void sbz_detect_quirk(struct hda_codec *codec)
9815
+{
9816
+ struct ca0132_spec *spec = codec->spec;
9817
+
9818
+ switch (codec->core.subsystem_id) {
9819
+ case 0x11020033:
9820
+ spec->quirk = QUIRK_ZXR;
9821
+ break;
9822
+ case 0x1102003f:
9823
+ spec->quirk = QUIRK_ZXR_DBPRO;
9824
+ break;
9825
+ default:
9826
+ spec->quirk = QUIRK_SBZ;
9827
+ break;
9828
+ }
9829
+}
9830
+
76019831 static int patch_ca0132(struct hda_codec *codec)
76029832 {
76039833 struct ca0132_spec *spec;
....@@ -7612,25 +9842,38 @@
76129842 codec->spec = spec;
76139843 spec->codec = codec;
76149844
7615
- codec->patch_ops = ca0132_patch_ops;
7616
- codec->pcm_format_first = 1;
7617
- codec->no_sticky_stream = 1;
7618
-
76199845 /* Detect codec quirk */
76209846 quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
76219847 if (quirk)
76229848 spec->quirk = quirk->value;
76239849 else
76249850 spec->quirk = QUIRK_NONE;
9851
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
9852
+ sbz_detect_quirk(codec);
9853
+
9854
+ if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
9855
+ codec->patch_ops = dbpro_patch_ops;
9856
+ else
9857
+ codec->patch_ops = ca0132_patch_ops;
9858
+
9859
+ codec->pcm_format_first = 1;
9860
+ codec->no_sticky_stream = 1;
9861
+
76259862
76269863 spec->dsp_state = DSP_DOWNLOAD_INIT;
76279864 spec->num_mixers = 1;
76289865
76299866 /* Set which mixers each quirk uses. */
7630
- switch (spec->quirk) {
9867
+ switch (ca0132_quirk(spec)) {
76319868 case QUIRK_SBZ:
76329869 spec->mixers[0] = desktop_mixer;
76339870 snd_hda_codec_set_name(codec, "Sound Blaster Z");
9871
+ break;
9872
+ case QUIRK_ZXR:
9873
+ spec->mixers[0] = desktop_mixer;
9874
+ snd_hda_codec_set_name(codec, "Sound Blaster ZxR");
9875
+ break;
9876
+ case QUIRK_ZXR_DBPRO:
76349877 break;
76359878 case QUIRK_R3D:
76369879 spec->mixers[0] = desktop_mixer;
....@@ -7640,15 +9883,26 @@
76409883 spec->mixers[0] = r3di_mixer;
76419884 snd_hda_codec_set_name(codec, "Recon3Di");
76429885 break;
9886
+ case QUIRK_AE5:
9887
+ spec->mixers[0] = desktop_mixer;
9888
+ snd_hda_codec_set_name(codec, "Sound BlasterX AE-5");
9889
+ break;
9890
+ case QUIRK_AE7:
9891
+ spec->mixers[0] = desktop_mixer;
9892
+ snd_hda_codec_set_name(codec, "Sound Blaster AE-7");
9893
+ break;
76439894 default:
76449895 spec->mixers[0] = ca0132_mixer;
76459896 break;
76469897 }
76479898
76489899 /* Setup whether or not to use alt functions/controls/pci_mmio */
7649
- switch (spec->quirk) {
9900
+ switch (ca0132_quirk(spec)) {
76509901 case QUIRK_SBZ:
76519902 case QUIRK_R3D:
9903
+ case QUIRK_AE5:
9904
+ case QUIRK_AE7:
9905
+ case QUIRK_ZXR:
76529906 spec->use_alt_controls = true;
76539907 spec->use_alt_functions = true;
76549908 spec->use_pci_mmio = true;
....@@ -7665,6 +9919,7 @@
76659919 break;
76669920 }
76679921
9922
+#ifdef CONFIG_PCI
76689923 if (spec->use_pci_mmio) {
76699924 spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20);
76709925 if (spec->mem_base == NULL) {
....@@ -7672,6 +9927,7 @@
76729927 spec->quirk = QUIRK_NONE;
76739928 }
76749929 }
9930
+#endif
76759931
76769932 spec->base_init_verbs = ca0132_base_init_verbs;
76779933 spec->base_exit_verbs = ca0132_base_exit_verbs;
....@@ -7700,7 +9956,7 @@
77009956 /*
77019957 * patch entries
77029958 */
7703
-static struct hda_device_id snd_hda_id_ca0132[] = {
9959
+static const struct hda_device_id snd_hda_id_ca0132[] = {
77049960 HDA_CODEC_ENTRY(0x11020011, "CA0132", patch_ca0132),
77059961 {} /* terminator */
77069962 };