forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
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,212 @@
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, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI),
10731276 SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
1277
+ SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
1278
+ SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5),
1279
+ SND_PCI_QUIRK(0x1102, 0x0191, "Sound Blaster AE-5 Plus", QUIRK_AE5),
1280
+ SND_PCI_QUIRK(0x1102, 0x0081, "Sound Blaster AE-7", QUIRK_AE7),
10741281 {}
1282
+};
1283
+
1284
+/* Output selection quirk info structures. */
1285
+#define MAX_QUIRK_MMIO_GPIO_SET_VALS 3
1286
+#define MAX_QUIRK_SCP_SET_VALS 2
1287
+struct ca0132_alt_out_set_info {
1288
+ unsigned int dac2port; /* ParamID 0x0d value. */
1289
+
1290
+ bool has_hda_gpio;
1291
+ char hda_gpio_pin;
1292
+ char hda_gpio_set;
1293
+
1294
+ unsigned int mmio_gpio_count;
1295
+ char mmio_gpio_pin[MAX_QUIRK_MMIO_GPIO_SET_VALS];
1296
+ char mmio_gpio_set[MAX_QUIRK_MMIO_GPIO_SET_VALS];
1297
+
1298
+ unsigned int scp_cmds_count;
1299
+ unsigned int scp_cmd_mid[MAX_QUIRK_SCP_SET_VALS];
1300
+ unsigned int scp_cmd_req[MAX_QUIRK_SCP_SET_VALS];
1301
+ unsigned int scp_cmd_val[MAX_QUIRK_SCP_SET_VALS];
1302
+
1303
+ bool has_chipio_write;
1304
+ unsigned int chipio_write_addr;
1305
+ unsigned int chipio_write_data;
1306
+};
1307
+
1308
+struct ca0132_alt_out_set_quirk_data {
1309
+ int quirk_id;
1310
+
1311
+ bool has_headphone_gain;
1312
+ bool is_ae_series;
1313
+
1314
+ struct ca0132_alt_out_set_info out_set_info[NUM_OF_OUTPUTS];
1315
+};
1316
+
1317
+static const struct ca0132_alt_out_set_quirk_data quirk_out_set_data[] = {
1318
+ { .quirk_id = QUIRK_R3DI,
1319
+ .has_headphone_gain = false,
1320
+ .is_ae_series = false,
1321
+ .out_set_info = {
1322
+ /* Speakers. */
1323
+ { .dac2port = 0x24,
1324
+ .has_hda_gpio = true,
1325
+ .hda_gpio_pin = 2,
1326
+ .hda_gpio_set = 1,
1327
+ .mmio_gpio_count = 0,
1328
+ .scp_cmds_count = 0,
1329
+ .has_chipio_write = false,
1330
+ },
1331
+ /* Headphones. */
1332
+ { .dac2port = 0x21,
1333
+ .has_hda_gpio = true,
1334
+ .hda_gpio_pin = 2,
1335
+ .hda_gpio_set = 0,
1336
+ .mmio_gpio_count = 0,
1337
+ .scp_cmds_count = 0,
1338
+ .has_chipio_write = false,
1339
+ } },
1340
+ },
1341
+ { .quirk_id = QUIRK_R3D,
1342
+ .has_headphone_gain = false,
1343
+ .is_ae_series = false,
1344
+ .out_set_info = {
1345
+ /* Speakers. */
1346
+ { .dac2port = 0x24,
1347
+ .has_hda_gpio = false,
1348
+ .mmio_gpio_count = 1,
1349
+ .mmio_gpio_pin = { 1 },
1350
+ .mmio_gpio_set = { 1 },
1351
+ .scp_cmds_count = 0,
1352
+ .has_chipio_write = false,
1353
+ },
1354
+ /* Headphones. */
1355
+ { .dac2port = 0x21,
1356
+ .has_hda_gpio = false,
1357
+ .mmio_gpio_count = 1,
1358
+ .mmio_gpio_pin = { 1 },
1359
+ .mmio_gpio_set = { 0 },
1360
+ .scp_cmds_count = 0,
1361
+ .has_chipio_write = false,
1362
+ } },
1363
+ },
1364
+ { .quirk_id = QUIRK_SBZ,
1365
+ .has_headphone_gain = false,
1366
+ .is_ae_series = false,
1367
+ .out_set_info = {
1368
+ /* Speakers. */
1369
+ { .dac2port = 0x18,
1370
+ .has_hda_gpio = false,
1371
+ .mmio_gpio_count = 3,
1372
+ .mmio_gpio_pin = { 7, 4, 1 },
1373
+ .mmio_gpio_set = { 0, 1, 1 },
1374
+ .scp_cmds_count = 0,
1375
+ .has_chipio_write = false, },
1376
+ /* Headphones. */
1377
+ { .dac2port = 0x12,
1378
+ .has_hda_gpio = false,
1379
+ .mmio_gpio_count = 3,
1380
+ .mmio_gpio_pin = { 7, 4, 1 },
1381
+ .mmio_gpio_set = { 1, 1, 0 },
1382
+ .scp_cmds_count = 0,
1383
+ .has_chipio_write = false,
1384
+ } },
1385
+ },
1386
+ { .quirk_id = QUIRK_ZXR,
1387
+ .has_headphone_gain = true,
1388
+ .is_ae_series = false,
1389
+ .out_set_info = {
1390
+ /* Speakers. */
1391
+ { .dac2port = 0x24,
1392
+ .has_hda_gpio = false,
1393
+ .mmio_gpio_count = 3,
1394
+ .mmio_gpio_pin = { 2, 3, 5 },
1395
+ .mmio_gpio_set = { 1, 1, 0 },
1396
+ .scp_cmds_count = 0,
1397
+ .has_chipio_write = false,
1398
+ },
1399
+ /* Headphones. */
1400
+ { .dac2port = 0x21,
1401
+ .has_hda_gpio = false,
1402
+ .mmio_gpio_count = 3,
1403
+ .mmio_gpio_pin = { 2, 3, 5 },
1404
+ .mmio_gpio_set = { 0, 1, 1 },
1405
+ .scp_cmds_count = 0,
1406
+ .has_chipio_write = false,
1407
+ } },
1408
+ },
1409
+ { .quirk_id = QUIRK_AE5,
1410
+ .has_headphone_gain = true,
1411
+ .is_ae_series = true,
1412
+ .out_set_info = {
1413
+ /* Speakers. */
1414
+ { .dac2port = 0xa4,
1415
+ .has_hda_gpio = false,
1416
+ .mmio_gpio_count = 0,
1417
+ .scp_cmds_count = 2,
1418
+ .scp_cmd_mid = { 0x96, 0x96 },
1419
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1420
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1421
+ .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO },
1422
+ .has_chipio_write = true,
1423
+ .chipio_write_addr = 0x0018b03c,
1424
+ .chipio_write_data = 0x00000012
1425
+ },
1426
+ /* Headphones. */
1427
+ { .dac2port = 0xa1,
1428
+ .has_hda_gpio = false,
1429
+ .mmio_gpio_count = 0,
1430
+ .scp_cmds_count = 2,
1431
+ .scp_cmd_mid = { 0x96, 0x96 },
1432
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1433
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1434
+ .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE },
1435
+ .has_chipio_write = true,
1436
+ .chipio_write_addr = 0x0018b03c,
1437
+ .chipio_write_data = 0x00000012
1438
+ } },
1439
+ },
1440
+ { .quirk_id = QUIRK_AE7,
1441
+ .has_headphone_gain = true,
1442
+ .is_ae_series = true,
1443
+ .out_set_info = {
1444
+ /* Speakers. */
1445
+ { .dac2port = 0x58,
1446
+ .has_hda_gpio = false,
1447
+ .mmio_gpio_count = 1,
1448
+ .mmio_gpio_pin = { 0 },
1449
+ .mmio_gpio_set = { 1 },
1450
+ .scp_cmds_count = 2,
1451
+ .scp_cmd_mid = { 0x96, 0x96 },
1452
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1453
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1454
+ .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO },
1455
+ .has_chipio_write = true,
1456
+ .chipio_write_addr = 0x0018b03c,
1457
+ .chipio_write_data = 0x00000000
1458
+ },
1459
+ /* Headphones. */
1460
+ { .dac2port = 0x58,
1461
+ .has_hda_gpio = false,
1462
+ .mmio_gpio_count = 1,
1463
+ .mmio_gpio_pin = { 0 },
1464
+ .mmio_gpio_set = { 1 },
1465
+ .scp_cmds_count = 2,
1466
+ .scp_cmd_mid = { 0x96, 0x96 },
1467
+ .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT,
1468
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT },
1469
+ .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE },
1470
+ .has_chipio_write = true,
1471
+ .chipio_write_addr = 0x0018b03c,
1472
+ .chipio_write_data = 0x00000010
1473
+ } },
1474
+ }
10751475 };
10761476
10771477 /*
....@@ -1456,6 +1856,20 @@
14561856 }
14571857
14581858 /*
1859
+ * Writes to the 8051's internal address space directly instead of indirectly,
1860
+ * giving access to the special function registers located at addresses
1861
+ * 0x80-0xFF.
1862
+ */
1863
+static void chipio_8051_write_direct(struct hda_codec *codec,
1864
+ unsigned int addr, unsigned int data)
1865
+{
1866
+ unsigned int verb;
1867
+
1868
+ verb = VENDOR_CHIPIO_8051_WRITE_DIRECT | data;
1869
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, verb, addr);
1870
+}
1871
+
1872
+/*
14591873 * Enable clocks.
14601874 */
14611875 static void chipio_enable_clocks(struct hda_codec *codec)
....@@ -1798,6 +2212,7 @@
17982212 * Prepare and send the SCP message to DSP
17992213 * @codec: the HDA codec
18002214 * @mod_id: ID of the DSP module to send the command
2215
+ * @src_id: ID of the source
18012216 * @req: ID of request to send to the DSP module
18022217 * @dir: SET or GET
18032218 * @data: pointer to the data to send with the request, request specific
....@@ -2572,7 +2987,7 @@
25722987 u32 magic;
25732988 u32 chip_addr;
25742989 u32 count;
2575
- u32 data[0];
2990
+ u32 data[];
25762991 };
25772992
25782993 static const u32 g_magic_value = 0x4c46584d;
....@@ -2595,7 +3010,7 @@
25953010
25963011 static size_t dsp_sizeof(const struct dsp_image_seg *p)
25973012 {
2598
- return sizeof(*p) + p->count*sizeof(u32);
3013
+ return struct_size(p, data, p->count);
25993014 }
26003015
26013016 static const struct dsp_image_seg *get_next_seg_ptr(
....@@ -2701,7 +3116,7 @@
27013116 }
27023117
27033118 data = fls->data;
2704
- chip_addx = fls->chip_addr,
3119
+ chip_addx = fls->chip_addr;
27053120 words_to_write = fls->count;
27063121
27073122 if (!words_to_write)
....@@ -2976,7 +3391,7 @@
29763391 {
29773392 struct ca0132_spec *spec = codec->spec;
29783393 codec_dbg(codec, "---- dspload_post_setup ------\n");
2979
- if (!spec->use_alt_functions) {
3394
+ if (!ca0132_use_alt_functions(spec)) {
29803395 /*set DSP speaker to 2.0 configuration*/
29813396 chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080);
29823397 chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000);
....@@ -3091,7 +3506,9 @@
30913506 }
30923507
30933508 /*
3094
- * Setup GPIO for the other variants of Core3D.
3509
+ * ca0113 related functions. The ca0113 acts as the HDA bus for the pci-e
3510
+ * based cards, and has a second mmio region, region2, that's used for special
3511
+ * commands.
30953512 */
30963513
30973514 /*
....@@ -3099,8 +3516,11 @@
30993516 * the mmio address 0x320 is used to set GPIO pins. The format for the data
31003517 * The first eight bits are just the number of the pin. So far, I've only seen
31013518 * this number go to 7.
3519
+ * AE-5 note: The AE-5 seems to use pins 2 and 3 to somehow set the color value
3520
+ * of the on-card LED. It seems to use pin 2 for data, then toggles 3 to on and
3521
+ * then off to send that bit.
31023522 */
3103
-static void ca0132_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin,
3523
+static void ca0113_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin,
31043524 bool enable)
31053525 {
31063526 struct ca0132_spec *spec = codec->spec;
....@@ -3113,6 +3533,89 @@
31133533 }
31143534
31153535 /*
3536
+ * Special pci region2 commands that are only used by the AE-5. They follow
3537
+ * a set format, and require reads at certain points to seemingly 'clear'
3538
+ * the response data. My first tests didn't do these reads, and would cause
3539
+ * the card to get locked up until the memory was read. These commands
3540
+ * seem to work with three distinct values that I've taken to calling group,
3541
+ * target-id, and value.
3542
+ */
3543
+static void ca0113_mmio_command_set(struct hda_codec *codec, unsigned int group,
3544
+ unsigned int target, unsigned int value)
3545
+{
3546
+ struct ca0132_spec *spec = codec->spec;
3547
+ unsigned int write_val;
3548
+
3549
+ writel(0x0000007e, spec->mem_base + 0x210);
3550
+ readl(spec->mem_base + 0x210);
3551
+ writel(0x0000005a, spec->mem_base + 0x210);
3552
+ readl(spec->mem_base + 0x210);
3553
+ readl(spec->mem_base + 0x210);
3554
+
3555
+ writel(0x00800005, spec->mem_base + 0x20c);
3556
+ writel(group, spec->mem_base + 0x804);
3557
+
3558
+ writel(0x00800005, spec->mem_base + 0x20c);
3559
+ write_val = (target & 0xff);
3560
+ write_val |= (value << 8);
3561
+
3562
+
3563
+ writel(write_val, spec->mem_base + 0x204);
3564
+ /*
3565
+ * Need delay here or else it goes too fast and works inconsistently.
3566
+ */
3567
+ msleep(20);
3568
+
3569
+ readl(spec->mem_base + 0x860);
3570
+ readl(spec->mem_base + 0x854);
3571
+ readl(spec->mem_base + 0x840);
3572
+
3573
+ writel(0x00800004, spec->mem_base + 0x20c);
3574
+ writel(0x00000000, spec->mem_base + 0x210);
3575
+ readl(spec->mem_base + 0x210);
3576
+ readl(spec->mem_base + 0x210);
3577
+}
3578
+
3579
+/*
3580
+ * This second type of command is used for setting the sound filter type.
3581
+ */
3582
+static void ca0113_mmio_command_set_type2(struct hda_codec *codec,
3583
+ unsigned int group, unsigned int target, unsigned int value)
3584
+{
3585
+ struct ca0132_spec *spec = codec->spec;
3586
+ unsigned int write_val;
3587
+
3588
+ writel(0x0000007e, spec->mem_base + 0x210);
3589
+ readl(spec->mem_base + 0x210);
3590
+ writel(0x0000005a, spec->mem_base + 0x210);
3591
+ readl(spec->mem_base + 0x210);
3592
+ readl(spec->mem_base + 0x210);
3593
+
3594
+ writel(0x00800003, spec->mem_base + 0x20c);
3595
+ writel(group, spec->mem_base + 0x804);
3596
+
3597
+ writel(0x00800005, spec->mem_base + 0x20c);
3598
+ write_val = (target & 0xff);
3599
+ write_val |= (value << 8);
3600
+
3601
+
3602
+ writel(write_val, spec->mem_base + 0x204);
3603
+ msleep(20);
3604
+ readl(spec->mem_base + 0x860);
3605
+ readl(spec->mem_base + 0x854);
3606
+ readl(spec->mem_base + 0x840);
3607
+
3608
+ writel(0x00800004, spec->mem_base + 0x20c);
3609
+ writel(0x00000000, spec->mem_base + 0x210);
3610
+ readl(spec->mem_base + 0x210);
3611
+ readl(spec->mem_base + 0x210);
3612
+}
3613
+
3614
+/*
3615
+ * Setup GPIO for the other variants of Core3D.
3616
+ */
3617
+
3618
+/*
31163619 * Sets up the GPIO pins so that they are discoverable. If this isn't done,
31173620 * the card shows as having no GPIO pins.
31183621 */
....@@ -3120,8 +3623,10 @@
31203623 {
31213624 struct ca0132_spec *spec = codec->spec;
31223625
3123
- switch (spec->quirk) {
3626
+ switch (ca0132_quirk(spec)) {
31243627 case QUIRK_SBZ:
3628
+ case QUIRK_AE5:
3629
+ case QUIRK_AE7:
31253630 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
31263631 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
31273632 snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23);
....@@ -3129,6 +3634,8 @@
31293634 case QUIRK_R3DI:
31303635 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
31313636 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5B);
3637
+ break;
3638
+ default:
31323639 break;
31333640 }
31343641
....@@ -3139,7 +3646,7 @@
31393646 {
31403647 struct ca0132_spec *spec = codec->spec;
31413648
3142
- switch (spec->quirk) {
3649
+ switch (ca0132_quirk(spec)) {
31433650 case QUIRK_SBZ:
31443651 snd_hda_codec_write(codec, 0x01, 0,
31453652 AC_VERB_SET_GPIO_DIRECTION, 0x07);
....@@ -3157,6 +3664,8 @@
31573664 AC_VERB_SET_GPIO_MASK, 0x1F);
31583665 snd_hda_codec_write(codec, 0x01, 0,
31593666 AC_VERB_SET_GPIO_DATA, 0x0C);
3667
+ break;
3668
+ default:
31603669 break;
31613670 }
31623671 }
....@@ -3217,26 +3726,6 @@
32173726 break;
32183727 case R3DI_FRONT_MIC:
32193728 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);
32403729 break;
32413730 }
32423731 snd_hda_codec_write(codec, codec->core.afg, 0,
....@@ -3550,7 +4039,7 @@
35504039 /* The following are for tuning of products */
35514040 #ifdef ENABLE_TUNING_CONTROLS
35524041
3553
-static unsigned int voice_focus_vals_lookup[] = {
4042
+static const unsigned int voice_focus_vals_lookup[] = {
35544043 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000,
35554044 0x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000,
35564045 0x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000,
....@@ -3580,7 +4069,7 @@
35804069 0x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000
35814070 };
35824071
3583
-static unsigned int mic_svm_vals_lookup[] = {
4072
+static const unsigned int mic_svm_vals_lookup[] = {
35844073 0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
35854074 0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
35864075 0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
....@@ -3600,7 +4089,7 @@
36004089 0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
36014090 };
36024091
3603
-static unsigned int equalizer_vals_lookup[] = {
4092
+static const unsigned int equalizer_vals_lookup[] = {
36044093 0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
36054094 0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
36064095 0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
....@@ -3613,7 +4102,7 @@
36134102 };
36144103
36154104 static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
3616
- unsigned int *lookup, int idx)
4105
+ const unsigned int *lookup, int idx)
36174106 {
36184107 int i = 0;
36194108
....@@ -3931,24 +4420,221 @@
39314420 return err < 0 ? err : 0;
39324421 }
39334422
4423
+static int ae5_headphone_gain_set(struct hda_codec *codec, long val);
4424
+static int zxr_headphone_gain_set(struct hda_codec *codec, long val);
4425
+static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
4426
+
4427
+static void ae5_mmio_select_out(struct hda_codec *codec)
4428
+{
4429
+ struct ca0132_spec *spec = codec->spec;
4430
+ const struct ae_ca0113_output_set *out_cmds;
4431
+ unsigned int i;
4432
+
4433
+ if (ca0132_quirk(spec) == QUIRK_AE5)
4434
+ out_cmds = &ae5_ca0113_output_presets;
4435
+ else
4436
+ out_cmds = &ae7_ca0113_output_presets;
4437
+
4438
+ for (i = 0; i < AE_CA0113_OUT_SET_COMMANDS; i++)
4439
+ ca0113_mmio_command_set(codec, out_cmds->group[i],
4440
+ out_cmds->target[i],
4441
+ out_cmds->vals[spec->cur_out_type][i]);
4442
+}
4443
+
4444
+static int ca0132_alt_set_full_range_speaker(struct hda_codec *codec)
4445
+{
4446
+ struct ca0132_spec *spec = codec->spec;
4447
+ int quirk = ca0132_quirk(spec);
4448
+ unsigned int tmp;
4449
+ int err;
4450
+
4451
+ /* 2.0/4.0 setup has no LFE channel, so setting full-range does nothing. */
4452
+ if (spec->channel_cfg_val == SPEAKER_CHANNELS_4_0
4453
+ || spec->channel_cfg_val == SPEAKER_CHANNELS_2_0)
4454
+ return 0;
4455
+
4456
+ /* Set front L/R full range. Zero for full-range, one for redirection. */
4457
+ tmp = spec->speaker_range_val[0] ? FLOAT_ZERO : FLOAT_ONE;
4458
+ err = dspio_set_uint_param(codec, 0x96,
4459
+ SPEAKER_FULL_RANGE_FRONT_L_R, tmp);
4460
+ if (err < 0)
4461
+ return err;
4462
+
4463
+ /* When setting full-range rear, both rear and center/lfe are set. */
4464
+ tmp = spec->speaker_range_val[1] ? FLOAT_ZERO : FLOAT_ONE;
4465
+ err = dspio_set_uint_param(codec, 0x96,
4466
+ SPEAKER_FULL_RANGE_CENTER_LFE, tmp);
4467
+ if (err < 0)
4468
+ return err;
4469
+
4470
+ err = dspio_set_uint_param(codec, 0x96,
4471
+ SPEAKER_FULL_RANGE_REAR_L_R, tmp);
4472
+ if (err < 0)
4473
+ return err;
4474
+
4475
+ /*
4476
+ * Only the AE series cards set this value when setting full-range,
4477
+ * and it's always 1.0f.
4478
+ */
4479
+ if (quirk == QUIRK_AE5 || quirk == QUIRK_AE7) {
4480
+ err = dspio_set_uint_param(codec, 0x96,
4481
+ SPEAKER_FULL_RANGE_SURROUND_L_R, FLOAT_ONE);
4482
+ if (err < 0)
4483
+ return err;
4484
+ }
4485
+
4486
+ return 0;
4487
+}
4488
+
4489
+static int ca0132_alt_surround_set_bass_redirection(struct hda_codec *codec,
4490
+ bool val)
4491
+{
4492
+ struct ca0132_spec *spec = codec->spec;
4493
+ unsigned int tmp;
4494
+ int err;
4495
+
4496
+ if (val && spec->channel_cfg_val != SPEAKER_CHANNELS_4_0 &&
4497
+ spec->channel_cfg_val != SPEAKER_CHANNELS_2_0)
4498
+ tmp = FLOAT_ONE;
4499
+ else
4500
+ tmp = FLOAT_ZERO;
4501
+
4502
+ err = dspio_set_uint_param(codec, 0x96, SPEAKER_BASS_REDIRECT, tmp);
4503
+ if (err < 0)
4504
+ return err;
4505
+
4506
+ /* If it is enabled, make sure to set the crossover frequency. */
4507
+ if (tmp) {
4508
+ tmp = float_xbass_xover_lookup[spec->xbass_xover_freq];
4509
+ err = dspio_set_uint_param(codec, 0x96,
4510
+ SPEAKER_BASS_REDIRECT_XOVER_FREQ, tmp);
4511
+ if (err < 0)
4512
+ return err;
4513
+ }
4514
+
4515
+ return 0;
4516
+}
4517
+
4518
+/*
4519
+ * These are the commands needed to setup output on each of the different card
4520
+ * types.
4521
+ */
4522
+static void ca0132_alt_select_out_get_quirk_data(struct hda_codec *codec,
4523
+ const struct ca0132_alt_out_set_quirk_data **quirk_data)
4524
+{
4525
+ struct ca0132_spec *spec = codec->spec;
4526
+ int quirk = ca0132_quirk(spec);
4527
+ unsigned int i;
4528
+
4529
+ *quirk_data = NULL;
4530
+ for (i = 0; i < ARRAY_SIZE(quirk_out_set_data); i++) {
4531
+ if (quirk_out_set_data[i].quirk_id == quirk) {
4532
+ *quirk_data = &quirk_out_set_data[i];
4533
+ return;
4534
+ }
4535
+ }
4536
+}
4537
+
4538
+static int ca0132_alt_select_out_quirk_set(struct hda_codec *codec)
4539
+{
4540
+ const struct ca0132_alt_out_set_quirk_data *quirk_data;
4541
+ const struct ca0132_alt_out_set_info *out_info;
4542
+ struct ca0132_spec *spec = codec->spec;
4543
+ unsigned int i, gpio_data;
4544
+ int err;
4545
+
4546
+ ca0132_alt_select_out_get_quirk_data(codec, &quirk_data);
4547
+ if (!quirk_data)
4548
+ return 0;
4549
+
4550
+ out_info = &quirk_data->out_set_info[spec->cur_out_type];
4551
+ if (quirk_data->is_ae_series)
4552
+ ae5_mmio_select_out(codec);
4553
+
4554
+ if (out_info->has_hda_gpio) {
4555
+ gpio_data = snd_hda_codec_read(codec, codec->core.afg, 0,
4556
+ AC_VERB_GET_GPIO_DATA, 0);
4557
+
4558
+ if (out_info->hda_gpio_set)
4559
+ gpio_data |= (1 << out_info->hda_gpio_pin);
4560
+ else
4561
+ gpio_data &= ~(1 << out_info->hda_gpio_pin);
4562
+
4563
+ snd_hda_codec_write(codec, codec->core.afg, 0,
4564
+ AC_VERB_SET_GPIO_DATA, gpio_data);
4565
+ }
4566
+
4567
+ if (out_info->mmio_gpio_count) {
4568
+ for (i = 0; i < out_info->mmio_gpio_count; i++) {
4569
+ ca0113_mmio_gpio_set(codec, out_info->mmio_gpio_pin[i],
4570
+ out_info->mmio_gpio_set[i]);
4571
+ }
4572
+ }
4573
+
4574
+ if (out_info->scp_cmds_count) {
4575
+ for (i = 0; i < out_info->scp_cmds_count; i++) {
4576
+ err = dspio_set_uint_param(codec,
4577
+ out_info->scp_cmd_mid[i],
4578
+ out_info->scp_cmd_req[i],
4579
+ out_info->scp_cmd_val[i]);
4580
+ if (err < 0)
4581
+ return err;
4582
+ }
4583
+ }
4584
+
4585
+ chipio_set_control_param(codec, 0x0d, out_info->dac2port);
4586
+
4587
+ if (out_info->has_chipio_write) {
4588
+ chipio_write(codec, out_info->chipio_write_addr,
4589
+ out_info->chipio_write_data);
4590
+ }
4591
+
4592
+ if (quirk_data->has_headphone_gain) {
4593
+ if (spec->cur_out_type != HEADPHONE_OUT) {
4594
+ if (quirk_data->is_ae_series)
4595
+ ae5_headphone_gain_set(codec, 2);
4596
+ else
4597
+ zxr_headphone_gain_set(codec, 0);
4598
+ } else {
4599
+ if (quirk_data->is_ae_series)
4600
+ ae5_headphone_gain_set(codec,
4601
+ spec->ae5_headphone_gain_val);
4602
+ else
4603
+ zxr_headphone_gain_set(codec,
4604
+ spec->zxr_gain_set);
4605
+ }
4606
+ }
4607
+
4608
+ return 0;
4609
+}
4610
+
4611
+static void ca0132_set_out_node_pincfg(struct hda_codec *codec, hda_nid_t nid,
4612
+ bool out_enable, bool hp_enable)
4613
+{
4614
+ unsigned int pin_ctl;
4615
+
4616
+ pin_ctl = snd_hda_codec_read(codec, nid, 0,
4617
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4618
+
4619
+ pin_ctl = hp_enable ? pin_ctl | PIN_HP_AMP : pin_ctl & ~PIN_HP_AMP;
4620
+ pin_ctl = out_enable ? pin_ctl | PIN_OUT : pin_ctl & ~PIN_OUT;
4621
+ snd_hda_set_pin_ctl(codec, nid, pin_ctl);
4622
+}
4623
+
39344624 /*
39354625 * This function behaves similarly to the ca0132_select_out funciton above,
39364626 * except with a few differences. It adds the ability to select the current
39374627 * output with an enumerated control "output source" if the auto detect
39384628 * mute switch is set to off. If the auto detect mute switch is enabled, it
39394629 * 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.
4630
+ * It also adds the ability to auto-detect the front headphone port.
39434631 */
39444632 static int ca0132_alt_select_out(struct hda_codec *codec)
39454633 {
39464634 struct ca0132_spec *spec = codec->spec;
3947
- unsigned int pin_ctl;
4635
+ unsigned int tmp, outfx_set;
39484636 int jack_present;
39494637 int auto_jack;
3950
- unsigned int i;
3951
- unsigned int tmp;
39524638 int err;
39534639 /* Default Headphone is rear headphone */
39544640 hda_nid_t headphone_nid = spec->out_pins[1];
....@@ -3975,156 +4661,112 @@
39754661 } else
39764662 spec->cur_out_type = spec->out_enum_val;
39774663
3978
- /* Begin DSP output switch */
3979
- tmp = FLOAT_ONE;
3980
- err = dspio_set_uint_param(codec, 0x96, 0x3A, tmp);
4664
+ outfx_set = spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID];
4665
+
4666
+ /* Begin DSP output switch, mute DSP volume. */
4667
+ err = dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_MUTE, FLOAT_ONE);
39814668 if (err < 0)
4669
+ goto exit;
4670
+
4671
+ if (ca0132_alt_select_out_quirk_set(codec) < 0)
39824672 goto exit;
39834673
39844674 switch (spec->cur_out_type) {
39854675 case SPEAKER_OUT:
39864676 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
- }
40044677
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);
40154678 /* Enable EAPD */
40164679 snd_hda_codec_write(codec, spec->out_pins[0], 0,
40174680 AC_VERB_SET_EAPD_BTLENABLE, 0x01);
40184681
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);
4682
+ /* Disable headphone node. */
4683
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[1], 0, 0);
4684
+ /* Set front L-R to output. */
4685
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 1, 0);
4686
+ /* Set Center/LFE to output. */
4687
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 1, 0);
4688
+ /* Set rear surround to output. */
4689
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 1, 0);
4690
+
4691
+ /*
4692
+ * Without PlayEnhancement being enabled, if we've got a 2.0
4693
+ * setup, set it to floating point eight to disable any DSP
4694
+ * processing effects.
4695
+ */
4696
+ if (!outfx_set && spec->channel_cfg_val == SPEAKER_CHANNELS_2_0)
4697
+ tmp = FLOAT_EIGHT;
40224698 else
4023
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT);
4699
+ tmp = speaker_channel_cfgs[spec->channel_cfg_val].val;
4700
+
4701
+ err = dspio_set_uint_param(codec, 0x80, 0x04, tmp);
4702
+ if (err < 0)
4703
+ goto exit;
4704
+
40244705 break;
40254706 case HEADPHONE_OUT:
40264707 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
-
40454708 snd_hda_codec_write(codec, spec->out_pins[0], 0,
40464709 AC_VERB_SET_EAPD_BTLENABLE, 0x00);
40474710
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);
4711
+ /* Disable all speaker nodes. */
4712
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 0, 0);
4713
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 0, 0);
4714
+ ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 0, 0);
40534715
40544716 /* enable headphone, either front or rear */
4055
-
40564717 if (snd_hda_jack_detect(codec, spec->unsol_tag_front_hp))
40574718 headphone_nid = spec->out_pins[2];
40584719 else if (snd_hda_jack_detect(codec, spec->unsol_tag_hp))
40594720 headphone_nid = spec->out_pins[1];
40604721
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);
4722
+ ca0132_set_out_node_pincfg(codec, headphone_nid, 1, 1);
40654723
4066
- if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4067
- dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
4724
+ if (outfx_set)
4725
+ err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
40684726 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);
4727
+ err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO);
41134728
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);
4729
+ if (err < 0)
4730
+ goto exit;
41184731 break;
41194732 }
4733
+ /*
4734
+ * If output effects are enabled, set the X-Bass effect value again to
4735
+ * make sure that it's properly enabled/disabled for speaker
4736
+ * configurations with an LFE channel.
4737
+ */
4738
+ if (outfx_set)
4739
+ ca0132_effects_set(codec, X_BASS,
4740
+ spec->effects_switch[X_BASS - EFFECT_START_NID]);
41204741
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]);
4742
+ /* Set speaker EQ bypass attenuation to 0. */
4743
+ err = dspio_set_uint_param(codec, 0x8f, 0x01, FLOAT_ZERO);
4744
+ if (err < 0)
4745
+ goto exit;
41274746
4747
+ /*
4748
+ * Although unused on all cards but the AE series, this is always set
4749
+ * to zero when setting the output.
4750
+ */
4751
+ err = dspio_set_uint_param(codec, 0x96,
4752
+ SPEAKER_TUNING_USE_SPEAKER_EQ, FLOAT_ZERO);
4753
+ if (err < 0)
4754
+ goto exit;
4755
+
4756
+ if (spec->cur_out_type == SPEAKER_OUT)
4757
+ err = ca0132_alt_surround_set_bass_redirection(codec,
4758
+ spec->bass_redirection_val);
4759
+ else
4760
+ err = ca0132_alt_surround_set_bass_redirection(codec, 0);
4761
+
4762
+ /* Unmute DSP now that we're done with output selection. */
4763
+ err = dspio_set_uint_param(codec, 0x96,
4764
+ SPEAKER_TUNING_MUTE, FLOAT_ZERO);
4765
+ if (err < 0)
4766
+ goto exit;
4767
+
4768
+ if (spec->cur_out_type == SPEAKER_OUT) {
4769
+ err = ca0132_alt_set_full_range_speaker(codec);
41284770 if (err < 0)
41294771 goto exit;
41304772 }
....@@ -4141,7 +4783,7 @@
41414783 to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
41424784 struct hda_jack_tbl *jack;
41434785
4144
- if (spec->use_alt_functions)
4786
+ if (ca0132_use_alt_functions(spec))
41454787 ca0132_alt_select_out(spec->codec);
41464788 else
41474789 ca0132_select_out(spec->codec);
....@@ -4155,7 +4797,6 @@
41554797
41564798 static void ca0132_set_dmic(struct hda_codec *codec, int enable);
41574799 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);
41594800 static void resume_mic1(struct hda_codec *codec, unsigned int oldval);
41604801 static int stop_mic1(struct hda_codec *codec);
41614802 static int ca0132_cvoice_switch_set(struct hda_codec *codec);
....@@ -4226,14 +4867,14 @@
42264867
42274868 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
42284869 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4229
- if (spec->quirk == QUIRK_R3DI)
4870
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
42304871 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
42314872
42324873
42334874 if (spec->in_enum_val == REAR_LINE_IN)
42344875 tmp = FLOAT_ZERO;
42354876 else {
4236
- if (spec->quirk == QUIRK_SBZ)
4877
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
42374878 tmp = FLOAT_THREE;
42384879 else
42394880 tmp = FLOAT_ONE;
....@@ -4245,7 +4886,7 @@
42454886 codec_dbg(codec, "%s: on.", __func__);
42464887 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000);
42474888 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000);
4248
- if (spec->quirk == QUIRK_R3DI)
4889
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
42494890 chipio_set_conn_rate(codec, 0x0F, SR_16_000);
42504891
42514892 if (spec->effects_switch[VOICE_FOCUS - EFFECT_START_NID])
....@@ -4341,15 +4982,31 @@
43414982
43424983 switch (spec->cur_mic_type) {
43434984 case REAR_MIC:
4344
- switch (spec->quirk) {
4985
+ switch (ca0132_quirk(spec)) {
43454986 case QUIRK_SBZ:
43464987 case QUIRK_R3D:
4347
- ca0132_mmio_gpio_set(codec, 0, false);
4988
+ ca0113_mmio_gpio_set(codec, 0, false);
4989
+ tmp = FLOAT_THREE;
4990
+ break;
4991
+ case QUIRK_ZXR:
43484992 tmp = FLOAT_THREE;
43494993 break;
43504994 case QUIRK_R3DI:
43514995 r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
43524996 tmp = FLOAT_ONE;
4997
+ break;
4998
+ case QUIRK_AE5:
4999
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
5000
+ tmp = FLOAT_THREE;
5001
+ break;
5002
+ case QUIRK_AE7:
5003
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
5004
+ tmp = FLOAT_THREE;
5005
+ chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
5006
+ SR_96_000);
5007
+ chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
5008
+ SR_96_000);
5009
+ dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
43535010 break;
43545011 default:
43555012 tmp = FLOAT_ONE;
....@@ -4358,60 +5015,95 @@
43585015
43595016 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
43605017 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4361
- if (spec->quirk == QUIRK_R3DI)
5018
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
43625019 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
43635020
43645021 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
43655022
43665023 chipio_set_stream_control(codec, 0x03, 1);
43675024 chipio_set_stream_control(codec, 0x04, 1);
4368
-
4369
- if (spec->quirk == QUIRK_SBZ) {
5025
+ switch (ca0132_quirk(spec)) {
5026
+ case QUIRK_SBZ:
43705027 chipio_write(codec, 0x18B098, 0x0000000C);
43715028 chipio_write(codec, 0x18B09C, 0x0000000C);
5029
+ break;
5030
+ case QUIRK_ZXR:
5031
+ chipio_write(codec, 0x18B098, 0x0000000C);
5032
+ chipio_write(codec, 0x18B09C, 0x000000CC);
5033
+ break;
5034
+ case QUIRK_AE5:
5035
+ chipio_write(codec, 0x18B098, 0x0000000C);
5036
+ chipio_write(codec, 0x18B09C, 0x0000004C);
5037
+ break;
5038
+ default:
5039
+ break;
43725040 }
43735041 ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
43745042 break;
43755043 case REAR_LINE_IN:
43765044 ca0132_mic_boost_set(codec, 0);
4377
- switch (spec->quirk) {
5045
+ switch (ca0132_quirk(spec)) {
43785046 case QUIRK_SBZ:
43795047 case QUIRK_R3D:
4380
- ca0132_mmio_gpio_set(codec, 0, false);
5048
+ ca0113_mmio_gpio_set(codec, 0, false);
43815049 break;
43825050 case QUIRK_R3DI:
43835051 r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
5052
+ break;
5053
+ case QUIRK_AE5:
5054
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
5055
+ break;
5056
+ case QUIRK_AE7:
5057
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
5058
+ chipio_set_conn_rate(codec, MEM_CONNID_MICIN2,
5059
+ SR_96_000);
5060
+ chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2,
5061
+ SR_96_000);
5062
+ dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO);
5063
+ break;
5064
+ default:
43845065 break;
43855066 }
43865067
43875068 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
43885069 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4389
- if (spec->quirk == QUIRK_R3DI)
5070
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
43905071 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
43915072
4392
- tmp = FLOAT_ZERO;
5073
+ if (ca0132_quirk(spec) == QUIRK_AE7)
5074
+ tmp = FLOAT_THREE;
5075
+ else
5076
+ tmp = FLOAT_ZERO;
43935077 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
43945078
4395
- if (spec->quirk == QUIRK_SBZ) {
5079
+ switch (ca0132_quirk(spec)) {
5080
+ case QUIRK_SBZ:
5081
+ case QUIRK_AE5:
43965082 chipio_write(codec, 0x18B098, 0x00000000);
43975083 chipio_write(codec, 0x18B09C, 0x00000000);
5084
+ break;
5085
+ default:
5086
+ break;
43985087 }
4399
-
44005088 chipio_set_stream_control(codec, 0x03, 1);
44015089 chipio_set_stream_control(codec, 0x04, 1);
44025090 break;
44035091 case FRONT_MIC:
4404
- switch (spec->quirk) {
5092
+ switch (ca0132_quirk(spec)) {
44055093 case QUIRK_SBZ:
44065094 case QUIRK_R3D:
4407
- ca0132_mmio_gpio_set(codec, 0, true);
4408
- ca0132_mmio_gpio_set(codec, 5, false);
5095
+ ca0113_mmio_gpio_set(codec, 0, true);
5096
+ ca0113_mmio_gpio_set(codec, 5, false);
44095097 tmp = FLOAT_THREE;
44105098 break;
44115099 case QUIRK_R3DI:
44125100 r3di_gpio_mic_set(codec, R3DI_FRONT_MIC);
44135101 tmp = FLOAT_ONE;
44145102 break;
5103
+ case QUIRK_AE5:
5104
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
5105
+ tmp = FLOAT_THREE;
5106
+ break;
44155107 default:
44165108 tmp = FLOAT_ONE;
44175109 break;
....@@ -4419,7 +5111,7 @@
44195111
44205112 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
44215113 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4422
- if (spec->quirk == QUIRK_R3DI)
5114
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
44235115 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
44245116
44255117 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
....@@ -4427,9 +5119,17 @@
44275119 chipio_set_stream_control(codec, 0x03, 1);
44285120 chipio_set_stream_control(codec, 0x04, 1);
44295121
4430
- if (spec->quirk == QUIRK_SBZ) {
5122
+ switch (ca0132_quirk(spec)) {
5123
+ case QUIRK_SBZ:
44315124 chipio_write(codec, 0x18B098, 0x0000000C);
44325125 chipio_write(codec, 0x18B09C, 0x000000CC);
5126
+ break;
5127
+ case QUIRK_AE5:
5128
+ chipio_write(codec, 0x18B098, 0x0000000C);
5129
+ chipio_write(codec, 0x18B09C, 0x0000004C);
5130
+ break;
5131
+ default:
5132
+ break;
44335133 }
44345134 ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
44355135 break;
....@@ -4438,7 +5138,6 @@
44385138
44395139 snd_hda_power_down_pm(codec);
44405140 return 0;
4441
-
44425141 }
44435142
44445143 /*
....@@ -4497,7 +5196,7 @@
44975196 static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val)
44985197 {
44995198 struct ca0132_spec *spec = codec->spec;
4500
- unsigned int on, tmp;
5199
+ unsigned int on, tmp, channel_cfg;
45015200 int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
45025201 int err = 0;
45035202 int idx = nid - EFFECT_START_NID;
....@@ -4510,6 +5209,12 @@
45105209 /* if PE if off, turn off out effects. */
45115210 if (!spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
45125211 val = 0;
5212
+ if (spec->cur_out_type == SPEAKER_OUT && nid == X_BASS) {
5213
+ channel_cfg = spec->channel_cfg_val;
5214
+ if (channel_cfg != SPEAKER_CHANNELS_2_0 &&
5215
+ channel_cfg != SPEAKER_CHANNELS_4_0)
5216
+ val = 0;
5217
+ }
45135218 }
45145219
45155220 /* for in effect, qualify with CrystalVoice */
....@@ -4523,7 +5228,7 @@
45235228 val = 0;
45245229
45255230 /* If Voice Focus on SBZ, set to two channel. */
4526
- if ((nid == VOICE_FOCUS) && (spec->use_pci_mmio)
5231
+ if ((nid == VOICE_FOCUS) && ca0132_use_pci_mmio(spec)
45275232 && (spec->cur_mic_type != REAR_LINE_IN)) {
45285233 if (spec->effects_switch[CRYSTAL_VOICE -
45295234 EFFECT_START_NID]) {
....@@ -4542,7 +5247,7 @@
45425247 * For SBZ noise reduction, there's an extra command
45435248 * to module ID 0x47. No clue why.
45445249 */
4545
- if ((nid == NOISE_REDUCTION) && (spec->use_pci_mmio)
5250
+ if ((nid == NOISE_REDUCTION) && ca0132_use_pci_mmio(spec)
45465251 && (spec->cur_mic_type != REAR_LINE_IN)) {
45475252 if (spec->effects_switch[CRYSTAL_VOICE -
45485253 EFFECT_START_NID]) {
....@@ -4558,7 +5263,7 @@
45585263 }
45595264
45605265 /* If rear line in disable effects. */
4561
- if (spec->use_alt_functions &&
5266
+ if (ca0132_use_alt_functions(spec) &&
45625267 spec->in_enum_val == REAR_LINE_IN)
45635268 val = 0;
45645269 }
....@@ -4588,7 +5293,7 @@
45885293 codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n",
45895294 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]);
45905295
4591
- if (spec->use_alt_functions)
5296
+ if (ca0132_use_alt_functions(spec))
45925297 ca0132_alt_select_out(codec);
45935298
45945299 i = OUT_EFFECT_START_NID - EFFECT_START_NID;
....@@ -4648,7 +5353,7 @@
46485353
46495354 /* set correct vipsource */
46505355 oldval = stop_mic1(codec);
4651
- if (spec->use_alt_functions)
5356
+ if (ca0132_use_alt_functions(spec))
46525357 ret |= ca0132_alt_set_vipsource(codec, 1);
46535358 else
46545359 ret |= ca0132_set_vipsource(codec, 1);
....@@ -4681,6 +5386,27 @@
46815386 return ret;
46825387 }
46835388
5389
+static int ae5_headphone_gain_set(struct hda_codec *codec, long val)
5390
+{
5391
+ unsigned int i;
5392
+
5393
+ for (i = 0; i < 4; i++)
5394
+ ca0113_mmio_command_set(codec, 0x48, 0x11 + i,
5395
+ ae5_headphone_gain_presets[val].vals[i]);
5396
+ return 0;
5397
+}
5398
+
5399
+/*
5400
+ * gpio pin 1 is a relay that switches on/off, apparently setting the headphone
5401
+ * amplifier to handle a 600 ohm load.
5402
+ */
5403
+static int zxr_headphone_gain_set(struct hda_codec *codec, long val)
5404
+{
5405
+ ca0113_mmio_gpio_set(codec, 1, val);
5406
+
5407
+ return 0;
5408
+}
5409
+
46845410 static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol,
46855411 struct snd_ctl_elem_value *ucontrol)
46865412 {
....@@ -4696,7 +5422,7 @@
46965422 auto_jack =
46975423 spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
46985424 if (!auto_jack) {
4699
- if (spec->use_alt_functions)
5425
+ if (ca0132_use_alt_functions(spec))
47005426 ca0132_alt_select_out(codec);
47015427 else
47025428 ca0132_select_out(codec);
....@@ -4713,7 +5439,7 @@
47135439 }
47145440
47155441 if (nid == VNID_HP_ASEL) {
4716
- if (spec->use_alt_functions)
5442
+ if (ca0132_use_alt_functions(spec))
47175443 ca0132_alt_select_out(codec);
47185444 else
47195445 ca0132_select_out(codec);
....@@ -4744,6 +5470,18 @@
47445470 return ret;
47455471 }
47465472 /* End of control change helpers. */
5473
+
5474
+static void ca0132_alt_bass_redirection_xover_set(struct hda_codec *codec,
5475
+ long idx)
5476
+{
5477
+ snd_hda_power_up(codec);
5478
+
5479
+ dspio_set_param(codec, 0x96, 0x20, SPEAKER_BASS_REDIRECT_XOVER_FREQ,
5480
+ &(float_xbass_xover_lookup[idx]), sizeof(unsigned int));
5481
+
5482
+ snd_hda_power_down(codec);
5483
+}
5484
+
47475485 /*
47485486 * Below I've added controls to mess with the effect levels, I've only enabled
47495487 * them on the Sound Blaster Z, but they would probably also work on the
....@@ -4752,6 +5490,7 @@
47525490 */
47535491
47545492 /* Sets DSP effect level from the sliders above the controls */
5493
+
47555494 static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid,
47565495 const unsigned int *lookup, int idx)
47575496 {
....@@ -4797,8 +5536,13 @@
47975536 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
47985537 struct ca0132_spec *spec = codec->spec;
47995538 long *valp = ucontrol->value.integer.value;
5539
+ hda_nid_t nid = get_amp_nid(kcontrol);
48005540
4801
- *valp = spec->xbass_xover_freq;
5541
+ if (nid == BASS_REDIRECTION_XOVER)
5542
+ *valp = spec->bass_redirect_xover_freq;
5543
+ else
5544
+ *valp = spec->xbass_xover_freq;
5545
+
48025546 return 0;
48035547 }
48045548
....@@ -4852,16 +5596,25 @@
48525596 struct ca0132_spec *spec = codec->spec;
48535597 hda_nid_t nid = get_amp_nid(kcontrol);
48545598 long *valp = ucontrol->value.integer.value;
5599
+ long *cur_val;
48555600 int idx;
48565601
5602
+ if (nid == BASS_REDIRECTION_XOVER)
5603
+ cur_val = &spec->bass_redirect_xover_freq;
5604
+ else
5605
+ cur_val = &spec->xbass_xover_freq;
5606
+
48575607 /* any change? */
4858
- if (spec->xbass_xover_freq == *valp)
5608
+ if (*cur_val == *valp)
48595609 return 0;
48605610
4861
- spec->xbass_xover_freq = *valp;
5611
+ *cur_val = *valp;
48625612
48635613 idx = *valp;
4864
- ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx);
5614
+ if (nid == BASS_REDIRECTION_XOVER)
5615
+ ca0132_alt_bass_redirection_xover_set(codec, *cur_val);
5616
+ else
5617
+ ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx);
48655618
48665619 return 0;
48675620 }
....@@ -4945,6 +5698,112 @@
49455698 return 1;
49465699 }
49475700
5701
+/*
5702
+ * Sound BlasterX AE-5 Headphone Gain Controls.
5703
+ */
5704
+#define AE5_HEADPHONE_GAIN_MAX 3
5705
+static int ae5_headphone_gain_info(struct snd_kcontrol *kcontrol,
5706
+ struct snd_ctl_elem_info *uinfo)
5707
+{
5708
+ char *sfx = " Ohms)";
5709
+ char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
5710
+
5711
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5712
+ uinfo->count = 1;
5713
+ uinfo->value.enumerated.items = AE5_HEADPHONE_GAIN_MAX;
5714
+ if (uinfo->value.enumerated.item >= AE5_HEADPHONE_GAIN_MAX)
5715
+ uinfo->value.enumerated.item = AE5_HEADPHONE_GAIN_MAX - 1;
5716
+ sprintf(namestr, "%s %s",
5717
+ ae5_headphone_gain_presets[uinfo->value.enumerated.item].name,
5718
+ sfx);
5719
+ strcpy(uinfo->value.enumerated.name, namestr);
5720
+ return 0;
5721
+}
5722
+
5723
+static int ae5_headphone_gain_get(struct snd_kcontrol *kcontrol,
5724
+ struct snd_ctl_elem_value *ucontrol)
5725
+{
5726
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5727
+ struct ca0132_spec *spec = codec->spec;
5728
+
5729
+ ucontrol->value.enumerated.item[0] = spec->ae5_headphone_gain_val;
5730
+ return 0;
5731
+}
5732
+
5733
+static int ae5_headphone_gain_put(struct snd_kcontrol *kcontrol,
5734
+ struct snd_ctl_elem_value *ucontrol)
5735
+{
5736
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5737
+ struct ca0132_spec *spec = codec->spec;
5738
+ int sel = ucontrol->value.enumerated.item[0];
5739
+ unsigned int items = AE5_HEADPHONE_GAIN_MAX;
5740
+
5741
+ if (sel >= items)
5742
+ return 0;
5743
+
5744
+ codec_dbg(codec, "ae5_headphone_gain: boost=%d\n",
5745
+ sel);
5746
+
5747
+ spec->ae5_headphone_gain_val = sel;
5748
+
5749
+ if (spec->out_enum_val == HEADPHONE_OUT)
5750
+ ae5_headphone_gain_set(codec, spec->ae5_headphone_gain_val);
5751
+
5752
+ return 1;
5753
+}
5754
+
5755
+/*
5756
+ * Sound BlasterX AE-5 sound filter enumerated control.
5757
+ */
5758
+#define AE5_SOUND_FILTER_MAX 3
5759
+
5760
+static int ae5_sound_filter_info(struct snd_kcontrol *kcontrol,
5761
+ struct snd_ctl_elem_info *uinfo)
5762
+{
5763
+ char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
5764
+
5765
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5766
+ uinfo->count = 1;
5767
+ uinfo->value.enumerated.items = AE5_SOUND_FILTER_MAX;
5768
+ if (uinfo->value.enumerated.item >= AE5_SOUND_FILTER_MAX)
5769
+ uinfo->value.enumerated.item = AE5_SOUND_FILTER_MAX - 1;
5770
+ sprintf(namestr, "%s",
5771
+ ae5_filter_presets[uinfo->value.enumerated.item].name);
5772
+ strcpy(uinfo->value.enumerated.name, namestr);
5773
+ return 0;
5774
+}
5775
+
5776
+static int ae5_sound_filter_get(struct snd_kcontrol *kcontrol,
5777
+ struct snd_ctl_elem_value *ucontrol)
5778
+{
5779
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5780
+ struct ca0132_spec *spec = codec->spec;
5781
+
5782
+ ucontrol->value.enumerated.item[0] = spec->ae5_filter_val;
5783
+ return 0;
5784
+}
5785
+
5786
+static int ae5_sound_filter_put(struct snd_kcontrol *kcontrol,
5787
+ struct snd_ctl_elem_value *ucontrol)
5788
+{
5789
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5790
+ struct ca0132_spec *spec = codec->spec;
5791
+ int sel = ucontrol->value.enumerated.item[0];
5792
+ unsigned int items = AE5_SOUND_FILTER_MAX;
5793
+
5794
+ if (sel >= items)
5795
+ return 0;
5796
+
5797
+ codec_dbg(codec, "ae5_sound_filter: %s\n",
5798
+ ae5_filter_presets[sel].name);
5799
+
5800
+ spec->ae5_filter_val = sel;
5801
+
5802
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07,
5803
+ ae5_filter_presets[sel].val);
5804
+
5805
+ return 1;
5806
+}
49485807
49495808 /*
49505809 * Input Select Control for alternative ca0132 codecs. This exists because
....@@ -4982,6 +5841,13 @@
49825841 int sel = ucontrol->value.enumerated.item[0];
49835842 unsigned int items = IN_SRC_NUM_OF_INPUTS;
49845843
5844
+ /*
5845
+ * The AE-7 has no front microphone, so limit items to 2: rear mic and
5846
+ * line-in.
5847
+ */
5848
+ if (ca0132_quirk(spec) == QUIRK_AE7)
5849
+ items = 2;
5850
+
49855851 if (sel >= items)
49865852 return 0;
49875853
....@@ -5005,7 +5871,7 @@
50055871 if (uinfo->value.enumerated.item >= NUM_OF_OUTPUTS)
50065872 uinfo->value.enumerated.item = NUM_OF_OUTPUTS - 1;
50075873 strcpy(uinfo->value.enumerated.name,
5008
- alt_out_presets[uinfo->value.enumerated.item].name);
5874
+ out_type_str[uinfo->value.enumerated.item]);
50095875 return 0;
50105876 }
50115877
....@@ -5032,13 +5898,61 @@
50325898 return 0;
50335899
50345900 codec_dbg(codec, "ca0132_alt_output_select: sel=%d, preset=%s\n",
5035
- sel, alt_out_presets[sel].name);
5901
+ sel, out_type_str[sel]);
50365902
50375903 spec->out_enum_val = sel;
50385904
50395905 auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
50405906
50415907 if (!auto_jack)
5908
+ ca0132_alt_select_out(codec);
5909
+
5910
+ return 1;
5911
+}
5912
+
5913
+/* Select surround output type: 2.1, 4.0, 4.1, or 5.1. */
5914
+static int ca0132_alt_speaker_channel_cfg_get_info(struct snd_kcontrol *kcontrol,
5915
+ struct snd_ctl_elem_info *uinfo)
5916
+{
5917
+ unsigned int items = SPEAKER_CHANNEL_CFG_COUNT;
5918
+
5919
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5920
+ uinfo->count = 1;
5921
+ uinfo->value.enumerated.items = items;
5922
+ if (uinfo->value.enumerated.item >= items)
5923
+ uinfo->value.enumerated.item = items - 1;
5924
+ strcpy(uinfo->value.enumerated.name,
5925
+ speaker_channel_cfgs[uinfo->value.enumerated.item].name);
5926
+ return 0;
5927
+}
5928
+
5929
+static int ca0132_alt_speaker_channel_cfg_get(struct snd_kcontrol *kcontrol,
5930
+ struct snd_ctl_elem_value *ucontrol)
5931
+{
5932
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5933
+ struct ca0132_spec *spec = codec->spec;
5934
+
5935
+ ucontrol->value.enumerated.item[0] = spec->channel_cfg_val;
5936
+ return 0;
5937
+}
5938
+
5939
+static int ca0132_alt_speaker_channel_cfg_put(struct snd_kcontrol *kcontrol,
5940
+ struct snd_ctl_elem_value *ucontrol)
5941
+{
5942
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5943
+ struct ca0132_spec *spec = codec->spec;
5944
+ int sel = ucontrol->value.enumerated.item[0];
5945
+ unsigned int items = SPEAKER_CHANNEL_CFG_COUNT;
5946
+
5947
+ if (sel >= items)
5948
+ return 0;
5949
+
5950
+ codec_dbg(codec, "ca0132_alt_speaker_channels: sel=%d, channels=%s\n",
5951
+ sel, speaker_channel_cfgs[sel].name);
5952
+
5953
+ spec->channel_cfg_val = sel;
5954
+
5955
+ if (spec->out_enum_val == SPEAKER_OUT)
50425956 ca0132_alt_select_out(codec);
50435957
50445958 return 1;
....@@ -5265,6 +6179,21 @@
52656179 return 0;
52666180 }
52676181
6182
+ if (nid == ZXR_HEADPHONE_GAIN) {
6183
+ *valp = spec->zxr_gain_set;
6184
+ return 0;
6185
+ }
6186
+
6187
+ if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) {
6188
+ *valp = spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT];
6189
+ return 0;
6190
+ }
6191
+
6192
+ if (nid == BASS_REDIRECTION) {
6193
+ *valp = spec->bass_redirection_val;
6194
+ return 0;
6195
+ }
6196
+
52686197 return 0;
52696198 }
52706199
....@@ -5321,7 +6250,7 @@
53216250 /* mic boost */
53226251 if (nid == spec->input_pins[0]) {
53236252 spec->cur_mic_boost = *valp;
5324
- if (spec->use_alt_functions) {
6253
+ if (ca0132_use_alt_functions(spec)) {
53256254 if (spec->in_enum_val != REAR_LINE_IN)
53266255 changed = ca0132_mic_boost_set(codec, *valp);
53276256 } else {
....@@ -5331,6 +6260,32 @@
53316260 }
53326261
53336262 goto exit;
6263
+ }
6264
+
6265
+ if (nid == ZXR_HEADPHONE_GAIN) {
6266
+ spec->zxr_gain_set = *valp;
6267
+ if (spec->cur_out_type == HEADPHONE_OUT)
6268
+ changed = zxr_headphone_gain_set(codec, *valp);
6269
+ else
6270
+ changed = 0;
6271
+
6272
+ goto exit;
6273
+ }
6274
+
6275
+ if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) {
6276
+ spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT] = *valp;
6277
+ if (spec->cur_out_type == SPEAKER_OUT)
6278
+ ca0132_alt_set_full_range_speaker(codec);
6279
+
6280
+ changed = 0;
6281
+ }
6282
+
6283
+ if (nid == BASS_REDIRECTION) {
6284
+ spec->bass_redirection_val = *valp;
6285
+ if (spec->cur_out_type == SPEAKER_OUT)
6286
+ ca0132_alt_surround_set_bass_redirection(codec, *valp);
6287
+
6288
+ changed = 0;
53346289 }
53356290
53366291 exit:
....@@ -5491,7 +6446,7 @@
54916446 int ch = get_amp_channels(kcontrol);
54926447 long *valp = ucontrol->value.integer.value;
54936448 hda_nid_t vnid = 0;
5494
- int changed = 1;
6449
+ int changed;
54956450
54966451 switch (nid) {
54976452 case 0x02:
....@@ -5607,7 +6562,7 @@
56076562 /* If using alt_controls, add FX: prefix. But, don't add FX:
56086563 * prefix to OutFX or InFX enable controls.
56096564 */
5610
- if ((spec->use_alt_controls) && (nid <= IN_EFFECT_END_NID))
6565
+ if (ca0132_use_alt_controls(spec) && (nid <= IN_EFFECT_END_NID))
56116566 sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]);
56126567 else
56136568 sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
....@@ -5674,6 +6629,81 @@
56746629 }
56756630
56766631 /*
6632
+ * Add a control for selecting channel count on speaker output. Setting this
6633
+ * allows the DSP to do bass redirection and channel upmixing on surround
6634
+ * configurations.
6635
+ */
6636
+static int ca0132_alt_add_speaker_channel_cfg_enum(struct hda_codec *codec)
6637
+{
6638
+ struct snd_kcontrol_new knew =
6639
+ HDA_CODEC_MUTE_MONO("Surround Channel Config",
6640
+ SPEAKER_CHANNEL_CFG_ENUM, 1, 0, HDA_OUTPUT);
6641
+ knew.info = ca0132_alt_speaker_channel_cfg_get_info;
6642
+ knew.get = ca0132_alt_speaker_channel_cfg_get;
6643
+ knew.put = ca0132_alt_speaker_channel_cfg_put;
6644
+ return snd_hda_ctl_add(codec, SPEAKER_CHANNEL_CFG_ENUM,
6645
+ snd_ctl_new1(&knew, codec));
6646
+}
6647
+
6648
+/*
6649
+ * Full range front stereo and rear surround switches. When these are set to
6650
+ * full range, the lower frequencies from these channels are no longer
6651
+ * redirected to the LFE channel.
6652
+ */
6653
+static int ca0132_alt_add_front_full_range_switch(struct hda_codec *codec)
6654
+{
6655
+ struct snd_kcontrol_new knew =
6656
+ CA0132_CODEC_MUTE_MONO("Full-Range Front Speakers",
6657
+ SPEAKER_FULL_RANGE_FRONT, 1, HDA_OUTPUT);
6658
+
6659
+ return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_FRONT,
6660
+ snd_ctl_new1(&knew, codec));
6661
+}
6662
+
6663
+static int ca0132_alt_add_rear_full_range_switch(struct hda_codec *codec)
6664
+{
6665
+ struct snd_kcontrol_new knew =
6666
+ CA0132_CODEC_MUTE_MONO("Full-Range Rear Speakers",
6667
+ SPEAKER_FULL_RANGE_REAR, 1, HDA_OUTPUT);
6668
+
6669
+ return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_REAR,
6670
+ snd_ctl_new1(&knew, codec));
6671
+}
6672
+
6673
+/*
6674
+ * Bass redirection redirects audio below the crossover frequency to the LFE
6675
+ * channel on speakers that are set as not being full-range. On configurations
6676
+ * without an LFE channel, it does nothing. Bass redirection seems to be the
6677
+ * replacement for X-Bass on configurations with an LFE channel.
6678
+ */
6679
+static int ca0132_alt_add_bass_redirection_crossover(struct hda_codec *codec)
6680
+{
6681
+ const char *namestr = "Bass Redirection Crossover";
6682
+ struct snd_kcontrol_new knew =
6683
+ HDA_CODEC_VOLUME_MONO(namestr, BASS_REDIRECTION_XOVER, 1, 0,
6684
+ HDA_OUTPUT);
6685
+
6686
+ knew.tlv.c = NULL;
6687
+ knew.info = ca0132_alt_xbass_xover_slider_info;
6688
+ knew.get = ca0132_alt_xbass_xover_slider_ctl_get;
6689
+ knew.put = ca0132_alt_xbass_xover_slider_put;
6690
+
6691
+ return snd_hda_ctl_add(codec, BASS_REDIRECTION_XOVER,
6692
+ snd_ctl_new1(&knew, codec));
6693
+}
6694
+
6695
+static int ca0132_alt_add_bass_redirection_switch(struct hda_codec *codec)
6696
+{
6697
+ const char *namestr = "Bass Redirection";
6698
+ struct snd_kcontrol_new knew =
6699
+ CA0132_CODEC_MUTE_MONO(namestr, BASS_REDIRECTION, 1,
6700
+ HDA_OUTPUT);
6701
+
6702
+ return snd_hda_ctl_add(codec, BASS_REDIRECTION,
6703
+ snd_ctl_new1(&knew, codec));
6704
+}
6705
+
6706
+/*
56776707 * Create an Input Source enumerated control for the alternate ca0132 codecs
56786708 * because the front microphone has no auto-detect, and Line-in has to be set
56796709 * somehow.
....@@ -5708,10 +6738,54 @@
57086738 }
57096739
57106740 /*
5711
- * Need to create slave controls for the alternate codecs that have surround
6741
+ * Add headphone gain enumerated control for the AE-5. This switches between
6742
+ * three modes, low, medium, and high. When non-headphone outputs are selected,
6743
+ * it is automatically set to high. This is the same behavior as Windows.
6744
+ */
6745
+static int ae5_add_headphone_gain_enum(struct hda_codec *codec)
6746
+{
6747
+ struct snd_kcontrol_new knew =
6748
+ HDA_CODEC_MUTE_MONO("AE-5: Headphone Gain",
6749
+ AE5_HEADPHONE_GAIN_ENUM, 1, 0, HDA_OUTPUT);
6750
+ knew.info = ae5_headphone_gain_info;
6751
+ knew.get = ae5_headphone_gain_get;
6752
+ knew.put = ae5_headphone_gain_put;
6753
+ return snd_hda_ctl_add(codec, AE5_HEADPHONE_GAIN_ENUM,
6754
+ snd_ctl_new1(&knew, codec));
6755
+}
6756
+
6757
+/*
6758
+ * Add sound filter enumerated control for the AE-5. This adds three different
6759
+ * settings: Slow Roll Off, Minimum Phase, and Fast Roll Off. From what I've
6760
+ * read into it, it changes the DAC's interpolation filter.
6761
+ */
6762
+static int ae5_add_sound_filter_enum(struct hda_codec *codec)
6763
+{
6764
+ struct snd_kcontrol_new knew =
6765
+ HDA_CODEC_MUTE_MONO("AE-5: Sound Filter",
6766
+ AE5_SOUND_FILTER_ENUM, 1, 0, HDA_OUTPUT);
6767
+ knew.info = ae5_sound_filter_info;
6768
+ knew.get = ae5_sound_filter_get;
6769
+ knew.put = ae5_sound_filter_put;
6770
+ return snd_hda_ctl_add(codec, AE5_SOUND_FILTER_ENUM,
6771
+ snd_ctl_new1(&knew, codec));
6772
+}
6773
+
6774
+static int zxr_add_headphone_gain_switch(struct hda_codec *codec)
6775
+{
6776
+ struct snd_kcontrol_new knew =
6777
+ CA0132_CODEC_MUTE_MONO("ZxR: 600 Ohm Gain",
6778
+ ZXR_HEADPHONE_GAIN, 1, HDA_OUTPUT);
6779
+
6780
+ return snd_hda_ctl_add(codec, ZXR_HEADPHONE_GAIN,
6781
+ snd_ctl_new1(&knew, codec));
6782
+}
6783
+
6784
+/*
6785
+ * Need to create follower controls for the alternate codecs that have surround
57126786 * capabilities.
57136787 */
5714
-static const char * const ca0132_alt_slave_pfxs[] = {
6788
+static const char * const ca0132_alt_follower_pfxs[] = {
57156789 "Front", "Surround", "Center", "LFE", NULL,
57166790 };
57176791
....@@ -5839,18 +6913,19 @@
58396913 if (err < 0)
58406914 return err;
58416915 }
5842
- /* Setup vmaster with surround slaves for desktop ca0132 devices */
5843
- if (spec->use_alt_functions) {
6916
+ /* Setup vmaster with surround followers for desktop ca0132 devices */
6917
+ if (ca0132_use_alt_functions(spec)) {
58446918 snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT,
58456919 spec->tlv);
58466920 snd_hda_add_vmaster(codec, "Master Playback Volume",
5847
- spec->tlv, ca0132_alt_slave_pfxs,
6921
+ spec->tlv, ca0132_alt_follower_pfxs,
58486922 "Playback Volume");
58496923 err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
5850
- NULL, ca0132_alt_slave_pfxs,
6924
+ NULL, ca0132_alt_follower_pfxs,
58516925 "Playback Switch",
58526926 true, &spec->vmaster_mute.sw_kctl);
5853
-
6927
+ if (err < 0)
6928
+ return err;
58546929 }
58556930
58566931 /* Add in and out effects controls.
....@@ -5859,7 +6934,7 @@
58596934 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
58606935 for (i = 0; i < num_fx; i++) {
58616936 /* Desktop cards break if Echo Cancellation is used. */
5862
- if (spec->use_pci_mmio) {
6937
+ if (ca0132_use_pci_mmio(spec)) {
58636938 if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID +
58646939 OUT_EFFECTS_COUNT))
58656940 continue;
....@@ -5876,9 +6951,15 @@
58766951 * EQ presets, and Smart Volume presets. Also, change names to add FX
58776952 * prefix, and change PlayEnhancement and CrystalVoice to match.
58786953 */
5879
- if (spec->use_alt_controls) {
5880
- ca0132_alt_add_svm_enum(codec);
5881
- add_ca0132_alt_eq_presets(codec);
6954
+ if (ca0132_use_alt_controls(spec)) {
6955
+ err = ca0132_alt_add_svm_enum(codec);
6956
+ if (err < 0)
6957
+ return err;
6958
+
6959
+ err = add_ca0132_alt_eq_presets(codec);
6960
+ if (err < 0)
6961
+ return err;
6962
+
58826963 err = add_fx_switch(codec, PLAY_ENHANCEMENT,
58836964 "Enable OutFX", 0);
58846965 if (err < 0)
....@@ -5915,18 +6996,67 @@
59156996 if (err < 0)
59166997 return err;
59176998 }
5918
- add_voicefx(codec);
6999
+ err = add_voicefx(codec);
7000
+ if (err < 0)
7001
+ return err;
59197002
59207003 /*
59217004 * If the codec uses alt_functions, you need the enumerated controls
59227005 * to select the new outputs and inputs, plus add the new mic boost
59237006 * setting control.
59247007 */
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);
7008
+ if (ca0132_use_alt_functions(spec)) {
7009
+ err = ca0132_alt_add_output_enum(codec);
7010
+ if (err < 0)
7011
+ return err;
7012
+ err = ca0132_alt_add_speaker_channel_cfg_enum(codec);
7013
+ if (err < 0)
7014
+ return err;
7015
+ err = ca0132_alt_add_front_full_range_switch(codec);
7016
+ if (err < 0)
7017
+ return err;
7018
+ err = ca0132_alt_add_rear_full_range_switch(codec);
7019
+ if (err < 0)
7020
+ return err;
7021
+ err = ca0132_alt_add_bass_redirection_crossover(codec);
7022
+ if (err < 0)
7023
+ return err;
7024
+ err = ca0132_alt_add_bass_redirection_switch(codec);
7025
+ if (err < 0)
7026
+ return err;
7027
+ err = ca0132_alt_add_mic_boost_enum(codec);
7028
+ if (err < 0)
7029
+ return err;
7030
+ /*
7031
+ * ZxR only has microphone input, there is no front panel
7032
+ * header on the card, and aux-in is handled by the DBPro board.
7033
+ */
7034
+ if (ca0132_quirk(spec) != QUIRK_ZXR) {
7035
+ err = ca0132_alt_add_input_enum(codec);
7036
+ if (err < 0)
7037
+ return err;
7038
+ }
59297039 }
7040
+
7041
+ switch (ca0132_quirk(spec)) {
7042
+ case QUIRK_AE5:
7043
+ case QUIRK_AE7:
7044
+ err = ae5_add_headphone_gain_enum(codec);
7045
+ if (err < 0)
7046
+ return err;
7047
+ err = ae5_add_sound_filter_enum(codec);
7048
+ if (err < 0)
7049
+ return err;
7050
+ break;
7051
+ case QUIRK_ZXR:
7052
+ err = zxr_add_headphone_gain_switch(codec);
7053
+ if (err < 0)
7054
+ return err;
7055
+ break;
7056
+ default:
7057
+ break;
7058
+ }
7059
+
59307060 #ifdef ENABLE_TUNING_CONTROLS
59317061 add_tuning_ctls(codec);
59327062 #endif
....@@ -5952,8 +7082,29 @@
59527082 return err;
59537083 }
59547084
5955
- if (spec->use_alt_functions)
7085
+ if (ca0132_use_alt_functions(spec))
59567086 ca0132_alt_add_chmap_ctls(codec);
7087
+
7088
+ return 0;
7089
+}
7090
+
7091
+static int dbpro_build_controls(struct hda_codec *codec)
7092
+{
7093
+ struct ca0132_spec *spec = codec->spec;
7094
+ int err = 0;
7095
+
7096
+ if (spec->dig_out) {
7097
+ err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
7098
+ spec->dig_out);
7099
+ if (err < 0)
7100
+ return err;
7101
+ }
7102
+
7103
+ if (spec->dig_in) {
7104
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
7105
+ if (err < 0)
7106
+ return err;
7107
+ }
59577108
59587109 return 0;
59597110 }
....@@ -6009,7 +7160,7 @@
60097160 info = snd_hda_codec_pcm_new(codec, "CA0132 Analog");
60107161 if (!info)
60117162 return -ENOMEM;
6012
- if (spec->use_alt_functions) {
7163
+ if (ca0132_use_alt_functions(spec)) {
60137164 info->own_chmap = true;
60147165 info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap
60157166 = ca0132_alt_chmaps;
....@@ -6023,7 +7174,7 @@
60237174 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
60247175
60257176 /* With the DSP enabled, desktops don't use this ADC. */
6026
- if (!spec->use_alt_functions) {
7177
+ if (!ca0132_use_alt_functions(spec)) {
60277178 info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
60287179 if (!info)
60297180 return -ENOMEM;
....@@ -6039,6 +7190,40 @@
60397190 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
60407191 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
60417192 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[2];
7193
+
7194
+ if (!spec->dig_out && !spec->dig_in)
7195
+ return 0;
7196
+
7197
+ info = snd_hda_codec_pcm_new(codec, "CA0132 Digital");
7198
+ if (!info)
7199
+ return -ENOMEM;
7200
+ info->pcm_type = HDA_PCM_TYPE_SPDIF;
7201
+ if (spec->dig_out) {
7202
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
7203
+ ca0132_pcm_digital_playback;
7204
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
7205
+ }
7206
+ if (spec->dig_in) {
7207
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] =
7208
+ ca0132_pcm_digital_capture;
7209
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
7210
+ }
7211
+
7212
+ return 0;
7213
+}
7214
+
7215
+static int dbpro_build_pcms(struct hda_codec *codec)
7216
+{
7217
+ struct ca0132_spec *spec = codec->spec;
7218
+ struct hda_pcm *info;
7219
+
7220
+ info = snd_hda_codec_pcm_new(codec, "CA0132 Alt Analog");
7221
+ if (!info)
7222
+ return -ENOMEM;
7223
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
7224
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
7225
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
7226
+
60427227
60437228 if (!spec->dig_out && !spec->dig_in)
60447229 return 0;
....@@ -6187,7 +7372,7 @@
61877372 * Bit 6: set to select Data2, clear for Data1
61887373 * Bit 7: set to enable DMic, clear for AMic
61897374 */
6190
- if (spec->quirk == QUIRK_ALIENWARE_M17XR4)
7375
+ if (ca0132_quirk(spec) == QUIRK_ALIENWARE_M17XR4)
61917376 val = 0x33;
61927377 else
61937378 val = 0x23;
....@@ -6241,69 +7426,110 @@
62417426 }
62427427
62437428 /*
6244
- * Recon3D r3d_setup_defaults sub functions.
7429
+ * Default speaker tuning values setup for alternative codecs.
62457430 */
7431
+static const unsigned int sbz_default_delay_values[] = {
7432
+ /* Non-zero values are floating point 0.000198. */
7433
+ 0x394f9e38, 0x394f9e38, 0x00000000, 0x00000000, 0x00000000, 0x00000000
7434
+};
62467435
6247
-static void r3d_dsp_scp_startup(struct hda_codec *codec)
7436
+static const unsigned int zxr_default_delay_values[] = {
7437
+ /* Non-zero values are floating point 0.000220. */
7438
+ 0x00000000, 0x00000000, 0x3966afcd, 0x3966afcd, 0x3966afcd, 0x3966afcd
7439
+};
7440
+
7441
+static const unsigned int ae5_default_delay_values[] = {
7442
+ /* Non-zero values are floating point 0.000100. */
7443
+ 0x00000000, 0x00000000, 0x38d1b717, 0x38d1b717, 0x38d1b717, 0x38d1b717
7444
+};
7445
+
7446
+/*
7447
+ * If we never change these, probably only need them on initialization.
7448
+ */
7449
+static void ca0132_alt_init_speaker_tuning(struct hda_codec *codec)
62487450 {
6249
- unsigned int tmp;
7451
+ struct ca0132_spec *spec = codec->spec;
7452
+ unsigned int i, tmp, start_req, end_req;
7453
+ const unsigned int *values;
62507454
6251
- tmp = 0x00000000;
6252
- dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7455
+ switch (ca0132_quirk(spec)) {
7456
+ case QUIRK_SBZ:
7457
+ values = sbz_default_delay_values;
7458
+ break;
7459
+ case QUIRK_ZXR:
7460
+ values = zxr_default_delay_values;
7461
+ break;
7462
+ case QUIRK_AE5:
7463
+ case QUIRK_AE7:
7464
+ values = ae5_default_delay_values;
7465
+ break;
7466
+ default:
7467
+ values = sbz_default_delay_values;
7468
+ break;
7469
+ }
62537470
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);
62847471 tmp = FLOAT_ZERO;
6285
- dspio_set_uint_param(codec, 0x80, 0x01, tmp);
7472
+ dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_ENABLE_CENTER_EQ, tmp);
7473
+
7474
+ start_req = SPEAKER_TUNING_FRONT_LEFT_VOL_LEVEL;
7475
+ end_req = SPEAKER_TUNING_REAR_RIGHT_VOL_LEVEL;
7476
+ for (i = start_req; i < end_req + 1; i++)
7477
+ dspio_set_uint_param(codec, 0x96, i, tmp);
7478
+
7479
+ start_req = SPEAKER_TUNING_FRONT_LEFT_INVERT;
7480
+ end_req = SPEAKER_TUNING_REAR_RIGHT_INVERT;
7481
+ for (i = start_req; i < end_req + 1; i++)
7482
+ dspio_set_uint_param(codec, 0x96, i, tmp);
7483
+
7484
+
7485
+ for (i = 0; i < 6; i++)
7486
+ dspio_set_uint_param(codec, 0x96,
7487
+ SPEAKER_TUNING_FRONT_LEFT_DELAY + i, values[i]);
62867488 }
62877489
62887490 /*
6289
- * Initialize Sound Blaster Z analog microphones.
7491
+ * Creates a dummy stream to bind the output to. This seems to have to be done
7492
+ * after changing the main outputs source and destination streams.
62907493 */
6291
-static void sbz_init_analog_mics(struct hda_codec *codec)
7494
+static void ca0132_alt_create_dummy_stream(struct hda_codec *codec)
62927495 {
7496
+ struct ca0132_spec *spec = codec->spec;
7497
+ unsigned int stream_format;
7498
+
7499
+ stream_format = snd_hdac_calc_stream_format(48000, 2,
7500
+ SNDRV_PCM_FORMAT_S32_LE, 32, 0);
7501
+
7502
+ snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id,
7503
+ 0, stream_format);
7504
+
7505
+ snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
7506
+}
7507
+
7508
+/*
7509
+ * Initialize mic for non-chromebook ca0132 implementations.
7510
+ */
7511
+static void ca0132_alt_init_analog_mics(struct hda_codec *codec)
7512
+{
7513
+ struct ca0132_spec *spec = codec->spec;
62937514 unsigned int tmp;
62947515
62957516 /* Mic 1 Setup */
62967517 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
62977518 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
6298
- tmp = FLOAT_THREE;
7519
+ if (ca0132_quirk(spec) == QUIRK_R3DI) {
7520
+ chipio_set_conn_rate(codec, 0x0F, SR_96_000);
7521
+ tmp = FLOAT_ONE;
7522
+ } else
7523
+ tmp = FLOAT_THREE;
62997524 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
63007525
6301
- /* Mic 2 Setup, even though it isn't connected on SBZ */
7526
+ /* Mic 2 setup (not present on desktop cards) */
63027527 chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000);
63037528 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000);
7529
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
7530
+ chipio_set_conn_rate(codec, 0x0F, SR_96_000);
63047531 tmp = FLOAT_ZERO;
63057532 dspio_set_uint_param(codec, 0x80, 0x01, tmp);
6306
-
63077533 }
63087534
63097535 /*
....@@ -6336,7 +7562,6 @@
63367562 codec_dbg(codec, "Connect Streams exited, mutex released.\n");
63377563
63387564 mutex_unlock(&spec->chipio_mutex);
6339
-
63407565 }
63417566
63427567 /*
....@@ -6363,19 +7588,29 @@
63637588 chipio_set_stream_channels(codec, 0x0C, 6);
63647589 chipio_set_stream_control(codec, 0x0C, 1);
63657590 /* 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
-
7591
+ if (ca0132_quirk(spec) == QUIRK_SBZ) {
7592
+ chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0);
7593
+ chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1);
7594
+ chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2);
7595
+ chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3);
7596
+ chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4);
7597
+ chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5);
7598
+ chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6);
7599
+ chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7);
7600
+ chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8);
7601
+ chipio_write_no_mutex(codec, 0x190054, 0x0001edc9);
7602
+ chipio_write_no_mutex(codec, 0x190058, 0x0001eaca);
7603
+ chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb);
7604
+ } else if (ca0132_quirk(spec) == QUIRK_ZXR) {
7605
+ chipio_write_no_mutex(codec, 0x190038, 0x000140c2);
7606
+ chipio_write_no_mutex(codec, 0x19003c, 0x000141c3);
7607
+ chipio_write_no_mutex(codec, 0x190040, 0x000150c4);
7608
+ chipio_write_no_mutex(codec, 0x190044, 0x000151c5);
7609
+ chipio_write_no_mutex(codec, 0x190050, 0x000142c8);
7610
+ chipio_write_no_mutex(codec, 0x190054, 0x000143c9);
7611
+ chipio_write_no_mutex(codec, 0x190058, 0x000152ca);
7612
+ chipio_write_no_mutex(codec, 0x19005c, 0x000153cb);
7613
+ }
63797614 chipio_write_no_mutex(codec, 0x19042c, 0x00000001);
63807615
63817616 codec_dbg(codec, "Startup Data exited, mutex released.\n");
....@@ -6383,35 +7618,59 @@
63837618 }
63847619
63857620 /*
6386
- * Sound Blaster Z uses these after DSP is loaded. Weird SCP commands
6387
- * without a 0x20 source like normal.
7621
+ * Custom DSP SCP commands where the src value is 0x00 instead of 0x20. This is
7622
+ * done after the DSP is loaded.
63887623 */
6389
-static void sbz_dsp_scp_startup(struct hda_codec *codec)
7624
+static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec)
63907625 {
6391
- unsigned int tmp;
7626
+ struct ca0132_spec *spec = codec->spec;
7627
+ unsigned int tmp, i;
63927628
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
-
7629
+ /*
7630
+ * Gotta run these twice, or else mic works inconsistently. Not clear
7631
+ * why this is, but multiple tests have confirmed it.
7632
+ */
7633
+ for (i = 0; i < 2; i++) {
7634
+ switch (ca0132_quirk(spec)) {
7635
+ case QUIRK_SBZ:
7636
+ case QUIRK_AE5:
7637
+ case QUIRK_AE7:
7638
+ tmp = 0x00000003;
7639
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7640
+ tmp = 0x00000000;
7641
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7642
+ tmp = 0x00000001;
7643
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
7644
+ tmp = 0x00000004;
7645
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7646
+ tmp = 0x00000005;
7647
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7648
+ tmp = 0x00000000;
7649
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7650
+ break;
7651
+ case QUIRK_R3D:
7652
+ case QUIRK_R3DI:
7653
+ tmp = 0x00000000;
7654
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7655
+ tmp = 0x00000001;
7656
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
7657
+ tmp = 0x00000004;
7658
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7659
+ tmp = 0x00000005;
7660
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7661
+ tmp = 0x00000000;
7662
+ dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7663
+ break;
7664
+ default:
7665
+ break;
7666
+ }
7667
+ msleep(100);
7668
+ }
64117669 }
64127670
6413
-static void sbz_dsp_initial_mic_setup(struct hda_codec *codec)
7671
+static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec)
64147672 {
7673
+ struct ca0132_spec *spec = codec->spec;
64157674 unsigned int tmp;
64167675
64177676 chipio_set_stream_control(codec, 0x03, 0);
....@@ -6426,8 +7685,369 @@
64267685 chipio_set_stream_control(codec, 0x03, 1);
64277686 chipio_set_stream_control(codec, 0x04, 1);
64287687
6429
- chipio_write(codec, 0x18b098, 0x0000000c);
6430
- chipio_write(codec, 0x18b09C, 0x0000000c);
7688
+ switch (ca0132_quirk(spec)) {
7689
+ case QUIRK_SBZ:
7690
+ chipio_write(codec, 0x18b098, 0x0000000c);
7691
+ chipio_write(codec, 0x18b09C, 0x0000000c);
7692
+ break;
7693
+ case QUIRK_AE5:
7694
+ chipio_write(codec, 0x18b098, 0x0000000c);
7695
+ chipio_write(codec, 0x18b09c, 0x0000004c);
7696
+ break;
7697
+ default:
7698
+ break;
7699
+ }
7700
+}
7701
+
7702
+static void ae5_post_dsp_register_set(struct hda_codec *codec)
7703
+{
7704
+ struct ca0132_spec *spec = codec->spec;
7705
+
7706
+ chipio_8051_write_direct(codec, 0x93, 0x10);
7707
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7708
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
7709
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7710
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
7711
+
7712
+ writeb(0xff, spec->mem_base + 0x304);
7713
+ writeb(0xff, spec->mem_base + 0x304);
7714
+ writeb(0xff, spec->mem_base + 0x304);
7715
+ writeb(0xff, spec->mem_base + 0x304);
7716
+ writeb(0x00, spec->mem_base + 0x100);
7717
+ writeb(0xff, spec->mem_base + 0x304);
7718
+ writeb(0x00, spec->mem_base + 0x100);
7719
+ writeb(0xff, spec->mem_base + 0x304);
7720
+ writeb(0x00, spec->mem_base + 0x100);
7721
+ writeb(0xff, spec->mem_base + 0x304);
7722
+ writeb(0x00, spec->mem_base + 0x100);
7723
+ writeb(0xff, spec->mem_base + 0x304);
7724
+
7725
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x3f);
7726
+ ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
7727
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7728
+}
7729
+
7730
+static void ae5_post_dsp_param_setup(struct hda_codec *codec)
7731
+{
7732
+ /*
7733
+ * Param3 in the 8051's memory is represented by the ascii string 'mch'
7734
+ * which seems to be 'multichannel'. This is also mentioned in the
7735
+ * AE-5's registry values in Windows.
7736
+ */
7737
+ chipio_set_control_param(codec, 3, 0);
7738
+ /*
7739
+ * I believe ASI is 'audio serial interface' and that it's used to
7740
+ * change colors on the external LED strip connected to the AE-5.
7741
+ */
7742
+ chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1);
7743
+
7744
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83);
7745
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
7746
+
7747
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7748
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92);
7749
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7750
+ VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa);
7751
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7752
+ VENDOR_CHIPIO_8051_DATA_WRITE, 0x22);
7753
+}
7754
+
7755
+static void ae5_post_dsp_pll_setup(struct hda_codec *codec)
7756
+{
7757
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7758
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41);
7759
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7760
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8);
7761
+
7762
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7763
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x45);
7764
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7765
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcc);
7766
+
7767
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7768
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x40);
7769
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7770
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcb);
7771
+
7772
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7773
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7774
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7775
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7776
+
7777
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7778
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x51);
7779
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7780
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0x8d);
7781
+}
7782
+
7783
+static void ae5_post_dsp_stream_setup(struct hda_codec *codec)
7784
+{
7785
+ struct ca0132_spec *spec = codec->spec;
7786
+
7787
+ mutex_lock(&spec->chipio_mutex);
7788
+
7789
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81);
7790
+
7791
+ chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000);
7792
+
7793
+ chipio_set_stream_channels(codec, 0x0C, 6);
7794
+ chipio_set_stream_control(codec, 0x0C, 1);
7795
+
7796
+ chipio_set_stream_source_dest(codec, 0x5, 0x43, 0x0);
7797
+
7798
+ chipio_set_stream_source_dest(codec, 0x18, 0x9, 0xd0);
7799
+ chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
7800
+ chipio_set_stream_channels(codec, 0x18, 6);
7801
+ chipio_set_stream_control(codec, 0x18, 1);
7802
+
7803
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4);
7804
+
7805
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7806
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7807
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7808
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7809
+
7810
+ ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80);
7811
+
7812
+ mutex_unlock(&spec->chipio_mutex);
7813
+}
7814
+
7815
+static void ae5_post_dsp_startup_data(struct hda_codec *codec)
7816
+{
7817
+ struct ca0132_spec *spec = codec->spec;
7818
+
7819
+ mutex_lock(&spec->chipio_mutex);
7820
+
7821
+ chipio_write_no_mutex(codec, 0x189000, 0x0001f101);
7822
+ chipio_write_no_mutex(codec, 0x189004, 0x0001f101);
7823
+ chipio_write_no_mutex(codec, 0x189024, 0x00014004);
7824
+ chipio_write_no_mutex(codec, 0x189028, 0x0002000f);
7825
+
7826
+ ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
7827
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
7828
+ ca0113_mmio_command_set(codec, 0x48, 0x0b, 0x12);
7829
+ ca0113_mmio_command_set(codec, 0x48, 0x04, 0x00);
7830
+ ca0113_mmio_command_set(codec, 0x48, 0x06, 0x48);
7831
+ ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
7832
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7833
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7834
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7835
+ ca0113_mmio_gpio_set(codec, 0, true);
7836
+ ca0113_mmio_gpio_set(codec, 1, true);
7837
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x80);
7838
+
7839
+ chipio_write_no_mutex(codec, 0x18b03c, 0x00000012);
7840
+
7841
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7842
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7843
+
7844
+ mutex_unlock(&spec->chipio_mutex);
7845
+}
7846
+
7847
+static const unsigned int ae7_port_set_data[] = {
7848
+ 0x0001e0c0, 0x0001e1c1, 0x0001e4c2, 0x0001e5c3, 0x0001e2c4, 0x0001e3c5,
7849
+ 0x0001e8c6, 0x0001e9c7, 0x0001ecc8, 0x0001edc9, 0x0001eaca, 0x0001ebcb
7850
+};
7851
+
7852
+static void ae7_post_dsp_setup_ports(struct hda_codec *codec)
7853
+{
7854
+ struct ca0132_spec *spec = codec->spec;
7855
+ unsigned int i, count, addr;
7856
+
7857
+ mutex_lock(&spec->chipio_mutex);
7858
+
7859
+ chipio_set_stream_channels(codec, 0x0c, 6);
7860
+ chipio_set_stream_control(codec, 0x0c, 1);
7861
+
7862
+ count = ARRAY_SIZE(ae7_port_set_data);
7863
+ addr = 0x190030;
7864
+ for (i = 0; i < count; i++) {
7865
+ chipio_write_no_mutex(codec, addr, ae7_port_set_data[i]);
7866
+
7867
+ /* Addresses are incremented by 4-bytes. */
7868
+ addr += 0x04;
7869
+ }
7870
+
7871
+ /*
7872
+ * Port setting always ends with a write of 0x1 to address 0x19042c.
7873
+ */
7874
+ chipio_write_no_mutex(codec, 0x19042c, 0x00000001);
7875
+
7876
+ ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
7877
+ ca0113_mmio_command_set(codec, 0x48, 0x0d, 0x40);
7878
+ ca0113_mmio_command_set(codec, 0x48, 0x17, 0x00);
7879
+ ca0113_mmio_command_set(codec, 0x48, 0x19, 0x00);
7880
+ ca0113_mmio_command_set(codec, 0x48, 0x11, 0xff);
7881
+ ca0113_mmio_command_set(codec, 0x48, 0x12, 0xff);
7882
+ ca0113_mmio_command_set(codec, 0x48, 0x13, 0xff);
7883
+ ca0113_mmio_command_set(codec, 0x48, 0x14, 0x7f);
7884
+
7885
+ mutex_unlock(&spec->chipio_mutex);
7886
+}
7887
+
7888
+static void ae7_post_dsp_asi_stream_setup(struct hda_codec *codec)
7889
+{
7890
+ struct ca0132_spec *spec = codec->spec;
7891
+
7892
+ mutex_lock(&spec->chipio_mutex);
7893
+
7894
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81);
7895
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
7896
+
7897
+ chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000);
7898
+ chipio_set_stream_channels(codec, 0x0c, 6);
7899
+ chipio_set_stream_control(codec, 0x0c, 1);
7900
+
7901
+ chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00);
7902
+ chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0);
7903
+
7904
+ chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
7905
+ chipio_set_stream_channels(codec, 0x18, 6);
7906
+ chipio_set_stream_control(codec, 0x18, 1);
7907
+
7908
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4);
7909
+
7910
+ mutex_unlock(&spec->chipio_mutex);
7911
+}
7912
+
7913
+static void ae7_post_dsp_pll_setup(struct hda_codec *codec)
7914
+{
7915
+ static const unsigned int addr[] = {
7916
+ 0x41, 0x45, 0x40, 0x43, 0x51
7917
+ };
7918
+ static const unsigned int data[] = {
7919
+ 0xc8, 0xcc, 0xcb, 0xc7, 0x8d
7920
+ };
7921
+ unsigned int i;
7922
+
7923
+ for (i = 0; i < ARRAY_SIZE(addr); i++) {
7924
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7925
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, addr[i]);
7926
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7927
+ VENDOR_CHIPIO_PLL_PMU_WRITE, data[i]);
7928
+ }
7929
+}
7930
+
7931
+static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec)
7932
+{
7933
+ struct ca0132_spec *spec = codec->spec;
7934
+ static const unsigned int target[] = {
7935
+ 0x0b, 0x04, 0x06, 0x0a, 0x0c, 0x11, 0x12, 0x13, 0x14
7936
+ };
7937
+ static const unsigned int data[] = {
7938
+ 0x12, 0x00, 0x48, 0x05, 0x5f, 0xff, 0xff, 0xff, 0x7f
7939
+ };
7940
+ unsigned int i;
7941
+
7942
+ mutex_lock(&spec->chipio_mutex);
7943
+
7944
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7945
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7946
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7947
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7948
+
7949
+ chipio_write_no_mutex(codec, 0x189000, 0x0001f101);
7950
+ chipio_write_no_mutex(codec, 0x189004, 0x0001f101);
7951
+ chipio_write_no_mutex(codec, 0x189024, 0x00014004);
7952
+ chipio_write_no_mutex(codec, 0x189028, 0x0002000f);
7953
+
7954
+ ae7_post_dsp_pll_setup(codec);
7955
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
7956
+
7957
+ for (i = 0; i < ARRAY_SIZE(target); i++)
7958
+ ca0113_mmio_command_set(codec, 0x48, target[i], data[i]);
7959
+
7960
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
7961
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7962
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7963
+
7964
+ chipio_set_stream_source_dest(codec, 0x21, 0x64, 0x56);
7965
+ chipio_set_stream_channels(codec, 0x21, 2);
7966
+ chipio_set_conn_rate_no_mutex(codec, 0x56, SR_8_000);
7967
+
7968
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_NODE_ID, 0x09);
7969
+ /*
7970
+ * In the 8051's memory, this param is referred to as 'n2sid', which I
7971
+ * believe is 'node to streamID'. It seems to be a way to assign a
7972
+ * stream to a given HDA node.
7973
+ */
7974
+ chipio_set_control_param_no_mutex(codec, 0x20, 0x21);
7975
+
7976
+ chipio_write_no_mutex(codec, 0x18b038, 0x00000088);
7977
+
7978
+ /*
7979
+ * Now, at this point on Windows, an actual stream is setup and
7980
+ * seemingly sends data to the HDA node 0x09, which is the digital
7981
+ * audio input node. This is left out here, because obviously I don't
7982
+ * know what data is being sent. Interestingly, the AE-5 seems to go
7983
+ * through the motions of getting here and never actually takes this
7984
+ * step, but the AE-7 does.
7985
+ */
7986
+
7987
+ ca0113_mmio_gpio_set(codec, 0, 1);
7988
+ ca0113_mmio_gpio_set(codec, 1, 1);
7989
+
7990
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
7991
+ chipio_write_no_mutex(codec, 0x18b03c, 0x00000000);
7992
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7993
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7994
+
7995
+ chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00);
7996
+ chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0);
7997
+
7998
+ chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
7999
+ chipio_set_stream_channels(codec, 0x18, 6);
8000
+
8001
+ /*
8002
+ * Runs again, this has been repeated a few times, but I'm just
8003
+ * following what the Windows driver does.
8004
+ */
8005
+ ae7_post_dsp_pll_setup(codec);
8006
+ chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
8007
+
8008
+ mutex_unlock(&spec->chipio_mutex);
8009
+}
8010
+
8011
+/*
8012
+ * The Windows driver has commands that seem to setup ASI, which I believe to
8013
+ * be some sort of audio serial interface. My current speculation is that it's
8014
+ * related to communicating with the new DAC.
8015
+ */
8016
+static void ae7_post_dsp_asi_setup(struct hda_codec *codec)
8017
+{
8018
+ chipio_8051_write_direct(codec, 0x93, 0x10);
8019
+
8020
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8021
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
8022
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8023
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
8024
+
8025
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
8026
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
8027
+
8028
+ chipio_set_control_param(codec, 3, 3);
8029
+ chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1);
8030
+
8031
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83);
8032
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
8033
+ snd_hda_codec_write(codec, 0x17, 0, 0x794, 0x00);
8034
+
8035
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8036
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92);
8037
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8038
+ VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa);
8039
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8040
+ VENDOR_CHIPIO_8051_DATA_WRITE, 0x22);
8041
+
8042
+ ae7_post_dsp_pll_setup(codec);
8043
+ ae7_post_dsp_asi_stream_setup(codec);
8044
+
8045
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8046
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
8047
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8048
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
8049
+
8050
+ ae7_post_dsp_asi_setup_ports(codec);
64318051 }
64328052
64338053 /*
....@@ -6488,9 +8108,8 @@
64888108 if (spec->dsp_state != DSP_DOWNLOADED)
64898109 return;
64908110
6491
- r3d_dsp_scp_startup(codec);
6492
-
6493
- r3d_dsp_initial_mic_setup(codec);
8111
+ ca0132_alt_dsp_scp_startup(codec);
8112
+ ca0132_alt_init_analog_mics(codec);
64948113
64958114 /*remove DSP headroom*/
64968115 tmp = FLOAT_ZERO;
....@@ -6504,8 +8123,14 @@
65048123 /* Set speaker source? */
65058124 dspio_set_uint_param(codec, 0x32, 0x00, tmp);
65068125
6507
- if (spec->quirk == QUIRK_R3DI)
8126
+ if (ca0132_quirk(spec) == QUIRK_R3DI)
65088127 r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED);
8128
+
8129
+ /* Disable mute on Center/LFE. */
8130
+ if (ca0132_quirk(spec) == QUIRK_R3D) {
8131
+ ca0113_mmio_gpio_set(codec, 2, false);
8132
+ ca0113_mmio_gpio_set(codec, 4, true);
8133
+ }
65098134
65108135 /* Setup effect defaults */
65118136 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
....@@ -6526,19 +8151,16 @@
65268151 static void sbz_setup_defaults(struct hda_codec *codec)
65278152 {
65288153 struct ca0132_spec *spec = codec->spec;
6529
- unsigned int tmp, stream_format;
8154
+ unsigned int tmp;
65308155 int num_fx;
65318156 int idx, i;
65328157
65338158 if (spec->dsp_state != DSP_DOWNLOADED)
65348159 return;
65358160
6536
- sbz_dsp_scp_startup(codec);
6537
-
6538
- sbz_init_analog_mics(codec);
6539
-
8161
+ ca0132_alt_dsp_scp_startup(codec);
8162
+ ca0132_alt_init_analog_mics(codec);
65408163 sbz_connect_streams(codec);
6541
-
65428164 sbz_chipio_startup_data(codec);
65438165
65448166 chipio_set_stream_control(codec, 0x03, 1);
....@@ -6564,8 +8186,7 @@
65648186 /* Set speaker source? */
65658187 dspio_set_uint_param(codec, 0x32, 0x00, tmp);
65668188
6567
- sbz_dsp_initial_mic_setup(codec);
6568
-
8189
+ ca0132_alt_dsp_initial_mic_setup(codec);
65698190
65708191 /* out, in effects + voicefx */
65718192 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
....@@ -6578,23 +8199,163 @@
65788199 }
65798200 }
65808201
8202
+ ca0132_alt_init_speaker_tuning(codec);
8203
+
8204
+ ca0132_alt_create_dummy_stream(codec);
8205
+}
8206
+
8207
+/*
8208
+ * Setup default parameters for the Sound BlasterX AE-5 DSP.
8209
+ */
8210
+static void ae5_setup_defaults(struct hda_codec *codec)
8211
+{
8212
+ struct ca0132_spec *spec = codec->spec;
8213
+ unsigned int tmp;
8214
+ int num_fx;
8215
+ int idx, i;
8216
+
8217
+ if (spec->dsp_state != DSP_DOWNLOADED)
8218
+ return;
8219
+
8220
+ ca0132_alt_dsp_scp_startup(codec);
8221
+ ca0132_alt_init_analog_mics(codec);
8222
+ chipio_set_stream_control(codec, 0x03, 1);
8223
+ chipio_set_stream_control(codec, 0x04, 1);
8224
+
8225
+ /* New, unknown SCP req's */
8226
+ tmp = FLOAT_ZERO;
8227
+ dspio_set_uint_param(codec, 0x96, 0x29, tmp);
8228
+ dspio_set_uint_param(codec, 0x96, 0x2a, tmp);
8229
+ dspio_set_uint_param(codec, 0x80, 0x0d, tmp);
8230
+ dspio_set_uint_param(codec, 0x80, 0x0e, tmp);
8231
+
8232
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
8233
+ ca0113_mmio_gpio_set(codec, 0, false);
8234
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
8235
+
8236
+ /* Internal loopback off */
8237
+ tmp = FLOAT_ONE;
8238
+ dspio_set_uint_param(codec, 0x37, 0x08, tmp);
8239
+ dspio_set_uint_param(codec, 0x37, 0x10, tmp);
8240
+
8241
+ /*remove DSP headroom*/
8242
+ tmp = FLOAT_ZERO;
8243
+ dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
8244
+
8245
+ /* set WUH source */
8246
+ tmp = FLOAT_TWO;
8247
+ dspio_set_uint_param(codec, 0x31, 0x00, tmp);
8248
+ chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
8249
+
8250
+ /* Set speaker source? */
8251
+ dspio_set_uint_param(codec, 0x32, 0x00, tmp);
8252
+
8253
+ ca0132_alt_dsp_initial_mic_setup(codec);
8254
+ ae5_post_dsp_register_set(codec);
8255
+ ae5_post_dsp_param_setup(codec);
8256
+ ae5_post_dsp_pll_setup(codec);
8257
+ ae5_post_dsp_stream_setup(codec);
8258
+ ae5_post_dsp_startup_data(codec);
8259
+
8260
+ /* out, in effects + voicefx */
8261
+ num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
8262
+ for (idx = 0; idx < num_fx; idx++) {
8263
+ for (i = 0; i <= ca0132_effects[idx].params; i++) {
8264
+ dspio_set_uint_param(codec,
8265
+ ca0132_effects[idx].mid,
8266
+ ca0132_effects[idx].reqs[i],
8267
+ ca0132_effects[idx].def_vals[i]);
8268
+ }
8269
+ }
8270
+
8271
+ ca0132_alt_init_speaker_tuning(codec);
8272
+
8273
+ ca0132_alt_create_dummy_stream(codec);
8274
+}
8275
+
8276
+/*
8277
+ * Setup default parameters for the Sound Blaster AE-7 DSP.
8278
+ */
8279
+static void ae7_setup_defaults(struct hda_codec *codec)
8280
+{
8281
+ struct ca0132_spec *spec = codec->spec;
8282
+ unsigned int tmp;
8283
+ int num_fx;
8284
+ int idx, i;
8285
+
8286
+ if (spec->dsp_state != DSP_DOWNLOADED)
8287
+ return;
8288
+
8289
+ ca0132_alt_dsp_scp_startup(codec);
8290
+ ca0132_alt_init_analog_mics(codec);
8291
+ ae7_post_dsp_setup_ports(codec);
8292
+
8293
+ tmp = FLOAT_ZERO;
8294
+ dspio_set_uint_param(codec, 0x96,
8295
+ SPEAKER_TUNING_FRONT_LEFT_INVERT, tmp);
8296
+ dspio_set_uint_param(codec, 0x96,
8297
+ SPEAKER_TUNING_FRONT_RIGHT_INVERT, tmp);
8298
+
8299
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
8300
+
8301
+ /* New, unknown SCP req's */
8302
+ dspio_set_uint_param(codec, 0x80, 0x0d, tmp);
8303
+ dspio_set_uint_param(codec, 0x80, 0x0e, tmp);
8304
+
8305
+ ca0113_mmio_gpio_set(codec, 0, false);
8306
+
8307
+ /* Internal loopback off */
8308
+ tmp = FLOAT_ONE;
8309
+ dspio_set_uint_param(codec, 0x37, 0x08, tmp);
8310
+ dspio_set_uint_param(codec, 0x37, 0x10, tmp);
8311
+
8312
+ /*remove DSP headroom*/
8313
+ tmp = FLOAT_ZERO;
8314
+ dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
8315
+
8316
+ /* set WUH source */
8317
+ tmp = FLOAT_TWO;
8318
+ dspio_set_uint_param(codec, 0x31, 0x00, tmp);
8319
+ chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
8320
+
8321
+ /* Set speaker source? */
8322
+ dspio_set_uint_param(codec, 0x32, 0x00, tmp);
8323
+ ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
8324
+
65818325 /*
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
8326
+ * This is the second time we've called this, but this is seemingly
8327
+ * what Windows does.
65858328 */
6586
- stream_format = snd_hdac_calc_stream_format(48000, 2,
6587
- SNDRV_PCM_FORMAT_S32_LE, 32, 0);
8329
+ ca0132_alt_init_analog_mics(codec);
65888330
6589
- snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id,
6590
- 0, stream_format);
8331
+ ae7_post_dsp_asi_setup(codec);
65918332
6592
- snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
8333
+ /*
8334
+ * Not sure why, but these are both set to 1. They're only set to 0
8335
+ * upon shutdown.
8336
+ */
8337
+ ca0113_mmio_gpio_set(codec, 0, true);
8338
+ ca0113_mmio_gpio_set(codec, 1, true);
65938339
6594
- snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id,
6595
- 0, stream_format);
8340
+ /* Volume control related. */
8341
+ ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x04);
8342
+ ca0113_mmio_command_set(codec, 0x48, 0x10, 0x04);
8343
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x80);
65968344
6597
- snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
8345
+ /* out, in effects + voicefx */
8346
+ num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
8347
+ for (idx = 0; idx < num_fx; idx++) {
8348
+ for (i = 0; i <= ca0132_effects[idx].params; i++) {
8349
+ dspio_set_uint_param(codec,
8350
+ ca0132_effects[idx].mid,
8351
+ ca0132_effects[idx].reqs[i],
8352
+ ca0132_effects[idx].def_vals[i]);
8353
+ }
8354
+ }
8355
+
8356
+ ca0132_alt_init_speaker_tuning(codec);
8357
+
8358
+ ca0132_alt_create_dummy_stream(codec);
65988359 }
65998360
66008361 /*
....@@ -6604,7 +8365,7 @@
66048365 {
66058366 struct ca0132_spec *spec = codec->spec;
66068367
6607
- if (spec->use_alt_functions) {
8368
+ if (ca0132_use_alt_functions(spec)) {
66088369 chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1);
66098370 chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1);
66108371 chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1);
....@@ -6637,7 +8398,7 @@
66378398 {
66388399 struct ca0132_spec *spec = codec->spec;
66398400
6640
- if (spec->use_alt_functions) {
8401
+ if (ca0132_use_alt_functions(spec)) {
66418402 chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
66428403 chipio_set_conn_rate(codec, 0x0B, SR_48_000);
66438404 chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0);
....@@ -6668,42 +8429,37 @@
66688429 bool dsp_loaded = false;
66698430 struct ca0132_spec *spec = codec->spec;
66708431 const struct dsp_image_seg *dsp_os_image;
6671
- const struct firmware *fw_entry;
8432
+ const struct firmware *fw_entry = NULL;
66728433 /*
66738434 * Alternate firmwares for different variants. The Recon3Di apparently
66748435 * can use the default firmware, but I'll leave the option in case
66758436 * it needs it again.
66768437 */
6677
- switch (spec->quirk) {
8438
+ switch (ca0132_quirk(spec)) {
66788439 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
- }
8440
+ case QUIRK_R3D:
8441
+ case QUIRK_AE5:
8442
+ if (request_firmware(&fw_entry, DESKTOP_EFX_FILE,
8443
+ codec->card->dev) != 0)
8444
+ codec_dbg(codec, "Desktop firmware not found.");
8445
+ else
8446
+ codec_dbg(codec, "Desktop firmware selected.");
66878447 break;
66888448 case QUIRK_R3DI:
66898449 if (request_firmware(&fw_entry, R3DI_EFX_FILE,
6690
- codec->card->dev) != 0) {
8450
+ codec->card->dev) != 0)
66918451 codec_dbg(codec, "Recon3Di alt firmware not detected.");
6692
- spec->alt_firmware_present = false;
6693
- } else {
8452
+ else
66948453 codec_dbg(codec, "Recon3Di firmware selected.");
6695
- spec->alt_firmware_present = true;
6696
- }
66978454 break;
66988455 default:
6699
- spec->alt_firmware_present = false;
67008456 break;
67018457 }
67028458 /*
67038459 * Use default ctefx.bin if no alt firmware is detected, or if none
67048460 * exists for your particular codec.
67058461 */
6706
- if (!spec->alt_firmware_present) {
8462
+ if (!fw_entry) {
67078463 codec_dbg(codec, "Default firmware selected.");
67088464 if (request_firmware(&fw_entry, EFX_FILE,
67098465 codec->card->dev) != 0)
....@@ -6746,7 +8502,7 @@
67468502 }
67478503
67488504 /* For codecs using alt functions, this is already done earlier */
6749
- if (spec->dsp_state == DSP_DOWNLOADED && (!spec->use_alt_functions))
8505
+ if (spec->dsp_state == DSP_DOWNLOADED && !ca0132_use_alt_functions(spec))
67508506 ca0132_set_dsp_msr(codec, true);
67518507 }
67528508
....@@ -6784,7 +8540,7 @@
67848540 {
67858541 struct ca0132_spec *spec = codec->spec;
67868542
6787
- if (spec->use_alt_functions)
8543
+ if (ca0132_use_alt_functions(spec))
67888544 ca0132_alt_select_in(codec);
67898545 else
67908546 ca0132_select_mic(codec);
....@@ -6799,7 +8555,7 @@
67998555 snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP,
68008556 ca0132_process_dsp_response);
68018557 /* Front headphone jack detection */
6802
- if (spec->use_alt_functions)
8558
+ if (ca0132_use_alt_functions(spec))
68038559 snd_hda_jack_detect_enable_callback(codec,
68048560 spec->unsol_tag_front_hp, hp_callback);
68058561 }
....@@ -6809,14 +8565,14 @@
68098565 */
68108566
68118567 /* Sends before DSP download. */
6812
-static struct hda_verb ca0132_base_init_verbs[] = {
8568
+static const struct hda_verb ca0132_base_init_verbs[] = {
68138569 /*enable ct extension*/
68148570 {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1},
68158571 {}
68168572 };
68178573
68188574 /* Send at exit. */
6819
-static struct hda_verb ca0132_base_exit_verbs[] = {
8575
+static const struct hda_verb ca0132_base_exit_verbs[] = {
68208576 /*set afg to D3*/
68218577 {0x01, AC_VERB_SET_POWER_STATE, 0x03},
68228578 /*disable ct extension*/
....@@ -6826,7 +8582,7 @@
68268582
68278583 /* Other verbs tables. Sends after DSP download. */
68288584
6829
-static struct hda_verb ca0132_init_verbs0[] = {
8585
+static const struct hda_verb ca0132_init_verbs0[] = {
68308586 /* chip init verbs */
68318587 {0x15, 0x70D, 0xF0},
68328588 {0x15, 0x70E, 0xFE},
....@@ -6859,7 +8615,7 @@
68598615 };
68608616
68618617 /* Extra init verbs for desktop cards. */
6862
-static struct hda_verb ca0132_init_verbs1[] = {
8618
+static const struct hda_verb ca0132_init_verbs1[] = {
68638619 {0x15, 0x70D, 0x20},
68648620 {0x15, 0x70E, 0x19},
68658621 {0x15, 0x707, 0x00},
....@@ -6889,7 +8645,7 @@
68898645 mutex_init(&spec->chipio_mutex);
68908646
68918647 spec->cur_out_type = SPEAKER_OUT;
6892
- if (!spec->use_alt_functions)
8648
+ if (!ca0132_use_alt_functions(spec))
68938649 spec->cur_mic_type = DIGITAL_MIC;
68948650 else
68958651 spec->cur_mic_type = REAR_MIC;
....@@ -6915,15 +8671,29 @@
69158671 * Sets defaults for the effect slider controls, only for alternative
69168672 * ca0132 codecs. Also sets x-bass crossover frequency to 80hz.
69178673 */
6918
- if (spec->use_alt_controls) {
8674
+ if (ca0132_use_alt_controls(spec)) {
8675
+ /* Set speakers to default to full range. */
8676
+ spec->speaker_range_val[0] = 1;
8677
+ spec->speaker_range_val[1] = 1;
8678
+
69198679 spec->xbass_xover_freq = 8;
69208680 for (i = 0; i < EFFECT_LEVEL_SLIDERS; i++)
69218681 spec->fx_ctl_val[i] = effect_slider_defaults[i];
8682
+
8683
+ spec->bass_redirect_xover_freq = 8;
69228684 }
69238685
69248686 spec->voicefx_val = 0;
69258687 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1;
69268688 spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0;
8689
+
8690
+ /*
8691
+ * The ZxR doesn't have a front panel header, and it's line-in is on
8692
+ * the daughter board. So, there is no input enum control, and we need
8693
+ * to make sure that spec->in_enum_val is set properly.
8694
+ */
8695
+ if (ca0132_quirk(spec) == QUIRK_ZXR)
8696
+ spec->in_enum_val = REAR_MIC;
69278697
69288698 #ifdef ENABLE_TUNING_CONTROLS
69298699 ca0132_init_tuning_defaults(codec);
....@@ -6952,32 +8722,32 @@
69528722 for (i = 0; i < 8; i++)
69538723 writeb(0xb3, spec->mem_base + 0x304);
69548724
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);
8725
+ ca0113_mmio_gpio_set(codec, 0, false);
8726
+ ca0113_mmio_gpio_set(codec, 1, false);
8727
+ ca0113_mmio_gpio_set(codec, 4, true);
8728
+ ca0113_mmio_gpio_set(codec, 5, false);
8729
+ ca0113_mmio_gpio_set(codec, 7, false);
69608730 }
69618731
69628732 static void sbz_set_pin_ctl_default(struct hda_codec *codec)
69638733 {
6964
- hda_nid_t pins[5] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
8734
+ static const hda_nid_t pins[] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
69658735 unsigned int i;
69668736
69678737 snd_hda_codec_write(codec, 0x11, 0,
69688738 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40);
69698739
6970
- for (i = 0; i < 5; i++)
8740
+ for (i = 0; i < ARRAY_SIZE(pins); i++)
69718741 snd_hda_codec_write(codec, pins[i], 0,
69728742 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00);
69738743 }
69748744
69758745 static void ca0132_clear_unsolicited(struct hda_codec *codec)
69768746 {
6977
- hda_nid_t pins[7] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
8747
+ static const hda_nid_t pins[] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
69788748 unsigned int i;
69798749
6980
- for (i = 0; i < 7; i++) {
8750
+ for (i = 0; i < ARRAY_SIZE(pins); i++) {
69818751 snd_hda_codec_write(codec, pins[i], 0,
69828752 AC_VERB_SET_UNSOLICITED_ENABLE, 0x00);
69838753 }
....@@ -6997,6 +8767,16 @@
69978767 if (data >= 0)
69988768 snd_hda_codec_write(codec, 0x01, 0,
69998769 AC_VERB_SET_GPIO_DATA, data);
8770
+}
8771
+
8772
+static void zxr_dbpro_power_state_shutdown(struct hda_codec *codec)
8773
+{
8774
+ static const hda_nid_t pins[] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01};
8775
+ unsigned int i;
8776
+
8777
+ for (i = 0; i < ARRAY_SIZE(pins); i++)
8778
+ snd_hda_codec_write(codec, pins[i], 0,
8779
+ AC_VERB_SET_POWER_STATE, 0x03);
70008780 }
70018781
70028782 static void sbz_exit_chip(struct hda_codec *codec)
....@@ -7039,6 +8819,87 @@
70398819 ca0132_clear_unsolicited(codec);
70408820 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
70418821 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b);
8822
+}
8823
+
8824
+static void ae5_exit_chip(struct hda_codec *codec)
8825
+{
8826
+ chipio_set_stream_control(codec, 0x03, 0);
8827
+ chipio_set_stream_control(codec, 0x04, 0);
8828
+
8829
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
8830
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
8831
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
8832
+ ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
8833
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
8834
+ ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x00);
8835
+ ca0113_mmio_gpio_set(codec, 0, false);
8836
+ ca0113_mmio_gpio_set(codec, 1, false);
8837
+
8838
+ snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
8839
+ snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
8840
+
8841
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
8842
+
8843
+ chipio_set_stream_control(codec, 0x18, 0);
8844
+ chipio_set_stream_control(codec, 0x0c, 0);
8845
+
8846
+ snd_hda_codec_write(codec, 0x01, 0, 0x724, 0x83);
8847
+}
8848
+
8849
+static void ae7_exit_chip(struct hda_codec *codec)
8850
+{
8851
+ chipio_set_stream_control(codec, 0x18, 0);
8852
+ chipio_set_stream_source_dest(codec, 0x21, 0xc8, 0xc8);
8853
+ chipio_set_stream_channels(codec, 0x21, 0);
8854
+ chipio_set_control_param(codec, CONTROL_PARAM_NODE_ID, 0x09);
8855
+ chipio_set_control_param(codec, 0x20, 0x01);
8856
+
8857
+ chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
8858
+
8859
+ chipio_set_stream_control(codec, 0x18, 0);
8860
+ chipio_set_stream_control(codec, 0x0c, 0);
8861
+
8862
+ ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
8863
+ snd_hda_codec_write(codec, 0x15, 0, 0x724, 0x83);
8864
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
8865
+ ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
8866
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x00);
8867
+ ca0113_mmio_gpio_set(codec, 0, false);
8868
+ ca0113_mmio_gpio_set(codec, 1, false);
8869
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
8870
+
8871
+ snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
8872
+ snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
8873
+}
8874
+
8875
+static void zxr_exit_chip(struct hda_codec *codec)
8876
+{
8877
+ chipio_set_stream_control(codec, 0x03, 0);
8878
+ chipio_set_stream_control(codec, 0x04, 0);
8879
+ chipio_set_stream_control(codec, 0x14, 0);
8880
+ chipio_set_stream_control(codec, 0x0C, 0);
8881
+
8882
+ chipio_set_conn_rate(codec, 0x41, SR_192_000);
8883
+ chipio_set_conn_rate(codec, 0x91, SR_192_000);
8884
+
8885
+ chipio_write(codec, 0x18a020, 0x00000083);
8886
+
8887
+ snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
8888
+ snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
8889
+
8890
+ ca0132_clear_unsolicited(codec);
8891
+ sbz_set_pin_ctl_default(codec);
8892
+ snd_hda_codec_write(codec, 0x0B, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x00);
8893
+
8894
+ ca0113_mmio_gpio_set(codec, 5, false);
8895
+ ca0113_mmio_gpio_set(codec, 2, false);
8896
+ ca0113_mmio_gpio_set(codec, 3, false);
8897
+ ca0113_mmio_gpio_set(codec, 0, false);
8898
+ ca0113_mmio_gpio_set(codec, 4, true);
8899
+ ca0113_mmio_gpio_set(codec, 0, true);
8900
+ ca0113_mmio_gpio_set(codec, 5, true);
8901
+ ca0113_mmio_gpio_set(codec, 2, false);
8902
+ ca0113_mmio_gpio_set(codec, 3, false);
70428903 }
70438904
70448905 static void ca0132_exit_chip(struct hda_codec *codec)
....@@ -7144,11 +9005,6 @@
71449005 writel(0x00820680, spec->mem_base + 0x01C);
71459006 writel(0x00820680, spec->mem_base + 0x01C);
71469007
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
-
71529008 chipio_write(codec, 0x18b0a4, 0x000000c2);
71539009
71549010 snd_hda_codec_write(codec, 0x11, 0,
....@@ -7157,12 +9013,6 @@
71579013
71589014 static void r3d_pre_dsp_setup(struct hda_codec *codec)
71599015 {
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
-
71669016 chipio_write(codec, 0x18b0a4, 0x000000c2);
71679017
71689018 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
....@@ -7205,27 +9055,220 @@
72059055 * what they do, or if they're necessary. Could possibly
72069056 * be removed. Figure they're better to leave in.
72079057 */
9058
+static const unsigned int ca0113_mmio_init_address_sbz[] = {
9059
+ 0x400, 0x408, 0x40c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c,
9060
+ 0xc0c, 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04
9061
+};
9062
+
9063
+static const unsigned int ca0113_mmio_init_data_sbz[] = {
9064
+ 0x00000030, 0x00000000, 0x00000003, 0x00000003, 0x00000003,
9065
+ 0x00000003, 0x000000c1, 0x000000f1, 0x00000001, 0x000000c7,
9066
+ 0x000000c1, 0x00000080
9067
+};
9068
+
9069
+static const unsigned int ca0113_mmio_init_data_zxr[] = {
9070
+ 0x00000030, 0x00000000, 0x00000000, 0x00000003, 0x00000003,
9071
+ 0x00000003, 0x00000001, 0x000000f1, 0x00000001, 0x000000c7,
9072
+ 0x000000c1, 0x00000080
9073
+};
9074
+
9075
+static const unsigned int ca0113_mmio_init_address_ae5[] = {
9076
+ 0x400, 0x42c, 0x46c, 0x4ac, 0x4ec, 0x43c, 0x47c, 0x4bc, 0x4fc, 0x408,
9077
+ 0x100, 0x410, 0x40c, 0x100, 0x100, 0x830, 0x86c, 0x800, 0x86c, 0x800,
9078
+ 0x804, 0x20c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c, 0xc0c,
9079
+ 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04, 0x01c
9080
+};
9081
+
9082
+static const unsigned int ca0113_mmio_init_data_ae5[] = {
9083
+ 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
9084
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
9085
+ 0x00000600, 0x00000014, 0x00000001, 0x0000060f, 0x0000070f,
9086
+ 0x00000aff, 0x00000000, 0x0000006b, 0x00000001, 0x0000006b,
9087
+ 0x00000057, 0x00800000, 0x00880680, 0x00000080, 0x00000030,
9088
+ 0x00000000, 0x00000000, 0x00000003, 0x00000003, 0x00000003,
9089
+ 0x00000001, 0x000000f1, 0x00000001, 0x000000c7, 0x000000c1,
9090
+ 0x00000080, 0x00880680
9091
+};
9092
+
9093
+static void ca0132_mmio_init_sbz(struct hda_codec *codec)
9094
+{
9095
+ struct ca0132_spec *spec = codec->spec;
9096
+ unsigned int tmp[2], i, count, cur_addr;
9097
+ const unsigned int *addr, *data;
9098
+
9099
+ addr = ca0113_mmio_init_address_sbz;
9100
+ for (i = 0; i < 3; i++)
9101
+ writel(0x00000000, spec->mem_base + addr[i]);
9102
+
9103
+ cur_addr = i;
9104
+ switch (ca0132_quirk(spec)) {
9105
+ case QUIRK_ZXR:
9106
+ tmp[0] = 0x00880480;
9107
+ tmp[1] = 0x00000080;
9108
+ break;
9109
+ case QUIRK_SBZ:
9110
+ tmp[0] = 0x00820680;
9111
+ tmp[1] = 0x00000083;
9112
+ break;
9113
+ case QUIRK_R3D:
9114
+ tmp[0] = 0x00880680;
9115
+ tmp[1] = 0x00000083;
9116
+ break;
9117
+ default:
9118
+ tmp[0] = 0x00000000;
9119
+ tmp[1] = 0x00000000;
9120
+ break;
9121
+ }
9122
+
9123
+ for (i = 0; i < 2; i++)
9124
+ writel(tmp[i], spec->mem_base + addr[cur_addr + i]);
9125
+
9126
+ cur_addr += i;
9127
+
9128
+ switch (ca0132_quirk(spec)) {
9129
+ case QUIRK_ZXR:
9130
+ count = ARRAY_SIZE(ca0113_mmio_init_data_zxr);
9131
+ data = ca0113_mmio_init_data_zxr;
9132
+ break;
9133
+ default:
9134
+ count = ARRAY_SIZE(ca0113_mmio_init_data_sbz);
9135
+ data = ca0113_mmio_init_data_sbz;
9136
+ break;
9137
+ }
9138
+
9139
+ for (i = 0; i < count; i++)
9140
+ writel(data[i], spec->mem_base + addr[cur_addr + i]);
9141
+}
9142
+
9143
+static void ca0132_mmio_init_ae5(struct hda_codec *codec)
9144
+{
9145
+ struct ca0132_spec *spec = codec->spec;
9146
+ const unsigned int *addr, *data;
9147
+ unsigned int i, count;
9148
+
9149
+ addr = ca0113_mmio_init_address_ae5;
9150
+ data = ca0113_mmio_init_data_ae5;
9151
+ count = ARRAY_SIZE(ca0113_mmio_init_data_ae5);
9152
+
9153
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9154
+ writel(0x00000680, spec->mem_base + 0x1c);
9155
+ writel(0x00880680, spec->mem_base + 0x1c);
9156
+ }
9157
+
9158
+ for (i = 0; i < count; i++) {
9159
+ /*
9160
+ * AE-7 shares all writes with the AE-5, except that it writes
9161
+ * a different value to 0x20c.
9162
+ */
9163
+ if (i == 21 && ca0132_quirk(spec) == QUIRK_AE7) {
9164
+ writel(0x00800001, spec->mem_base + addr[i]);
9165
+ continue;
9166
+ }
9167
+
9168
+ writel(data[i], spec->mem_base + addr[i]);
9169
+ }
9170
+
9171
+ if (ca0132_quirk(spec) == QUIRK_AE5)
9172
+ writel(0x00880680, spec->mem_base + 0x1c);
9173
+}
9174
+
72089175 static void ca0132_mmio_init(struct hda_codec *codec)
72099176 {
72109177 struct ca0132_spec *spec = codec->spec;
72119178
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);
9179
+ switch (ca0132_quirk(spec)) {
9180
+ case QUIRK_R3D:
9181
+ case QUIRK_SBZ:
9182
+ case QUIRK_ZXR:
9183
+ ca0132_mmio_init_sbz(codec);
9184
+ break;
9185
+ case QUIRK_AE5:
9186
+ ca0132_mmio_init_ae5(codec);
9187
+ break;
9188
+ default:
9189
+ break;
9190
+ }
9191
+}
9192
+
9193
+static const unsigned int ca0132_ae5_register_set_addresses[] = {
9194
+ 0x304, 0x304, 0x304, 0x304, 0x100, 0x304, 0x100, 0x304, 0x100, 0x304,
9195
+ 0x100, 0x304, 0x86c, 0x800, 0x86c, 0x800, 0x804
9196
+};
9197
+
9198
+static const unsigned char ca0132_ae5_register_set_data[] = {
9199
+ 0x0f, 0x0e, 0x1f, 0x0c, 0x3f, 0x08, 0x7f, 0x00, 0xff, 0x00, 0x6b,
9200
+ 0x01, 0x6b, 0x57
9201
+};
9202
+
9203
+/*
9204
+ * This function writes to some SFR's, does some region2 writes, and then
9205
+ * eventually resets the codec with the 0x7ff verb. Not quite sure why it does
9206
+ * what it does.
9207
+ */
9208
+static void ae5_register_set(struct hda_codec *codec)
9209
+{
9210
+ struct ca0132_spec *spec = codec->spec;
9211
+ unsigned int count = ARRAY_SIZE(ca0132_ae5_register_set_addresses);
9212
+ const unsigned int *addr = ca0132_ae5_register_set_addresses;
9213
+ const unsigned char *data = ca0132_ae5_register_set_data;
9214
+ unsigned int i, cur_addr;
9215
+ unsigned char tmp[3];
9216
+
9217
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9218
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9219
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41);
9220
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9221
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8);
9222
+ }
9223
+
9224
+ chipio_8051_write_direct(codec, 0x93, 0x10);
9225
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9226
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
9227
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9228
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
9229
+
9230
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9231
+ tmp[0] = 0x03;
9232
+ tmp[1] = 0x03;
9233
+ tmp[2] = 0x07;
9234
+ } else {
9235
+ tmp[0] = 0x0f;
9236
+ tmp[1] = 0x0f;
9237
+ tmp[2] = 0x0f;
9238
+ }
9239
+
9240
+ for (i = cur_addr = 0; i < 3; i++, cur_addr++)
9241
+ writeb(tmp[i], spec->mem_base + addr[cur_addr]);
9242
+
9243
+ /*
9244
+ * First writes are in single bytes, final are in 4 bytes. So, we use
9245
+ * writeb, then writel.
9246
+ */
9247
+ for (i = 0; cur_addr < 12; i++, cur_addr++)
9248
+ writeb(data[i], spec->mem_base + addr[cur_addr]);
9249
+
9250
+ for (; cur_addr < count; i++, cur_addr++)
9251
+ writel(data[i], spec->mem_base + addr[cur_addr]);
9252
+
9253
+ writel(0x00800001, spec->mem_base + 0x20c);
9254
+
9255
+ if (ca0132_quirk(spec) == QUIRK_AE7) {
9256
+ ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83);
9257
+ ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
9258
+ } else {
9259
+ ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
9260
+ }
9261
+
9262
+ chipio_8051_write_direct(codec, 0x90, 0x00);
9263
+ chipio_8051_write_direct(codec, 0x90, 0x10);
9264
+
9265
+ if (ca0132_quirk(spec) == QUIRK_AE5)
9266
+ ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
9267
+
9268
+ chipio_write(codec, 0x18b0a4, 0x000000c2);
9269
+
9270
+ snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00);
9271
+ snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00);
72299272 }
72309273
72319274 /*
....@@ -7239,7 +9282,7 @@
72399282
72409283 ca0132_alt_vol_setup(codec);
72419284
7242
- switch (spec->quirk) {
9285
+ switch (ca0132_quirk(spec)) {
72439286 case QUIRK_SBZ:
72449287 codec_dbg(codec, "SBZ alt_init");
72459288 ca0132_gpio_init(codec);
....@@ -7260,6 +9303,36 @@
72609303 r3d_pre_dsp_setup(codec);
72619304 snd_hda_sequence_write(codec, spec->chip_init_verbs);
72629305 snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9306
+ break;
9307
+ case QUIRK_AE5:
9308
+ ca0132_gpio_init(codec);
9309
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9310
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49);
9311
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9312
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88);
9313
+ chipio_write(codec, 0x18b030, 0x00000020);
9314
+ snd_hda_sequence_write(codec, spec->chip_init_verbs);
9315
+ snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9316
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
9317
+ break;
9318
+ case QUIRK_AE7:
9319
+ ca0132_gpio_init(codec);
9320
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9321
+ VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49);
9322
+ snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
9323
+ VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88);
9324
+ snd_hda_sequence_write(codec, spec->chip_init_verbs);
9325
+ snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9326
+ chipio_write(codec, 0x18b008, 0x000000f8);
9327
+ chipio_write(codec, 0x18b008, 0x000000f0);
9328
+ chipio_write(codec, 0x18b030, 0x00000020);
9329
+ ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
9330
+ break;
9331
+ case QUIRK_ZXR:
9332
+ snd_hda_sequence_write(codec, spec->chip_init_verbs);
9333
+ snd_hda_sequence_write(codec, spec->desktop_init_verbs);
9334
+ break;
9335
+ default:
72639336 break;
72649337 }
72659338 }
....@@ -7287,7 +9360,7 @@
72879360 spec->dsp_reload = true;
72889361 spec->dsp_state = DSP_DOWNLOAD_INIT;
72899362 } else {
7290
- if (spec->quirk == QUIRK_SBZ)
9363
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
72919364 sbz_dsp_startup_check(codec);
72929365 return 0;
72939366 }
....@@ -7297,10 +9370,13 @@
72979370 spec->dsp_state = DSP_DOWNLOAD_INIT;
72989371 spec->curr_chip_addx = INVALID_CHIP_ADDRESS;
72999372
7300
- if (spec->use_pci_mmio)
9373
+ if (ca0132_use_pci_mmio(spec))
73019374 ca0132_mmio_init(codec);
73029375
73039376 snd_hda_power_up_pm(codec);
9377
+
9378
+ if (ca0132_quirk(spec) == QUIRK_AE5 || ca0132_quirk(spec) == QUIRK_AE7)
9379
+ ae5_register_set(codec);
73049380
73059381 ca0132_init_unsol(codec);
73069382 ca0132_init_params(codec);
....@@ -7308,20 +9384,27 @@
73089384
73099385 snd_hda_sequence_write(codec, spec->base_init_verbs);
73109386
7311
- if (spec->use_alt_functions)
9387
+ if (ca0132_use_alt_functions(spec))
73129388 ca0132_alt_init(codec);
73139389
73149390 ca0132_download_dsp(codec);
73159391
73169392 ca0132_refresh_widget_caps(codec);
73179393
7318
- switch (spec->quirk) {
9394
+ switch (ca0132_quirk(spec)) {
73199395 case QUIRK_R3DI:
73209396 case QUIRK_R3D:
73219397 r3d_setup_defaults(codec);
73229398 break;
73239399 case QUIRK_SBZ:
9400
+ case QUIRK_ZXR:
73249401 sbz_setup_defaults(codec);
9402
+ break;
9403
+ case QUIRK_AE5:
9404
+ ae5_setup_defaults(codec);
9405
+ break;
9406
+ case QUIRK_AE7:
9407
+ ae7_setup_defaults(codec);
73259408 break;
73269409 default:
73279410 ca0132_setup_defaults(codec);
....@@ -7340,7 +9423,7 @@
73409423
73419424 init_input(codec, cfg->dig_in_pin, spec->dig_in);
73429425
7343
- if (!spec->use_alt_functions) {
9426
+ if (!ca0132_use_alt_functions(spec)) {
73449427 snd_hda_sequence_write(codec, spec->chip_init_verbs);
73459428 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
73469429 VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D);
....@@ -7348,11 +9431,11 @@
73489431 VENDOR_CHIPIO_PARAM_EX_VALUE_SET, 0x20);
73499432 }
73509433
7351
- if (spec->quirk == QUIRK_SBZ)
9434
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
73529435 ca0132_gpio_setup(codec);
73539436
73549437 snd_hda_sequence_write(codec, spec->spec_init_verbs);
7355
- if (spec->use_alt_functions) {
9438
+ if (ca0132_use_alt_functions(spec)) {
73569439 ca0132_alt_select_out(codec);
73579440 ca0132_alt_select_in(codec);
73589441 } else {
....@@ -7376,21 +9459,47 @@
73769459 return 0;
73779460 }
73789461
9462
+static int dbpro_init(struct hda_codec *codec)
9463
+{
9464
+ struct ca0132_spec *spec = codec->spec;
9465
+ struct auto_pin_cfg *cfg = &spec->autocfg;
9466
+ unsigned int i;
9467
+
9468
+ init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
9469
+ init_input(codec, cfg->dig_in_pin, spec->dig_in);
9470
+
9471
+ for (i = 0; i < spec->num_inputs; i++)
9472
+ init_input(codec, spec->input_pins[i], spec->adcs[i]);
9473
+
9474
+ return 0;
9475
+}
9476
+
73799477 static void ca0132_free(struct hda_codec *codec)
73809478 {
73819479 struct ca0132_spec *spec = codec->spec;
73829480
73839481 cancel_delayed_work_sync(&spec->unsol_hp_work);
73849482 snd_hda_power_up(codec);
7385
- switch (spec->quirk) {
9483
+ switch (ca0132_quirk(spec)) {
73869484 case QUIRK_SBZ:
73879485 sbz_exit_chip(codec);
9486
+ break;
9487
+ case QUIRK_ZXR:
9488
+ zxr_exit_chip(codec);
73889489 break;
73899490 case QUIRK_R3D:
73909491 r3d_exit_chip(codec);
73919492 break;
9493
+ case QUIRK_AE5:
9494
+ ae5_exit_chip(codec);
9495
+ break;
9496
+ case QUIRK_AE7:
9497
+ ae7_exit_chip(codec);
9498
+ break;
73929499 case QUIRK_R3DI:
73939500 r3di_gpio_shutdown(codec);
9501
+ break;
9502
+ default:
73949503 break;
73959504 }
73969505
....@@ -7402,6 +9511,16 @@
74029511 if (spec->mem_base)
74039512 pci_iounmap(codec->bus->pci, spec->mem_base);
74049513 #endif
9514
+ kfree(spec->spec_init_verbs);
9515
+ kfree(codec->spec);
9516
+}
9517
+
9518
+static void dbpro_free(struct hda_codec *codec)
9519
+{
9520
+ struct ca0132_spec *spec = codec->spec;
9521
+
9522
+ zxr_dbpro_power_state_shutdown(codec);
9523
+
74059524 kfree(spec->spec_init_verbs);
74069525 kfree(codec->spec);
74079526 }
....@@ -7433,6 +9552,13 @@
74339552 .reboot_notify = ca0132_reboot_notify,
74349553 };
74359554
9555
+static const struct hda_codec_ops dbpro_patch_ops = {
9556
+ .build_controls = dbpro_build_controls,
9557
+ .build_pcms = dbpro_build_pcms,
9558
+ .init = dbpro_init,
9559
+ .free = dbpro_free,
9560
+};
9561
+
74369562 static void ca0132_config(struct hda_codec *codec)
74379563 {
74389564 struct ca0132_spec *spec = codec->spec;
....@@ -7444,16 +9570,46 @@
74449570 spec->multiout.dac_nids = spec->dacs;
74459571 spec->multiout.num_dacs = 3;
74469572
7447
- if (!spec->use_alt_functions)
9573
+ if (!ca0132_use_alt_functions(spec))
74489574 spec->multiout.max_channels = 2;
74499575 else
74509576 spec->multiout.max_channels = 6;
74519577
7452
- switch (spec->quirk) {
9578
+ switch (ca0132_quirk(spec)) {
74539579 case QUIRK_ALIENWARE:
7454
- codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n");
9580
+ codec_dbg(codec, "%s: QUIRK_ALIENWARE applied.\n", __func__);
74559581 snd_hda_apply_pincfgs(codec, alienware_pincfgs);
9582
+ break;
9583
+ case QUIRK_SBZ:
9584
+ codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__);
9585
+ snd_hda_apply_pincfgs(codec, sbz_pincfgs);
9586
+ break;
9587
+ case QUIRK_ZXR:
9588
+ codec_dbg(codec, "%s: QUIRK_ZXR applied.\n", __func__);
9589
+ snd_hda_apply_pincfgs(codec, zxr_pincfgs);
9590
+ break;
9591
+ case QUIRK_R3D:
9592
+ codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__);
9593
+ snd_hda_apply_pincfgs(codec, r3d_pincfgs);
9594
+ break;
9595
+ case QUIRK_R3DI:
9596
+ codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__);
9597
+ snd_hda_apply_pincfgs(codec, r3di_pincfgs);
9598
+ break;
9599
+ case QUIRK_AE5:
9600
+ codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__);
9601
+ snd_hda_apply_pincfgs(codec, ae5_pincfgs);
9602
+ break;
9603
+ case QUIRK_AE7:
9604
+ codec_dbg(codec, "%s: QUIRK_AE7 applied.\n", __func__);
9605
+ snd_hda_apply_pincfgs(codec, ae7_pincfgs);
9606
+ break;
9607
+ default:
9608
+ break;
9609
+ }
74569610
9611
+ switch (ca0132_quirk(spec)) {
9612
+ case QUIRK_ALIENWARE:
74579613 spec->num_outputs = 2;
74589614 spec->out_pins[0] = 0x0b; /* speaker out */
74599615 spec->out_pins[1] = 0x0f;
....@@ -7473,15 +9629,6 @@
74739629 break;
74749630 case QUIRK_SBZ:
74759631 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
-
74859632 spec->num_outputs = 2;
74869633 spec->out_pins[0] = 0x0B; /* Line out */
74879634 spec->out_pins[1] = 0x0F; /* Rear headphone out */
....@@ -7506,10 +9653,63 @@
75069653 spec->multiout.dig_out_nid = spec->dig_out;
75079654 spec->dig_in = 0x09;
75089655 break;
7509
- case QUIRK_R3DI:
7510
- codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__);
7511
- snd_hda_apply_pincfgs(codec, r3di_pincfgs);
9656
+ case QUIRK_ZXR:
9657
+ spec->num_outputs = 2;
9658
+ spec->out_pins[0] = 0x0B; /* Line out */
9659
+ spec->out_pins[1] = 0x0F; /* Rear headphone out */
9660
+ spec->out_pins[2] = 0x10; /* Center/LFE */
9661
+ spec->out_pins[3] = 0x11; /* Rear surround */
9662
+ spec->shared_out_nid = 0x2;
9663
+ spec->unsol_tag_hp = spec->out_pins[1];
9664
+ spec->unsol_tag_front_hp = spec->out_pins[2];
75129665
9666
+ spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
9667
+ spec->adcs[1] = 0x8; /* Not connected, no front mic */
9668
+ spec->adcs[2] = 0xa; /* what u hear */
9669
+
9670
+ spec->num_inputs = 2;
9671
+ spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
9672
+ spec->input_pins[1] = 0x13; /* What U Hear */
9673
+ spec->shared_mic_nid = 0x7;
9674
+ spec->unsol_tag_amic1 = spec->input_pins[0];
9675
+ break;
9676
+ case QUIRK_ZXR_DBPRO:
9677
+ spec->adcs[0] = 0x8; /* ZxR DBPro Aux In */
9678
+
9679
+ spec->num_inputs = 1;
9680
+ spec->input_pins[0] = 0x11; /* RCA Line-in */
9681
+
9682
+ spec->dig_out = 0x05;
9683
+ spec->multiout.dig_out_nid = spec->dig_out;
9684
+
9685
+ spec->dig_in = 0x09;
9686
+ break;
9687
+ case QUIRK_AE5:
9688
+ case QUIRK_AE7:
9689
+ spec->num_outputs = 2;
9690
+ spec->out_pins[0] = 0x0B; /* Line out */
9691
+ spec->out_pins[1] = 0x11; /* Rear headphone out */
9692
+ spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
9693
+ spec->out_pins[3] = 0x0F; /* Rear surround */
9694
+ spec->shared_out_nid = 0x2;
9695
+ spec->unsol_tag_hp = spec->out_pins[1];
9696
+ spec->unsol_tag_front_hp = spec->out_pins[2];
9697
+
9698
+ spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
9699
+ spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */
9700
+ spec->adcs[2] = 0xa; /* what u hear */
9701
+
9702
+ spec->num_inputs = 2;
9703
+ spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
9704
+ spec->input_pins[1] = 0x13; /* What U Hear */
9705
+ spec->shared_mic_nid = 0x7;
9706
+ spec->unsol_tag_amic1 = spec->input_pins[0];
9707
+
9708
+ /* SPDIF I/O */
9709
+ spec->dig_out = 0x05;
9710
+ spec->multiout.dig_out_nid = spec->dig_out;
9711
+ break;
9712
+ case QUIRK_R3DI:
75139713 spec->num_outputs = 2;
75149714 spec->out_pins[0] = 0x0B; /* Line out */
75159715 spec->out_pins[1] = 0x0F; /* Rear headphone out */
....@@ -7566,7 +9766,11 @@
75669766 struct ca0132_spec *spec = codec->spec;
75679767
75689768 spec->chip_init_verbs = ca0132_init_verbs0;
7569
- if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3D)
9769
+ /*
9770
+ * Since desktop cards use pci_mmio, this can be used to determine
9771
+ * whether or not to use these verbs instead of a separate bool.
9772
+ */
9773
+ if (ca0132_use_pci_mmio(spec))
75709774 spec->desktop_init_verbs = ca0132_init_verbs1;
75719775 spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS,
75729776 sizeof(struct hda_verb),
....@@ -7598,6 +9802,29 @@
75989802 return 0;
75999803 }
76009804
9805
+/*
9806
+ * The Sound Blaster ZxR shares the same PCI subsystem ID as some regular
9807
+ * Sound Blaster Z cards. However, they have different HDA codec subsystem
9808
+ * ID's. So, we check for the ZxR's subsystem ID, as well as the DBPro
9809
+ * daughter boards ID.
9810
+ */
9811
+static void sbz_detect_quirk(struct hda_codec *codec)
9812
+{
9813
+ struct ca0132_spec *spec = codec->spec;
9814
+
9815
+ switch (codec->core.subsystem_id) {
9816
+ case 0x11020033:
9817
+ spec->quirk = QUIRK_ZXR;
9818
+ break;
9819
+ case 0x1102003f:
9820
+ spec->quirk = QUIRK_ZXR_DBPRO;
9821
+ break;
9822
+ default:
9823
+ spec->quirk = QUIRK_SBZ;
9824
+ break;
9825
+ }
9826
+}
9827
+
76019828 static int patch_ca0132(struct hda_codec *codec)
76029829 {
76039830 struct ca0132_spec *spec;
....@@ -7612,25 +9839,38 @@
76129839 codec->spec = spec;
76139840 spec->codec = codec;
76149841
7615
- codec->patch_ops = ca0132_patch_ops;
7616
- codec->pcm_format_first = 1;
7617
- codec->no_sticky_stream = 1;
7618
-
76199842 /* Detect codec quirk */
76209843 quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
76219844 if (quirk)
76229845 spec->quirk = quirk->value;
76239846 else
76249847 spec->quirk = QUIRK_NONE;
9848
+ if (ca0132_quirk(spec) == QUIRK_SBZ)
9849
+ sbz_detect_quirk(codec);
9850
+
9851
+ if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
9852
+ codec->patch_ops = dbpro_patch_ops;
9853
+ else
9854
+ codec->patch_ops = ca0132_patch_ops;
9855
+
9856
+ codec->pcm_format_first = 1;
9857
+ codec->no_sticky_stream = 1;
9858
+
76259859
76269860 spec->dsp_state = DSP_DOWNLOAD_INIT;
76279861 spec->num_mixers = 1;
76289862
76299863 /* Set which mixers each quirk uses. */
7630
- switch (spec->quirk) {
9864
+ switch (ca0132_quirk(spec)) {
76319865 case QUIRK_SBZ:
76329866 spec->mixers[0] = desktop_mixer;
76339867 snd_hda_codec_set_name(codec, "Sound Blaster Z");
9868
+ break;
9869
+ case QUIRK_ZXR:
9870
+ spec->mixers[0] = desktop_mixer;
9871
+ snd_hda_codec_set_name(codec, "Sound Blaster ZxR");
9872
+ break;
9873
+ case QUIRK_ZXR_DBPRO:
76349874 break;
76359875 case QUIRK_R3D:
76369876 spec->mixers[0] = desktop_mixer;
....@@ -7640,15 +9880,26 @@
76409880 spec->mixers[0] = r3di_mixer;
76419881 snd_hda_codec_set_name(codec, "Recon3Di");
76429882 break;
9883
+ case QUIRK_AE5:
9884
+ spec->mixers[0] = desktop_mixer;
9885
+ snd_hda_codec_set_name(codec, "Sound BlasterX AE-5");
9886
+ break;
9887
+ case QUIRK_AE7:
9888
+ spec->mixers[0] = desktop_mixer;
9889
+ snd_hda_codec_set_name(codec, "Sound Blaster AE-7");
9890
+ break;
76439891 default:
76449892 spec->mixers[0] = ca0132_mixer;
76459893 break;
76469894 }
76479895
76489896 /* Setup whether or not to use alt functions/controls/pci_mmio */
7649
- switch (spec->quirk) {
9897
+ switch (ca0132_quirk(spec)) {
76509898 case QUIRK_SBZ:
76519899 case QUIRK_R3D:
9900
+ case QUIRK_AE5:
9901
+ case QUIRK_AE7:
9902
+ case QUIRK_ZXR:
76529903 spec->use_alt_controls = true;
76539904 spec->use_alt_functions = true;
76549905 spec->use_pci_mmio = true;
....@@ -7665,6 +9916,7 @@
76659916 break;
76669917 }
76679918
9919
+#ifdef CONFIG_PCI
76689920 if (spec->use_pci_mmio) {
76699921 spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20);
76709922 if (spec->mem_base == NULL) {
....@@ -7672,6 +9924,7 @@
76729924 spec->quirk = QUIRK_NONE;
76739925 }
76749926 }
9927
+#endif
76759928
76769929 spec->base_init_verbs = ca0132_base_init_verbs;
76779930 spec->base_exit_verbs = ca0132_base_exit_verbs;
....@@ -7700,7 +9953,7 @@
77009953 /*
77019954 * patch entries
77029955 */
7703
-static struct hda_device_id snd_hda_id_ca0132[] = {
9956
+static const struct hda_device_id snd_hda_id_ca0132[] = {
77049957 HDA_CODEC_ENTRY(0x11020011, "CA0132", patch_ca0132),
77059958 {} /* terminator */
77069959 };