.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * HD audio interface patch for Creative CA0132 chip |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * |
---|
6 | 7 | * Based on patch_ca0110.c |
---|
7 | 8 | * 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 |
---|
22 | 9 | */ |
---|
23 | 10 | |
---|
24 | 11 | #include <linux/init.h> |
---|
.. | .. |
---|
33 | 20 | #include <linux/pci.h> |
---|
34 | 21 | #include <asm/io.h> |
---|
35 | 22 | #include <sound/core.h> |
---|
36 | | -#include "hda_codec.h" |
---|
| 23 | +#include <sound/hda_codec.h> |
---|
37 | 24 | #include "hda_local.h" |
---|
38 | 25 | #include "hda_auto_parser.h" |
---|
39 | 26 | #include "hda_jack.h" |
---|
.. | .. |
---|
51 | 38 | #define FLOAT_ONE 0x3f800000 |
---|
52 | 39 | #define FLOAT_TWO 0x40000000 |
---|
53 | 40 | #define FLOAT_THREE 0x40400000 |
---|
| 41 | +#define FLOAT_FIVE 0x40a00000 |
---|
| 42 | +#define FLOAT_SIX 0x40c00000 |
---|
54 | 43 | #define FLOAT_EIGHT 0x41000000 |
---|
55 | 44 | #define FLOAT_MINUS_5 0xc0a00000 |
---|
56 | 45 | |
---|
.. | .. |
---|
82 | 71 | #define SCP_GET 1 |
---|
83 | 72 | |
---|
84 | 73 | #define EFX_FILE "ctefx.bin" |
---|
85 | | -#define SBZ_EFX_FILE "ctefx-sbz.bin" |
---|
| 74 | +#define DESKTOP_EFX_FILE "ctefx-desktop.bin" |
---|
86 | 75 | #define R3DI_EFX_FILE "ctefx-r3di.bin" |
---|
87 | 76 | |
---|
88 | 77 | #ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP |
---|
89 | 78 | MODULE_FIRMWARE(EFX_FILE); |
---|
90 | | -MODULE_FIRMWARE(SBZ_EFX_FILE); |
---|
| 79 | +MODULE_FIRMWARE(DESKTOP_EFX_FILE); |
---|
91 | 80 | MODULE_FIRMWARE(R3DI_EFX_FILE); |
---|
92 | 81 | #endif |
---|
93 | 82 | |
---|
94 | 83 | static const char *const dirstr[2] = { "Playback", "Capture" }; |
---|
95 | 84 | |
---|
96 | | -#define NUM_OF_OUTPUTS 3 |
---|
| 85 | +#define NUM_OF_OUTPUTS 2 |
---|
| 86 | +static const char *const out_type_str[2] = { "Speakers", "Headphone" }; |
---|
97 | 87 | enum { |
---|
98 | 88 | SPEAKER_OUT, |
---|
99 | 89 | HEADPHONE_OUT, |
---|
100 | | - SURROUND_OUT |
---|
101 | 90 | }; |
---|
102 | 91 | |
---|
103 | 92 | enum { |
---|
.. | .. |
---|
153 | 142 | XBASS_XOVER, |
---|
154 | 143 | EQ_PRESET_ENUM, |
---|
155 | 144 | 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, |
---|
157 | 154 | #define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID) |
---|
158 | 155 | }; |
---|
159 | 156 | |
---|
.. | .. |
---|
599 | 596 | } |
---|
600 | 597 | }; |
---|
601 | 598 | |
---|
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, |
---|
610 | 615 | }; |
---|
611 | 616 | |
---|
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 |
---|
622 | 689 | }, |
---|
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 |
---|
632 | 692 | }, |
---|
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 |
---|
642 | 701 | } |
---|
643 | 702 | }; |
---|
644 | 703 | |
---|
.. | .. |
---|
667 | 726 | } |
---|
668 | 727 | }; |
---|
669 | 728 | |
---|
| 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 | + |
---|
670 | 791 | enum hda_cmd_vendor_io { |
---|
671 | 792 | /* for DspIO node */ |
---|
672 | 793 | VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000, |
---|
.. | .. |
---|
686 | 807 | VENDOR_CHIPIO_DATA_LOW = 0x300, |
---|
687 | 808 | VENDOR_CHIPIO_DATA_HIGH = 0x400, |
---|
688 | 809 | |
---|
| 810 | + VENDOR_CHIPIO_8051_WRITE_DIRECT = 0x500, |
---|
| 811 | + VENDOR_CHIPIO_8051_READ_DIRECT = 0xD00, |
---|
| 812 | + |
---|
689 | 813 | VENDOR_CHIPIO_GET_PARAMETER = 0xF00, |
---|
690 | 814 | VENDOR_CHIPIO_STATUS = 0xF01, |
---|
691 | 815 | VENDOR_CHIPIO_HIC_POST_READ = 0x702, |
---|
.. | .. |
---|
693 | 817 | |
---|
694 | 818 | VENDOR_CHIPIO_8051_DATA_WRITE = 0x707, |
---|
695 | 819 | 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, |
---|
696 | 823 | |
---|
697 | 824 | VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A, |
---|
698 | 825 | VENDOR_CHIPIO_CT_EXTENSIONS_GET = 0xF0A, |
---|
.. | .. |
---|
798 | 925 | /* Port D output stage gain setting to use when 16 Ohm output |
---|
799 | 926 | * impedance is selected*/ |
---|
800 | 927 | 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, |
---|
801 | 934 | |
---|
802 | 935 | /* Stream Control */ |
---|
803 | 936 | |
---|
.. | .. |
---|
931 | 1064 | unsigned int scp_resp_header; |
---|
932 | 1065 | unsigned int scp_resp_data[4]; |
---|
933 | 1066 | unsigned int scp_resp_count; |
---|
934 | | - bool alt_firmware_present; |
---|
935 | 1067 | bool startup_check_entered; |
---|
936 | 1068 | bool dsp_reload; |
---|
937 | 1069 | |
---|
.. | .. |
---|
949 | 1081 | /* ca0132_alt control related values */ |
---|
950 | 1082 | unsigned char in_enum_val; |
---|
951 | 1083 | unsigned char out_enum_val; |
---|
| 1084 | + unsigned char channel_cfg_val; |
---|
| 1085 | + unsigned char speaker_range_val[2]; |
---|
952 | 1086 | unsigned char mic_boost_enum_val; |
---|
953 | 1087 | unsigned char smart_volume_setting; |
---|
| 1088 | + unsigned char bass_redirection_val; |
---|
| 1089 | + long bass_redirect_xover_freq; |
---|
954 | 1090 | long fx_ctl_val[EFFECT_LEVEL_SLIDERS]; |
---|
955 | 1091 | long xbass_xover_freq; |
---|
956 | 1092 | long eq_preset_val; |
---|
957 | 1093 | unsigned int tlv[4]; |
---|
958 | 1094 | 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; |
---|
960 | 1100 | |
---|
961 | 1101 | struct hda_codec *codec; |
---|
962 | 1102 | struct delayed_work unsol_hp_work; |
---|
.. | .. |
---|
996 | 1136 | QUIRK_ALIENWARE, |
---|
997 | 1137 | QUIRK_ALIENWARE_M17XR4, |
---|
998 | 1138 | QUIRK_SBZ, |
---|
| 1139 | + QUIRK_ZXR, |
---|
| 1140 | + QUIRK_ZXR_DBPRO, |
---|
999 | 1141 | QUIRK_R3DI, |
---|
1000 | 1142 | QUIRK_R3D, |
---|
| 1143 | + QUIRK_AE5, |
---|
| 1144 | + QUIRK_AE7, |
---|
1001 | 1145 | }; |
---|
| 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 |
---|
1002 | 1158 | |
---|
1003 | 1159 | static const struct hda_pintbl alienware_pincfgs[] = { |
---|
1004 | 1160 | { 0x0b, 0x90170110 }, /* Builtin Speaker */ |
---|
.. | .. |
---|
1029 | 1185 | {} |
---|
1030 | 1186 | }; |
---|
1031 | 1187 | |
---|
| 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 | + |
---|
1032 | 1203 | /* Recon3D pin configs taken from Windows Driver */ |
---|
1033 | 1204 | static const struct hda_pintbl r3d_pincfgs[] = { |
---|
1034 | 1205 | { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */ |
---|
.. | .. |
---|
1039 | 1210 | { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */ |
---|
1040 | 1211 | { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */ |
---|
1041 | 1212 | { 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 */ |
---|
1042 | 1228 | { 0x13, 0x908700f0 }, /* What U Hear In*/ |
---|
1043 | 1229 | { 0x18, 0x50d000f0 }, /* N/A */ |
---|
1044 | 1230 | {} |
---|
.. | .. |
---|
1059 | 1245 | {} |
---|
1060 | 1246 | }; |
---|
1061 | 1247 | |
---|
| 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 | + |
---|
1062 | 1262 | static const struct snd_pci_quirk ca0132_quirks[] = { |
---|
1063 | 1263 | SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4), |
---|
1064 | 1264 | SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), |
---|
.. | .. |
---|
1066 | 1266 | SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE), |
---|
1067 | 1267 | SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ), |
---|
1068 | 1268 | 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), |
---|
1069 | 1271 | SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), |
---|
1070 | 1272 | SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), |
---|
1071 | 1273 | SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), |
---|
1072 | 1274 | SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), |
---|
| 1275 | + SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI), |
---|
| 1276 | + SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI), |
---|
1073 | 1277 | SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D), |
---|
| 1278 | + SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D), |
---|
| 1279 | + SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5), |
---|
| 1280 | + SND_PCI_QUIRK(0x1102, 0x0191, "Sound Blaster AE-5 Plus", QUIRK_AE5), |
---|
| 1281 | + SND_PCI_QUIRK(0x1102, 0x0081, "Sound Blaster AE-7", QUIRK_AE7), |
---|
1074 | 1282 | {} |
---|
| 1283 | +}; |
---|
| 1284 | + |
---|
| 1285 | +/* Output selection quirk info structures. */ |
---|
| 1286 | +#define MAX_QUIRK_MMIO_GPIO_SET_VALS 3 |
---|
| 1287 | +#define MAX_QUIRK_SCP_SET_VALS 2 |
---|
| 1288 | +struct ca0132_alt_out_set_info { |
---|
| 1289 | + unsigned int dac2port; /* ParamID 0x0d value. */ |
---|
| 1290 | + |
---|
| 1291 | + bool has_hda_gpio; |
---|
| 1292 | + char hda_gpio_pin; |
---|
| 1293 | + char hda_gpio_set; |
---|
| 1294 | + |
---|
| 1295 | + unsigned int mmio_gpio_count; |
---|
| 1296 | + char mmio_gpio_pin[MAX_QUIRK_MMIO_GPIO_SET_VALS]; |
---|
| 1297 | + char mmio_gpio_set[MAX_QUIRK_MMIO_GPIO_SET_VALS]; |
---|
| 1298 | + |
---|
| 1299 | + unsigned int scp_cmds_count; |
---|
| 1300 | + unsigned int scp_cmd_mid[MAX_QUIRK_SCP_SET_VALS]; |
---|
| 1301 | + unsigned int scp_cmd_req[MAX_QUIRK_SCP_SET_VALS]; |
---|
| 1302 | + unsigned int scp_cmd_val[MAX_QUIRK_SCP_SET_VALS]; |
---|
| 1303 | + |
---|
| 1304 | + bool has_chipio_write; |
---|
| 1305 | + unsigned int chipio_write_addr; |
---|
| 1306 | + unsigned int chipio_write_data; |
---|
| 1307 | +}; |
---|
| 1308 | + |
---|
| 1309 | +struct ca0132_alt_out_set_quirk_data { |
---|
| 1310 | + int quirk_id; |
---|
| 1311 | + |
---|
| 1312 | + bool has_headphone_gain; |
---|
| 1313 | + bool is_ae_series; |
---|
| 1314 | + |
---|
| 1315 | + struct ca0132_alt_out_set_info out_set_info[NUM_OF_OUTPUTS]; |
---|
| 1316 | +}; |
---|
| 1317 | + |
---|
| 1318 | +static const struct ca0132_alt_out_set_quirk_data quirk_out_set_data[] = { |
---|
| 1319 | + { .quirk_id = QUIRK_R3DI, |
---|
| 1320 | + .has_headphone_gain = false, |
---|
| 1321 | + .is_ae_series = false, |
---|
| 1322 | + .out_set_info = { |
---|
| 1323 | + /* Speakers. */ |
---|
| 1324 | + { .dac2port = 0x24, |
---|
| 1325 | + .has_hda_gpio = true, |
---|
| 1326 | + .hda_gpio_pin = 2, |
---|
| 1327 | + .hda_gpio_set = 1, |
---|
| 1328 | + .mmio_gpio_count = 0, |
---|
| 1329 | + .scp_cmds_count = 0, |
---|
| 1330 | + .has_chipio_write = false, |
---|
| 1331 | + }, |
---|
| 1332 | + /* Headphones. */ |
---|
| 1333 | + { .dac2port = 0x21, |
---|
| 1334 | + .has_hda_gpio = true, |
---|
| 1335 | + .hda_gpio_pin = 2, |
---|
| 1336 | + .hda_gpio_set = 0, |
---|
| 1337 | + .mmio_gpio_count = 0, |
---|
| 1338 | + .scp_cmds_count = 0, |
---|
| 1339 | + .has_chipio_write = false, |
---|
| 1340 | + } }, |
---|
| 1341 | + }, |
---|
| 1342 | + { .quirk_id = QUIRK_R3D, |
---|
| 1343 | + .has_headphone_gain = false, |
---|
| 1344 | + .is_ae_series = false, |
---|
| 1345 | + .out_set_info = { |
---|
| 1346 | + /* Speakers. */ |
---|
| 1347 | + { .dac2port = 0x24, |
---|
| 1348 | + .has_hda_gpio = false, |
---|
| 1349 | + .mmio_gpio_count = 1, |
---|
| 1350 | + .mmio_gpio_pin = { 1 }, |
---|
| 1351 | + .mmio_gpio_set = { 1 }, |
---|
| 1352 | + .scp_cmds_count = 0, |
---|
| 1353 | + .has_chipio_write = false, |
---|
| 1354 | + }, |
---|
| 1355 | + /* Headphones. */ |
---|
| 1356 | + { .dac2port = 0x21, |
---|
| 1357 | + .has_hda_gpio = false, |
---|
| 1358 | + .mmio_gpio_count = 1, |
---|
| 1359 | + .mmio_gpio_pin = { 1 }, |
---|
| 1360 | + .mmio_gpio_set = { 0 }, |
---|
| 1361 | + .scp_cmds_count = 0, |
---|
| 1362 | + .has_chipio_write = false, |
---|
| 1363 | + } }, |
---|
| 1364 | + }, |
---|
| 1365 | + { .quirk_id = QUIRK_SBZ, |
---|
| 1366 | + .has_headphone_gain = false, |
---|
| 1367 | + .is_ae_series = false, |
---|
| 1368 | + .out_set_info = { |
---|
| 1369 | + /* Speakers. */ |
---|
| 1370 | + { .dac2port = 0x18, |
---|
| 1371 | + .has_hda_gpio = false, |
---|
| 1372 | + .mmio_gpio_count = 3, |
---|
| 1373 | + .mmio_gpio_pin = { 7, 4, 1 }, |
---|
| 1374 | + .mmio_gpio_set = { 0, 1, 1 }, |
---|
| 1375 | + .scp_cmds_count = 0, |
---|
| 1376 | + .has_chipio_write = false, }, |
---|
| 1377 | + /* Headphones. */ |
---|
| 1378 | + { .dac2port = 0x12, |
---|
| 1379 | + .has_hda_gpio = false, |
---|
| 1380 | + .mmio_gpio_count = 3, |
---|
| 1381 | + .mmio_gpio_pin = { 7, 4, 1 }, |
---|
| 1382 | + .mmio_gpio_set = { 1, 1, 0 }, |
---|
| 1383 | + .scp_cmds_count = 0, |
---|
| 1384 | + .has_chipio_write = false, |
---|
| 1385 | + } }, |
---|
| 1386 | + }, |
---|
| 1387 | + { .quirk_id = QUIRK_ZXR, |
---|
| 1388 | + .has_headphone_gain = true, |
---|
| 1389 | + .is_ae_series = false, |
---|
| 1390 | + .out_set_info = { |
---|
| 1391 | + /* Speakers. */ |
---|
| 1392 | + { .dac2port = 0x24, |
---|
| 1393 | + .has_hda_gpio = false, |
---|
| 1394 | + .mmio_gpio_count = 3, |
---|
| 1395 | + .mmio_gpio_pin = { 2, 3, 5 }, |
---|
| 1396 | + .mmio_gpio_set = { 1, 1, 0 }, |
---|
| 1397 | + .scp_cmds_count = 0, |
---|
| 1398 | + .has_chipio_write = false, |
---|
| 1399 | + }, |
---|
| 1400 | + /* Headphones. */ |
---|
| 1401 | + { .dac2port = 0x21, |
---|
| 1402 | + .has_hda_gpio = false, |
---|
| 1403 | + .mmio_gpio_count = 3, |
---|
| 1404 | + .mmio_gpio_pin = { 2, 3, 5 }, |
---|
| 1405 | + .mmio_gpio_set = { 0, 1, 1 }, |
---|
| 1406 | + .scp_cmds_count = 0, |
---|
| 1407 | + .has_chipio_write = false, |
---|
| 1408 | + } }, |
---|
| 1409 | + }, |
---|
| 1410 | + { .quirk_id = QUIRK_AE5, |
---|
| 1411 | + .has_headphone_gain = true, |
---|
| 1412 | + .is_ae_series = true, |
---|
| 1413 | + .out_set_info = { |
---|
| 1414 | + /* Speakers. */ |
---|
| 1415 | + { .dac2port = 0xa4, |
---|
| 1416 | + .has_hda_gpio = false, |
---|
| 1417 | + .mmio_gpio_count = 0, |
---|
| 1418 | + .scp_cmds_count = 2, |
---|
| 1419 | + .scp_cmd_mid = { 0x96, 0x96 }, |
---|
| 1420 | + .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT, |
---|
| 1421 | + SPEAKER_TUNING_FRONT_RIGHT_INVERT }, |
---|
| 1422 | + .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO }, |
---|
| 1423 | + .has_chipio_write = true, |
---|
| 1424 | + .chipio_write_addr = 0x0018b03c, |
---|
| 1425 | + .chipio_write_data = 0x00000012 |
---|
| 1426 | + }, |
---|
| 1427 | + /* Headphones. */ |
---|
| 1428 | + { .dac2port = 0xa1, |
---|
| 1429 | + .has_hda_gpio = false, |
---|
| 1430 | + .mmio_gpio_count = 0, |
---|
| 1431 | + .scp_cmds_count = 2, |
---|
| 1432 | + .scp_cmd_mid = { 0x96, 0x96 }, |
---|
| 1433 | + .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT, |
---|
| 1434 | + SPEAKER_TUNING_FRONT_RIGHT_INVERT }, |
---|
| 1435 | + .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE }, |
---|
| 1436 | + .has_chipio_write = true, |
---|
| 1437 | + .chipio_write_addr = 0x0018b03c, |
---|
| 1438 | + .chipio_write_data = 0x00000012 |
---|
| 1439 | + } }, |
---|
| 1440 | + }, |
---|
| 1441 | + { .quirk_id = QUIRK_AE7, |
---|
| 1442 | + .has_headphone_gain = true, |
---|
| 1443 | + .is_ae_series = true, |
---|
| 1444 | + .out_set_info = { |
---|
| 1445 | + /* Speakers. */ |
---|
| 1446 | + { .dac2port = 0x58, |
---|
| 1447 | + .has_hda_gpio = false, |
---|
| 1448 | + .mmio_gpio_count = 1, |
---|
| 1449 | + .mmio_gpio_pin = { 0 }, |
---|
| 1450 | + .mmio_gpio_set = { 1 }, |
---|
| 1451 | + .scp_cmds_count = 2, |
---|
| 1452 | + .scp_cmd_mid = { 0x96, 0x96 }, |
---|
| 1453 | + .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT, |
---|
| 1454 | + SPEAKER_TUNING_FRONT_RIGHT_INVERT }, |
---|
| 1455 | + .scp_cmd_val = { FLOAT_ZERO, FLOAT_ZERO }, |
---|
| 1456 | + .has_chipio_write = true, |
---|
| 1457 | + .chipio_write_addr = 0x0018b03c, |
---|
| 1458 | + .chipio_write_data = 0x00000000 |
---|
| 1459 | + }, |
---|
| 1460 | + /* Headphones. */ |
---|
| 1461 | + { .dac2port = 0x58, |
---|
| 1462 | + .has_hda_gpio = false, |
---|
| 1463 | + .mmio_gpio_count = 1, |
---|
| 1464 | + .mmio_gpio_pin = { 0 }, |
---|
| 1465 | + .mmio_gpio_set = { 1 }, |
---|
| 1466 | + .scp_cmds_count = 2, |
---|
| 1467 | + .scp_cmd_mid = { 0x96, 0x96 }, |
---|
| 1468 | + .scp_cmd_req = { SPEAKER_TUNING_FRONT_LEFT_INVERT, |
---|
| 1469 | + SPEAKER_TUNING_FRONT_RIGHT_INVERT }, |
---|
| 1470 | + .scp_cmd_val = { FLOAT_ONE, FLOAT_ONE }, |
---|
| 1471 | + .has_chipio_write = true, |
---|
| 1472 | + .chipio_write_addr = 0x0018b03c, |
---|
| 1473 | + .chipio_write_data = 0x00000010 |
---|
| 1474 | + } }, |
---|
| 1475 | + } |
---|
1075 | 1476 | }; |
---|
1076 | 1477 | |
---|
1077 | 1478 | /* |
---|
.. | .. |
---|
1456 | 1857 | } |
---|
1457 | 1858 | |
---|
1458 | 1859 | /* |
---|
| 1860 | + * Writes to the 8051's internal address space directly instead of indirectly, |
---|
| 1861 | + * giving access to the special function registers located at addresses |
---|
| 1862 | + * 0x80-0xFF. |
---|
| 1863 | + */ |
---|
| 1864 | +static void chipio_8051_write_direct(struct hda_codec *codec, |
---|
| 1865 | + unsigned int addr, unsigned int data) |
---|
| 1866 | +{ |
---|
| 1867 | + unsigned int verb; |
---|
| 1868 | + |
---|
| 1869 | + verb = VENDOR_CHIPIO_8051_WRITE_DIRECT | data; |
---|
| 1870 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, verb, addr); |
---|
| 1871 | +} |
---|
| 1872 | + |
---|
| 1873 | +/* |
---|
1459 | 1874 | * Enable clocks. |
---|
1460 | 1875 | */ |
---|
1461 | 1876 | static void chipio_enable_clocks(struct hda_codec *codec) |
---|
.. | .. |
---|
1798 | 2213 | * Prepare and send the SCP message to DSP |
---|
1799 | 2214 | * @codec: the HDA codec |
---|
1800 | 2215 | * @mod_id: ID of the DSP module to send the command |
---|
| 2216 | + * @src_id: ID of the source |
---|
1801 | 2217 | * @req: ID of request to send to the DSP module |
---|
1802 | 2218 | * @dir: SET or GET |
---|
1803 | 2219 | * @data: pointer to the data to send with the request, request specific |
---|
.. | .. |
---|
1916 | 2332 | static int dspio_alloc_dma_chan(struct hda_codec *codec, unsigned int *dma_chan) |
---|
1917 | 2333 | { |
---|
1918 | 2334 | int status = 0; |
---|
1919 | | - unsigned int size = sizeof(dma_chan); |
---|
| 2335 | + unsigned int size = sizeof(*dma_chan); |
---|
1920 | 2336 | |
---|
1921 | 2337 | codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n"); |
---|
1922 | 2338 | status = dspio_scp(codec, MASTERCONTROL, 0x20, |
---|
.. | .. |
---|
2572 | 2988 | u32 magic; |
---|
2573 | 2989 | u32 chip_addr; |
---|
2574 | 2990 | u32 count; |
---|
2575 | | - u32 data[0]; |
---|
| 2991 | + u32 data[]; |
---|
2576 | 2992 | }; |
---|
2577 | 2993 | |
---|
2578 | 2994 | static const u32 g_magic_value = 0x4c46584d; |
---|
.. | .. |
---|
2595 | 3011 | |
---|
2596 | 3012 | static size_t dsp_sizeof(const struct dsp_image_seg *p) |
---|
2597 | 3013 | { |
---|
2598 | | - return sizeof(*p) + p->count*sizeof(u32); |
---|
| 3014 | + return struct_size(p, data, p->count); |
---|
2599 | 3015 | } |
---|
2600 | 3016 | |
---|
2601 | 3017 | static const struct dsp_image_seg *get_next_seg_ptr( |
---|
.. | .. |
---|
2701 | 3117 | } |
---|
2702 | 3118 | |
---|
2703 | 3119 | data = fls->data; |
---|
2704 | | - chip_addx = fls->chip_addr, |
---|
| 3120 | + chip_addx = fls->chip_addr; |
---|
2705 | 3121 | words_to_write = fls->count; |
---|
2706 | 3122 | |
---|
2707 | 3123 | if (!words_to_write) |
---|
.. | .. |
---|
2976 | 3392 | { |
---|
2977 | 3393 | struct ca0132_spec *spec = codec->spec; |
---|
2978 | 3394 | codec_dbg(codec, "---- dspload_post_setup ------\n"); |
---|
2979 | | - if (!spec->use_alt_functions) { |
---|
| 3395 | + if (!ca0132_use_alt_functions(spec)) { |
---|
2980 | 3396 | /*set DSP speaker to 2.0 configuration*/ |
---|
2981 | 3397 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080); |
---|
2982 | 3398 | chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000); |
---|
.. | .. |
---|
3091 | 3507 | } |
---|
3092 | 3508 | |
---|
3093 | 3509 | /* |
---|
3094 | | - * Setup GPIO for the other variants of Core3D. |
---|
| 3510 | + * ca0113 related functions. The ca0113 acts as the HDA bus for the pci-e |
---|
| 3511 | + * based cards, and has a second mmio region, region2, that's used for special |
---|
| 3512 | + * commands. |
---|
3095 | 3513 | */ |
---|
3096 | 3514 | |
---|
3097 | 3515 | /* |
---|
.. | .. |
---|
3099 | 3517 | * the mmio address 0x320 is used to set GPIO pins. The format for the data |
---|
3100 | 3518 | * The first eight bits are just the number of the pin. So far, I've only seen |
---|
3101 | 3519 | * this number go to 7. |
---|
| 3520 | + * AE-5 note: The AE-5 seems to use pins 2 and 3 to somehow set the color value |
---|
| 3521 | + * of the on-card LED. It seems to use pin 2 for data, then toggles 3 to on and |
---|
| 3522 | + * then off to send that bit. |
---|
3102 | 3523 | */ |
---|
3103 | | -static void ca0132_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin, |
---|
| 3524 | +static void ca0113_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin, |
---|
3104 | 3525 | bool enable) |
---|
3105 | 3526 | { |
---|
3106 | 3527 | struct ca0132_spec *spec = codec->spec; |
---|
.. | .. |
---|
3113 | 3534 | } |
---|
3114 | 3535 | |
---|
3115 | 3536 | /* |
---|
| 3537 | + * Special pci region2 commands that are only used by the AE-5. They follow |
---|
| 3538 | + * a set format, and require reads at certain points to seemingly 'clear' |
---|
| 3539 | + * the response data. My first tests didn't do these reads, and would cause |
---|
| 3540 | + * the card to get locked up until the memory was read. These commands |
---|
| 3541 | + * seem to work with three distinct values that I've taken to calling group, |
---|
| 3542 | + * target-id, and value. |
---|
| 3543 | + */ |
---|
| 3544 | +static void ca0113_mmio_command_set(struct hda_codec *codec, unsigned int group, |
---|
| 3545 | + unsigned int target, unsigned int value) |
---|
| 3546 | +{ |
---|
| 3547 | + struct ca0132_spec *spec = codec->spec; |
---|
| 3548 | + unsigned int write_val; |
---|
| 3549 | + |
---|
| 3550 | + writel(0x0000007e, spec->mem_base + 0x210); |
---|
| 3551 | + readl(spec->mem_base + 0x210); |
---|
| 3552 | + writel(0x0000005a, spec->mem_base + 0x210); |
---|
| 3553 | + readl(spec->mem_base + 0x210); |
---|
| 3554 | + readl(spec->mem_base + 0x210); |
---|
| 3555 | + |
---|
| 3556 | + writel(0x00800005, spec->mem_base + 0x20c); |
---|
| 3557 | + writel(group, spec->mem_base + 0x804); |
---|
| 3558 | + |
---|
| 3559 | + writel(0x00800005, spec->mem_base + 0x20c); |
---|
| 3560 | + write_val = (target & 0xff); |
---|
| 3561 | + write_val |= (value << 8); |
---|
| 3562 | + |
---|
| 3563 | + |
---|
| 3564 | + writel(write_val, spec->mem_base + 0x204); |
---|
| 3565 | + /* |
---|
| 3566 | + * Need delay here or else it goes too fast and works inconsistently. |
---|
| 3567 | + */ |
---|
| 3568 | + msleep(20); |
---|
| 3569 | + |
---|
| 3570 | + readl(spec->mem_base + 0x860); |
---|
| 3571 | + readl(spec->mem_base + 0x854); |
---|
| 3572 | + readl(spec->mem_base + 0x840); |
---|
| 3573 | + |
---|
| 3574 | + writel(0x00800004, spec->mem_base + 0x20c); |
---|
| 3575 | + writel(0x00000000, spec->mem_base + 0x210); |
---|
| 3576 | + readl(spec->mem_base + 0x210); |
---|
| 3577 | + readl(spec->mem_base + 0x210); |
---|
| 3578 | +} |
---|
| 3579 | + |
---|
| 3580 | +/* |
---|
| 3581 | + * This second type of command is used for setting the sound filter type. |
---|
| 3582 | + */ |
---|
| 3583 | +static void ca0113_mmio_command_set_type2(struct hda_codec *codec, |
---|
| 3584 | + unsigned int group, unsigned int target, unsigned int value) |
---|
| 3585 | +{ |
---|
| 3586 | + struct ca0132_spec *spec = codec->spec; |
---|
| 3587 | + unsigned int write_val; |
---|
| 3588 | + |
---|
| 3589 | + writel(0x0000007e, spec->mem_base + 0x210); |
---|
| 3590 | + readl(spec->mem_base + 0x210); |
---|
| 3591 | + writel(0x0000005a, spec->mem_base + 0x210); |
---|
| 3592 | + readl(spec->mem_base + 0x210); |
---|
| 3593 | + readl(spec->mem_base + 0x210); |
---|
| 3594 | + |
---|
| 3595 | + writel(0x00800003, spec->mem_base + 0x20c); |
---|
| 3596 | + writel(group, spec->mem_base + 0x804); |
---|
| 3597 | + |
---|
| 3598 | + writel(0x00800005, spec->mem_base + 0x20c); |
---|
| 3599 | + write_val = (target & 0xff); |
---|
| 3600 | + write_val |= (value << 8); |
---|
| 3601 | + |
---|
| 3602 | + |
---|
| 3603 | + writel(write_val, spec->mem_base + 0x204); |
---|
| 3604 | + msleep(20); |
---|
| 3605 | + readl(spec->mem_base + 0x860); |
---|
| 3606 | + readl(spec->mem_base + 0x854); |
---|
| 3607 | + readl(spec->mem_base + 0x840); |
---|
| 3608 | + |
---|
| 3609 | + writel(0x00800004, spec->mem_base + 0x20c); |
---|
| 3610 | + writel(0x00000000, spec->mem_base + 0x210); |
---|
| 3611 | + readl(spec->mem_base + 0x210); |
---|
| 3612 | + readl(spec->mem_base + 0x210); |
---|
| 3613 | +} |
---|
| 3614 | + |
---|
| 3615 | +/* |
---|
| 3616 | + * Setup GPIO for the other variants of Core3D. |
---|
| 3617 | + */ |
---|
| 3618 | + |
---|
| 3619 | +/* |
---|
3116 | 3620 | * Sets up the GPIO pins so that they are discoverable. If this isn't done, |
---|
3117 | 3621 | * the card shows as having no GPIO pins. |
---|
3118 | 3622 | */ |
---|
.. | .. |
---|
3120 | 3624 | { |
---|
3121 | 3625 | struct ca0132_spec *spec = codec->spec; |
---|
3122 | 3626 | |
---|
3123 | | - switch (spec->quirk) { |
---|
| 3627 | + switch (ca0132_quirk(spec)) { |
---|
3124 | 3628 | case QUIRK_SBZ: |
---|
| 3629 | + case QUIRK_AE5: |
---|
| 3630 | + case QUIRK_AE7: |
---|
3125 | 3631 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); |
---|
3126 | 3632 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); |
---|
3127 | 3633 | snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23); |
---|
.. | .. |
---|
3129 | 3635 | case QUIRK_R3DI: |
---|
3130 | 3636 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); |
---|
3131 | 3637 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5B); |
---|
| 3638 | + break; |
---|
| 3639 | + default: |
---|
3132 | 3640 | break; |
---|
3133 | 3641 | } |
---|
3134 | 3642 | |
---|
.. | .. |
---|
3139 | 3647 | { |
---|
3140 | 3648 | struct ca0132_spec *spec = codec->spec; |
---|
3141 | 3649 | |
---|
3142 | | - switch (spec->quirk) { |
---|
| 3650 | + switch (ca0132_quirk(spec)) { |
---|
3143 | 3651 | case QUIRK_SBZ: |
---|
3144 | 3652 | snd_hda_codec_write(codec, 0x01, 0, |
---|
3145 | 3653 | AC_VERB_SET_GPIO_DIRECTION, 0x07); |
---|
.. | .. |
---|
3157 | 3665 | AC_VERB_SET_GPIO_MASK, 0x1F); |
---|
3158 | 3666 | snd_hda_codec_write(codec, 0x01, 0, |
---|
3159 | 3667 | AC_VERB_SET_GPIO_DATA, 0x0C); |
---|
| 3668 | + break; |
---|
| 3669 | + default: |
---|
3160 | 3670 | break; |
---|
3161 | 3671 | } |
---|
3162 | 3672 | } |
---|
.. | .. |
---|
3217 | 3727 | break; |
---|
3218 | 3728 | case R3DI_FRONT_MIC: |
---|
3219 | 3729 | 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); |
---|
3240 | 3730 | break; |
---|
3241 | 3731 | } |
---|
3242 | 3732 | snd_hda_codec_write(codec, codec->core.afg, 0, |
---|
.. | .. |
---|
3550 | 4040 | /* The following are for tuning of products */ |
---|
3551 | 4041 | #ifdef ENABLE_TUNING_CONTROLS |
---|
3552 | 4042 | |
---|
3553 | | -static unsigned int voice_focus_vals_lookup[] = { |
---|
| 4043 | +static const unsigned int voice_focus_vals_lookup[] = { |
---|
3554 | 4044 | 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000, |
---|
3555 | 4045 | 0x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000, |
---|
3556 | 4046 | 0x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000, |
---|
.. | .. |
---|
3580 | 4070 | 0x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000 |
---|
3581 | 4071 | }; |
---|
3582 | 4072 | |
---|
3583 | | -static unsigned int mic_svm_vals_lookup[] = { |
---|
| 4073 | +static const unsigned int mic_svm_vals_lookup[] = { |
---|
3584 | 4074 | 0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD, |
---|
3585 | 4075 | 0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE, |
---|
3586 | 4076 | 0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B, |
---|
.. | .. |
---|
3600 | 4090 | 0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000 |
---|
3601 | 4091 | }; |
---|
3602 | 4092 | |
---|
3603 | | -static unsigned int equalizer_vals_lookup[] = { |
---|
| 4093 | +static const unsigned int equalizer_vals_lookup[] = { |
---|
3604 | 4094 | 0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000, |
---|
3605 | 4095 | 0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000, |
---|
3606 | 4096 | 0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000, |
---|
.. | .. |
---|
3613 | 4103 | }; |
---|
3614 | 4104 | |
---|
3615 | 4105 | static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid, |
---|
3616 | | - unsigned int *lookup, int idx) |
---|
| 4106 | + const unsigned int *lookup, int idx) |
---|
3617 | 4107 | { |
---|
3618 | 4108 | int i = 0; |
---|
3619 | 4109 | |
---|
3620 | 4110 | for (i = 0; i < TUNING_CTLS_COUNT; i++) |
---|
3621 | 4111 | if (nid == ca0132_tuning_ctls[i].nid) |
---|
3622 | | - break; |
---|
| 4112 | + goto found; |
---|
3623 | 4113 | |
---|
| 4114 | + return -EINVAL; |
---|
| 4115 | +found: |
---|
3624 | 4116 | snd_hda_power_up(codec); |
---|
3625 | 4117 | dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20, |
---|
3626 | 4118 | ca0132_tuning_ctls[i].req, |
---|
.. | .. |
---|
3931 | 4423 | return err < 0 ? err : 0; |
---|
3932 | 4424 | } |
---|
3933 | 4425 | |
---|
| 4426 | +static int ae5_headphone_gain_set(struct hda_codec *codec, long val); |
---|
| 4427 | +static int zxr_headphone_gain_set(struct hda_codec *codec, long val); |
---|
| 4428 | +static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val); |
---|
| 4429 | + |
---|
| 4430 | +static void ae5_mmio_select_out(struct hda_codec *codec) |
---|
| 4431 | +{ |
---|
| 4432 | + struct ca0132_spec *spec = codec->spec; |
---|
| 4433 | + const struct ae_ca0113_output_set *out_cmds; |
---|
| 4434 | + unsigned int i; |
---|
| 4435 | + |
---|
| 4436 | + if (ca0132_quirk(spec) == QUIRK_AE5) |
---|
| 4437 | + out_cmds = &ae5_ca0113_output_presets; |
---|
| 4438 | + else |
---|
| 4439 | + out_cmds = &ae7_ca0113_output_presets; |
---|
| 4440 | + |
---|
| 4441 | + for (i = 0; i < AE_CA0113_OUT_SET_COMMANDS; i++) |
---|
| 4442 | + ca0113_mmio_command_set(codec, out_cmds->group[i], |
---|
| 4443 | + out_cmds->target[i], |
---|
| 4444 | + out_cmds->vals[spec->cur_out_type][i]); |
---|
| 4445 | +} |
---|
| 4446 | + |
---|
| 4447 | +static int ca0132_alt_set_full_range_speaker(struct hda_codec *codec) |
---|
| 4448 | +{ |
---|
| 4449 | + struct ca0132_spec *spec = codec->spec; |
---|
| 4450 | + int quirk = ca0132_quirk(spec); |
---|
| 4451 | + unsigned int tmp; |
---|
| 4452 | + int err; |
---|
| 4453 | + |
---|
| 4454 | + /* 2.0/4.0 setup has no LFE channel, so setting full-range does nothing. */ |
---|
| 4455 | + if (spec->channel_cfg_val == SPEAKER_CHANNELS_4_0 |
---|
| 4456 | + || spec->channel_cfg_val == SPEAKER_CHANNELS_2_0) |
---|
| 4457 | + return 0; |
---|
| 4458 | + |
---|
| 4459 | + /* Set front L/R full range. Zero for full-range, one for redirection. */ |
---|
| 4460 | + tmp = spec->speaker_range_val[0] ? FLOAT_ZERO : FLOAT_ONE; |
---|
| 4461 | + err = dspio_set_uint_param(codec, 0x96, |
---|
| 4462 | + SPEAKER_FULL_RANGE_FRONT_L_R, tmp); |
---|
| 4463 | + if (err < 0) |
---|
| 4464 | + return err; |
---|
| 4465 | + |
---|
| 4466 | + /* When setting full-range rear, both rear and center/lfe are set. */ |
---|
| 4467 | + tmp = spec->speaker_range_val[1] ? FLOAT_ZERO : FLOAT_ONE; |
---|
| 4468 | + err = dspio_set_uint_param(codec, 0x96, |
---|
| 4469 | + SPEAKER_FULL_RANGE_CENTER_LFE, tmp); |
---|
| 4470 | + if (err < 0) |
---|
| 4471 | + return err; |
---|
| 4472 | + |
---|
| 4473 | + err = dspio_set_uint_param(codec, 0x96, |
---|
| 4474 | + SPEAKER_FULL_RANGE_REAR_L_R, tmp); |
---|
| 4475 | + if (err < 0) |
---|
| 4476 | + return err; |
---|
| 4477 | + |
---|
| 4478 | + /* |
---|
| 4479 | + * Only the AE series cards set this value when setting full-range, |
---|
| 4480 | + * and it's always 1.0f. |
---|
| 4481 | + */ |
---|
| 4482 | + if (quirk == QUIRK_AE5 || quirk == QUIRK_AE7) { |
---|
| 4483 | + err = dspio_set_uint_param(codec, 0x96, |
---|
| 4484 | + SPEAKER_FULL_RANGE_SURROUND_L_R, FLOAT_ONE); |
---|
| 4485 | + if (err < 0) |
---|
| 4486 | + return err; |
---|
| 4487 | + } |
---|
| 4488 | + |
---|
| 4489 | + return 0; |
---|
| 4490 | +} |
---|
| 4491 | + |
---|
| 4492 | +static int ca0132_alt_surround_set_bass_redirection(struct hda_codec *codec, |
---|
| 4493 | + bool val) |
---|
| 4494 | +{ |
---|
| 4495 | + struct ca0132_spec *spec = codec->spec; |
---|
| 4496 | + unsigned int tmp; |
---|
| 4497 | + int err; |
---|
| 4498 | + |
---|
| 4499 | + if (val && spec->channel_cfg_val != SPEAKER_CHANNELS_4_0 && |
---|
| 4500 | + spec->channel_cfg_val != SPEAKER_CHANNELS_2_0) |
---|
| 4501 | + tmp = FLOAT_ONE; |
---|
| 4502 | + else |
---|
| 4503 | + tmp = FLOAT_ZERO; |
---|
| 4504 | + |
---|
| 4505 | + err = dspio_set_uint_param(codec, 0x96, SPEAKER_BASS_REDIRECT, tmp); |
---|
| 4506 | + if (err < 0) |
---|
| 4507 | + return err; |
---|
| 4508 | + |
---|
| 4509 | + /* If it is enabled, make sure to set the crossover frequency. */ |
---|
| 4510 | + if (tmp) { |
---|
| 4511 | + tmp = float_xbass_xover_lookup[spec->xbass_xover_freq]; |
---|
| 4512 | + err = dspio_set_uint_param(codec, 0x96, |
---|
| 4513 | + SPEAKER_BASS_REDIRECT_XOVER_FREQ, tmp); |
---|
| 4514 | + if (err < 0) |
---|
| 4515 | + return err; |
---|
| 4516 | + } |
---|
| 4517 | + |
---|
| 4518 | + return 0; |
---|
| 4519 | +} |
---|
| 4520 | + |
---|
| 4521 | +/* |
---|
| 4522 | + * These are the commands needed to setup output on each of the different card |
---|
| 4523 | + * types. |
---|
| 4524 | + */ |
---|
| 4525 | +static void ca0132_alt_select_out_get_quirk_data(struct hda_codec *codec, |
---|
| 4526 | + const struct ca0132_alt_out_set_quirk_data **quirk_data) |
---|
| 4527 | +{ |
---|
| 4528 | + struct ca0132_spec *spec = codec->spec; |
---|
| 4529 | + int quirk = ca0132_quirk(spec); |
---|
| 4530 | + unsigned int i; |
---|
| 4531 | + |
---|
| 4532 | + *quirk_data = NULL; |
---|
| 4533 | + for (i = 0; i < ARRAY_SIZE(quirk_out_set_data); i++) { |
---|
| 4534 | + if (quirk_out_set_data[i].quirk_id == quirk) { |
---|
| 4535 | + *quirk_data = &quirk_out_set_data[i]; |
---|
| 4536 | + return; |
---|
| 4537 | + } |
---|
| 4538 | + } |
---|
| 4539 | +} |
---|
| 4540 | + |
---|
| 4541 | +static int ca0132_alt_select_out_quirk_set(struct hda_codec *codec) |
---|
| 4542 | +{ |
---|
| 4543 | + const struct ca0132_alt_out_set_quirk_data *quirk_data; |
---|
| 4544 | + const struct ca0132_alt_out_set_info *out_info; |
---|
| 4545 | + struct ca0132_spec *spec = codec->spec; |
---|
| 4546 | + unsigned int i, gpio_data; |
---|
| 4547 | + int err; |
---|
| 4548 | + |
---|
| 4549 | + ca0132_alt_select_out_get_quirk_data(codec, &quirk_data); |
---|
| 4550 | + if (!quirk_data) |
---|
| 4551 | + return 0; |
---|
| 4552 | + |
---|
| 4553 | + out_info = &quirk_data->out_set_info[spec->cur_out_type]; |
---|
| 4554 | + if (quirk_data->is_ae_series) |
---|
| 4555 | + ae5_mmio_select_out(codec); |
---|
| 4556 | + |
---|
| 4557 | + if (out_info->has_hda_gpio) { |
---|
| 4558 | + gpio_data = snd_hda_codec_read(codec, codec->core.afg, 0, |
---|
| 4559 | + AC_VERB_GET_GPIO_DATA, 0); |
---|
| 4560 | + |
---|
| 4561 | + if (out_info->hda_gpio_set) |
---|
| 4562 | + gpio_data |= (1 << out_info->hda_gpio_pin); |
---|
| 4563 | + else |
---|
| 4564 | + gpio_data &= ~(1 << out_info->hda_gpio_pin); |
---|
| 4565 | + |
---|
| 4566 | + snd_hda_codec_write(codec, codec->core.afg, 0, |
---|
| 4567 | + AC_VERB_SET_GPIO_DATA, gpio_data); |
---|
| 4568 | + } |
---|
| 4569 | + |
---|
| 4570 | + if (out_info->mmio_gpio_count) { |
---|
| 4571 | + for (i = 0; i < out_info->mmio_gpio_count; i++) { |
---|
| 4572 | + ca0113_mmio_gpio_set(codec, out_info->mmio_gpio_pin[i], |
---|
| 4573 | + out_info->mmio_gpio_set[i]); |
---|
| 4574 | + } |
---|
| 4575 | + } |
---|
| 4576 | + |
---|
| 4577 | + if (out_info->scp_cmds_count) { |
---|
| 4578 | + for (i = 0; i < out_info->scp_cmds_count; i++) { |
---|
| 4579 | + err = dspio_set_uint_param(codec, |
---|
| 4580 | + out_info->scp_cmd_mid[i], |
---|
| 4581 | + out_info->scp_cmd_req[i], |
---|
| 4582 | + out_info->scp_cmd_val[i]); |
---|
| 4583 | + if (err < 0) |
---|
| 4584 | + return err; |
---|
| 4585 | + } |
---|
| 4586 | + } |
---|
| 4587 | + |
---|
| 4588 | + chipio_set_control_param(codec, 0x0d, out_info->dac2port); |
---|
| 4589 | + |
---|
| 4590 | + if (out_info->has_chipio_write) { |
---|
| 4591 | + chipio_write(codec, out_info->chipio_write_addr, |
---|
| 4592 | + out_info->chipio_write_data); |
---|
| 4593 | + } |
---|
| 4594 | + |
---|
| 4595 | + if (quirk_data->has_headphone_gain) { |
---|
| 4596 | + if (spec->cur_out_type != HEADPHONE_OUT) { |
---|
| 4597 | + if (quirk_data->is_ae_series) |
---|
| 4598 | + ae5_headphone_gain_set(codec, 2); |
---|
| 4599 | + else |
---|
| 4600 | + zxr_headphone_gain_set(codec, 0); |
---|
| 4601 | + } else { |
---|
| 4602 | + if (quirk_data->is_ae_series) |
---|
| 4603 | + ae5_headphone_gain_set(codec, |
---|
| 4604 | + spec->ae5_headphone_gain_val); |
---|
| 4605 | + else |
---|
| 4606 | + zxr_headphone_gain_set(codec, |
---|
| 4607 | + spec->zxr_gain_set); |
---|
| 4608 | + } |
---|
| 4609 | + } |
---|
| 4610 | + |
---|
| 4611 | + return 0; |
---|
| 4612 | +} |
---|
| 4613 | + |
---|
| 4614 | +static void ca0132_set_out_node_pincfg(struct hda_codec *codec, hda_nid_t nid, |
---|
| 4615 | + bool out_enable, bool hp_enable) |
---|
| 4616 | +{ |
---|
| 4617 | + unsigned int pin_ctl; |
---|
| 4618 | + |
---|
| 4619 | + pin_ctl = snd_hda_codec_read(codec, nid, 0, |
---|
| 4620 | + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
---|
| 4621 | + |
---|
| 4622 | + pin_ctl = hp_enable ? pin_ctl | PIN_HP_AMP : pin_ctl & ~PIN_HP_AMP; |
---|
| 4623 | + pin_ctl = out_enable ? pin_ctl | PIN_OUT : pin_ctl & ~PIN_OUT; |
---|
| 4624 | + snd_hda_set_pin_ctl(codec, nid, pin_ctl); |
---|
| 4625 | +} |
---|
| 4626 | + |
---|
3934 | 4627 | /* |
---|
3935 | 4628 | * This function behaves similarly to the ca0132_select_out funciton above, |
---|
3936 | 4629 | * except with a few differences. It adds the ability to select the current |
---|
3937 | 4630 | * output with an enumerated control "output source" if the auto detect |
---|
3938 | 4631 | * mute switch is set to off. If the auto detect mute switch is enabled, it |
---|
3939 | 4632 | * will detect either headphone or lineout(SPEAKER_OUT) from jack detection. |
---|
3940 | | - * It also adds the ability to auto-detect the front headphone port. The only |
---|
3941 | | - * way to select surround is to disable auto detect, and set Surround with the |
---|
3942 | | - * enumerated control. |
---|
| 4633 | + * It also adds the ability to auto-detect the front headphone port. |
---|
3943 | 4634 | */ |
---|
3944 | 4635 | static int ca0132_alt_select_out(struct hda_codec *codec) |
---|
3945 | 4636 | { |
---|
3946 | 4637 | struct ca0132_spec *spec = codec->spec; |
---|
3947 | | - unsigned int pin_ctl; |
---|
| 4638 | + unsigned int tmp, outfx_set; |
---|
3948 | 4639 | int jack_present; |
---|
3949 | 4640 | int auto_jack; |
---|
3950 | | - unsigned int i; |
---|
3951 | | - unsigned int tmp; |
---|
3952 | 4641 | int err; |
---|
3953 | 4642 | /* Default Headphone is rear headphone */ |
---|
3954 | 4643 | hda_nid_t headphone_nid = spec->out_pins[1]; |
---|
.. | .. |
---|
3975 | 4664 | } else |
---|
3976 | 4665 | spec->cur_out_type = spec->out_enum_val; |
---|
3977 | 4666 | |
---|
3978 | | - /* Begin DSP output switch */ |
---|
3979 | | - tmp = FLOAT_ONE; |
---|
3980 | | - err = dspio_set_uint_param(codec, 0x96, 0x3A, tmp); |
---|
| 4667 | + outfx_set = spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]; |
---|
| 4668 | + |
---|
| 4669 | + /* Begin DSP output switch, mute DSP volume. */ |
---|
| 4670 | + err = dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_MUTE, FLOAT_ONE); |
---|
3981 | 4671 | if (err < 0) |
---|
| 4672 | + goto exit; |
---|
| 4673 | + |
---|
| 4674 | + if (ca0132_alt_select_out_quirk_set(codec) < 0) |
---|
3982 | 4675 | goto exit; |
---|
3983 | 4676 | |
---|
3984 | 4677 | switch (spec->cur_out_type) { |
---|
3985 | 4678 | case SPEAKER_OUT: |
---|
3986 | 4679 | 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 | | - } |
---|
4004 | 4680 | |
---|
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); |
---|
4015 | 4681 | /* Enable EAPD */ |
---|
4016 | 4682 | snd_hda_codec_write(codec, spec->out_pins[0], 0, |
---|
4017 | 4683 | AC_VERB_SET_EAPD_BTLENABLE, 0x01); |
---|
4018 | 4684 | |
---|
4019 | | - /* If PlayEnhancement is enabled, set different source */ |
---|
4020 | | - if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) |
---|
4021 | | - dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); |
---|
| 4685 | + /* Disable headphone node. */ |
---|
| 4686 | + ca0132_set_out_node_pincfg(codec, spec->out_pins[1], 0, 0); |
---|
| 4687 | + /* Set front L-R to output. */ |
---|
| 4688 | + ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 1, 0); |
---|
| 4689 | + /* Set Center/LFE to output. */ |
---|
| 4690 | + ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 1, 0); |
---|
| 4691 | + /* Set rear surround to output. */ |
---|
| 4692 | + ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 1, 0); |
---|
| 4693 | + |
---|
| 4694 | + /* |
---|
| 4695 | + * Without PlayEnhancement being enabled, if we've got a 2.0 |
---|
| 4696 | + * setup, set it to floating point eight to disable any DSP |
---|
| 4697 | + * processing effects. |
---|
| 4698 | + */ |
---|
| 4699 | + if (!outfx_set && spec->channel_cfg_val == SPEAKER_CHANNELS_2_0) |
---|
| 4700 | + tmp = FLOAT_EIGHT; |
---|
4022 | 4701 | else |
---|
4023 | | - dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT); |
---|
| 4702 | + tmp = speaker_channel_cfgs[spec->channel_cfg_val].val; |
---|
| 4703 | + |
---|
| 4704 | + err = dspio_set_uint_param(codec, 0x80, 0x04, tmp); |
---|
| 4705 | + if (err < 0) |
---|
| 4706 | + goto exit; |
---|
| 4707 | + |
---|
4024 | 4708 | break; |
---|
4025 | 4709 | case HEADPHONE_OUT: |
---|
4026 | 4710 | 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 | | - |
---|
4045 | 4711 | snd_hda_codec_write(codec, spec->out_pins[0], 0, |
---|
4046 | 4712 | AC_VERB_SET_EAPD_BTLENABLE, 0x00); |
---|
4047 | 4713 | |
---|
4048 | | - /* disable speaker*/ |
---|
4049 | | - pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, |
---|
4050 | | - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
---|
4051 | | - snd_hda_set_pin_ctl(codec, spec->out_pins[0], |
---|
4052 | | - pin_ctl & ~PIN_HP); |
---|
| 4714 | + /* Disable all speaker nodes. */ |
---|
| 4715 | + ca0132_set_out_node_pincfg(codec, spec->out_pins[0], 0, 0); |
---|
| 4716 | + ca0132_set_out_node_pincfg(codec, spec->out_pins[2], 0, 0); |
---|
| 4717 | + ca0132_set_out_node_pincfg(codec, spec->out_pins[3], 0, 0); |
---|
4053 | 4718 | |
---|
4054 | 4719 | /* enable headphone, either front or rear */ |
---|
4055 | | - |
---|
4056 | 4720 | if (snd_hda_jack_detect(codec, spec->unsol_tag_front_hp)) |
---|
4057 | 4721 | headphone_nid = spec->out_pins[2]; |
---|
4058 | 4722 | else if (snd_hda_jack_detect(codec, spec->unsol_tag_hp)) |
---|
4059 | 4723 | headphone_nid = spec->out_pins[1]; |
---|
4060 | 4724 | |
---|
4061 | | - pin_ctl = snd_hda_codec_read(codec, headphone_nid, 0, |
---|
4062 | | - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
---|
4063 | | - snd_hda_set_pin_ctl(codec, headphone_nid, |
---|
4064 | | - pin_ctl | PIN_HP); |
---|
| 4725 | + ca0132_set_out_node_pincfg(codec, headphone_nid, 1, 1); |
---|
4065 | 4726 | |
---|
4066 | | - if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) |
---|
4067 | | - dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); |
---|
| 4727 | + if (outfx_set) |
---|
| 4728 | + err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); |
---|
4068 | 4729 | else |
---|
4069 | | - dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO); |
---|
4070 | | - break; |
---|
4071 | | - case SURROUND_OUT: |
---|
4072 | | - codec_dbg(codec, "%s surround\n", __func__); |
---|
4073 | | - /* Surround out config*/ |
---|
4074 | | - switch (spec->quirk) { |
---|
4075 | | - case QUIRK_SBZ: |
---|
4076 | | - ca0132_mmio_gpio_set(codec, 7, false); |
---|
4077 | | - ca0132_mmio_gpio_set(codec, 4, true); |
---|
4078 | | - ca0132_mmio_gpio_set(codec, 1, true); |
---|
4079 | | - chipio_set_control_param(codec, 0x0D, 0x18); |
---|
4080 | | - break; |
---|
4081 | | - case QUIRK_R3DI: |
---|
4082 | | - chipio_set_control_param(codec, 0x0D, 0x24); |
---|
4083 | | - r3di_gpio_out_set(codec, R3DI_LINE_OUT); |
---|
4084 | | - break; |
---|
4085 | | - case QUIRK_R3D: |
---|
4086 | | - ca0132_mmio_gpio_set(codec, 1, true); |
---|
4087 | | - chipio_set_control_param(codec, 0x0D, 0x24); |
---|
4088 | | - break; |
---|
4089 | | - } |
---|
4090 | | - /* enable line out node */ |
---|
4091 | | - pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0, |
---|
4092 | | - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
---|
4093 | | - snd_hda_set_pin_ctl(codec, spec->out_pins[0], |
---|
4094 | | - pin_ctl | PIN_OUT); |
---|
4095 | | - /* Disable headphone out */ |
---|
4096 | | - pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0, |
---|
4097 | | - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
---|
4098 | | - snd_hda_set_pin_ctl(codec, spec->out_pins[1], |
---|
4099 | | - pin_ctl & ~PIN_HP); |
---|
4100 | | - /* Enable EAPD on line out */ |
---|
4101 | | - snd_hda_codec_write(codec, spec->out_pins[0], 0, |
---|
4102 | | - AC_VERB_SET_EAPD_BTLENABLE, 0x01); |
---|
4103 | | - /* enable center/lfe out node */ |
---|
4104 | | - pin_ctl = snd_hda_codec_read(codec, spec->out_pins[2], 0, |
---|
4105 | | - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
---|
4106 | | - snd_hda_set_pin_ctl(codec, spec->out_pins[2], |
---|
4107 | | - pin_ctl | PIN_OUT); |
---|
4108 | | - /* Now set rear surround node as out. */ |
---|
4109 | | - pin_ctl = snd_hda_codec_read(codec, spec->out_pins[3], 0, |
---|
4110 | | - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
---|
4111 | | - snd_hda_set_pin_ctl(codec, spec->out_pins[3], |
---|
4112 | | - pin_ctl | PIN_OUT); |
---|
| 4730 | + err = dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO); |
---|
4113 | 4731 | |
---|
4114 | | - if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) |
---|
4115 | | - dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE); |
---|
4116 | | - else |
---|
4117 | | - dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT); |
---|
| 4732 | + if (err < 0) |
---|
| 4733 | + goto exit; |
---|
4118 | 4734 | break; |
---|
4119 | 4735 | } |
---|
| 4736 | + /* |
---|
| 4737 | + * If output effects are enabled, set the X-Bass effect value again to |
---|
| 4738 | + * make sure that it's properly enabled/disabled for speaker |
---|
| 4739 | + * configurations with an LFE channel. |
---|
| 4740 | + */ |
---|
| 4741 | + if (outfx_set) |
---|
| 4742 | + ca0132_effects_set(codec, X_BASS, |
---|
| 4743 | + spec->effects_switch[X_BASS - EFFECT_START_NID]); |
---|
4120 | 4744 | |
---|
4121 | | - /* run through the output dsp commands for line-out */ |
---|
4122 | | - for (i = 0; i < alt_out_presets[spec->cur_out_type].commands; i++) { |
---|
4123 | | - err = dspio_set_uint_param(codec, |
---|
4124 | | - alt_out_presets[spec->cur_out_type].mids[i], |
---|
4125 | | - alt_out_presets[spec->cur_out_type].reqs[i], |
---|
4126 | | - alt_out_presets[spec->cur_out_type].vals[i]); |
---|
| 4745 | + /* Set speaker EQ bypass attenuation to 0. */ |
---|
| 4746 | + err = dspio_set_uint_param(codec, 0x8f, 0x01, FLOAT_ZERO); |
---|
| 4747 | + if (err < 0) |
---|
| 4748 | + goto exit; |
---|
4127 | 4749 | |
---|
| 4750 | + /* |
---|
| 4751 | + * Although unused on all cards but the AE series, this is always set |
---|
| 4752 | + * to zero when setting the output. |
---|
| 4753 | + */ |
---|
| 4754 | + err = dspio_set_uint_param(codec, 0x96, |
---|
| 4755 | + SPEAKER_TUNING_USE_SPEAKER_EQ, FLOAT_ZERO); |
---|
| 4756 | + if (err < 0) |
---|
| 4757 | + goto exit; |
---|
| 4758 | + |
---|
| 4759 | + if (spec->cur_out_type == SPEAKER_OUT) |
---|
| 4760 | + err = ca0132_alt_surround_set_bass_redirection(codec, |
---|
| 4761 | + spec->bass_redirection_val); |
---|
| 4762 | + else |
---|
| 4763 | + err = ca0132_alt_surround_set_bass_redirection(codec, 0); |
---|
| 4764 | + |
---|
| 4765 | + /* Unmute DSP now that we're done with output selection. */ |
---|
| 4766 | + err = dspio_set_uint_param(codec, 0x96, |
---|
| 4767 | + SPEAKER_TUNING_MUTE, FLOAT_ZERO); |
---|
| 4768 | + if (err < 0) |
---|
| 4769 | + goto exit; |
---|
| 4770 | + |
---|
| 4771 | + if (spec->cur_out_type == SPEAKER_OUT) { |
---|
| 4772 | + err = ca0132_alt_set_full_range_speaker(codec); |
---|
4128 | 4773 | if (err < 0) |
---|
4129 | 4774 | goto exit; |
---|
4130 | 4775 | } |
---|
.. | .. |
---|
4141 | 4786 | to_delayed_work(work), struct ca0132_spec, unsol_hp_work); |
---|
4142 | 4787 | struct hda_jack_tbl *jack; |
---|
4143 | 4788 | |
---|
4144 | | - if (spec->use_alt_functions) |
---|
| 4789 | + if (ca0132_use_alt_functions(spec)) |
---|
4145 | 4790 | ca0132_alt_select_out(spec->codec); |
---|
4146 | 4791 | else |
---|
4147 | 4792 | ca0132_select_out(spec->codec); |
---|
.. | .. |
---|
4155 | 4800 | |
---|
4156 | 4801 | static void ca0132_set_dmic(struct hda_codec *codec, int enable); |
---|
4157 | 4802 | 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); |
---|
4159 | 4803 | static void resume_mic1(struct hda_codec *codec, unsigned int oldval); |
---|
4160 | 4804 | static int stop_mic1(struct hda_codec *codec); |
---|
4161 | 4805 | static int ca0132_cvoice_switch_set(struct hda_codec *codec); |
---|
.. | .. |
---|
4226 | 4870 | |
---|
4227 | 4871 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); |
---|
4228 | 4872 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); |
---|
4229 | | - if (spec->quirk == QUIRK_R3DI) |
---|
| 4873 | + if (ca0132_quirk(spec) == QUIRK_R3DI) |
---|
4230 | 4874 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); |
---|
4231 | 4875 | |
---|
4232 | 4876 | |
---|
4233 | 4877 | if (spec->in_enum_val == REAR_LINE_IN) |
---|
4234 | 4878 | tmp = FLOAT_ZERO; |
---|
4235 | 4879 | else { |
---|
4236 | | - if (spec->quirk == QUIRK_SBZ) |
---|
| 4880 | + if (ca0132_quirk(spec) == QUIRK_SBZ) |
---|
4237 | 4881 | tmp = FLOAT_THREE; |
---|
4238 | 4882 | else |
---|
4239 | 4883 | tmp = FLOAT_ONE; |
---|
.. | .. |
---|
4245 | 4889 | codec_dbg(codec, "%s: on.", __func__); |
---|
4246 | 4890 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000); |
---|
4247 | 4891 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000); |
---|
4248 | | - if (spec->quirk == QUIRK_R3DI) |
---|
| 4892 | + if (ca0132_quirk(spec) == QUIRK_R3DI) |
---|
4249 | 4893 | chipio_set_conn_rate(codec, 0x0F, SR_16_000); |
---|
4250 | 4894 | |
---|
4251 | 4895 | if (spec->effects_switch[VOICE_FOCUS - EFFECT_START_NID]) |
---|
.. | .. |
---|
4341 | 4985 | |
---|
4342 | 4986 | switch (spec->cur_mic_type) { |
---|
4343 | 4987 | case REAR_MIC: |
---|
4344 | | - switch (spec->quirk) { |
---|
| 4988 | + switch (ca0132_quirk(spec)) { |
---|
4345 | 4989 | case QUIRK_SBZ: |
---|
4346 | 4990 | case QUIRK_R3D: |
---|
4347 | | - ca0132_mmio_gpio_set(codec, 0, false); |
---|
| 4991 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
| 4992 | + tmp = FLOAT_THREE; |
---|
| 4993 | + break; |
---|
| 4994 | + case QUIRK_ZXR: |
---|
4348 | 4995 | tmp = FLOAT_THREE; |
---|
4349 | 4996 | break; |
---|
4350 | 4997 | case QUIRK_R3DI: |
---|
4351 | 4998 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); |
---|
4352 | 4999 | tmp = FLOAT_ONE; |
---|
| 5000 | + break; |
---|
| 5001 | + case QUIRK_AE5: |
---|
| 5002 | + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); |
---|
| 5003 | + tmp = FLOAT_THREE; |
---|
| 5004 | + break; |
---|
| 5005 | + case QUIRK_AE7: |
---|
| 5006 | + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); |
---|
| 5007 | + tmp = FLOAT_THREE; |
---|
| 5008 | + chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, |
---|
| 5009 | + SR_96_000); |
---|
| 5010 | + chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, |
---|
| 5011 | + SR_96_000); |
---|
| 5012 | + dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO); |
---|
4353 | 5013 | break; |
---|
4354 | 5014 | default: |
---|
4355 | 5015 | tmp = FLOAT_ONE; |
---|
.. | .. |
---|
4358 | 5018 | |
---|
4359 | 5019 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); |
---|
4360 | 5020 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); |
---|
4361 | | - if (spec->quirk == QUIRK_R3DI) |
---|
| 5021 | + if (ca0132_quirk(spec) == QUIRK_R3DI) |
---|
4362 | 5022 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); |
---|
4363 | 5023 | |
---|
4364 | 5024 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); |
---|
4365 | 5025 | |
---|
4366 | 5026 | chipio_set_stream_control(codec, 0x03, 1); |
---|
4367 | 5027 | chipio_set_stream_control(codec, 0x04, 1); |
---|
4368 | | - |
---|
4369 | | - if (spec->quirk == QUIRK_SBZ) { |
---|
| 5028 | + switch (ca0132_quirk(spec)) { |
---|
| 5029 | + case QUIRK_SBZ: |
---|
4370 | 5030 | chipio_write(codec, 0x18B098, 0x0000000C); |
---|
4371 | 5031 | chipio_write(codec, 0x18B09C, 0x0000000C); |
---|
| 5032 | + break; |
---|
| 5033 | + case QUIRK_ZXR: |
---|
| 5034 | + chipio_write(codec, 0x18B098, 0x0000000C); |
---|
| 5035 | + chipio_write(codec, 0x18B09C, 0x000000CC); |
---|
| 5036 | + break; |
---|
| 5037 | + case QUIRK_AE5: |
---|
| 5038 | + chipio_write(codec, 0x18B098, 0x0000000C); |
---|
| 5039 | + chipio_write(codec, 0x18B09C, 0x0000004C); |
---|
| 5040 | + break; |
---|
| 5041 | + default: |
---|
| 5042 | + break; |
---|
4372 | 5043 | } |
---|
4373 | 5044 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); |
---|
4374 | 5045 | break; |
---|
4375 | 5046 | case REAR_LINE_IN: |
---|
4376 | 5047 | ca0132_mic_boost_set(codec, 0); |
---|
4377 | | - switch (spec->quirk) { |
---|
| 5048 | + switch (ca0132_quirk(spec)) { |
---|
4378 | 5049 | case QUIRK_SBZ: |
---|
4379 | 5050 | case QUIRK_R3D: |
---|
4380 | | - ca0132_mmio_gpio_set(codec, 0, false); |
---|
| 5051 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
4381 | 5052 | break; |
---|
4382 | 5053 | case QUIRK_R3DI: |
---|
4383 | 5054 | r3di_gpio_mic_set(codec, R3DI_REAR_MIC); |
---|
| 5055 | + break; |
---|
| 5056 | + case QUIRK_AE5: |
---|
| 5057 | + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); |
---|
| 5058 | + break; |
---|
| 5059 | + case QUIRK_AE7: |
---|
| 5060 | + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f); |
---|
| 5061 | + chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, |
---|
| 5062 | + SR_96_000); |
---|
| 5063 | + chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, |
---|
| 5064 | + SR_96_000); |
---|
| 5065 | + dspio_set_uint_param(codec, 0x80, 0x01, FLOAT_ZERO); |
---|
| 5066 | + break; |
---|
| 5067 | + default: |
---|
4384 | 5068 | break; |
---|
4385 | 5069 | } |
---|
4386 | 5070 | |
---|
4387 | 5071 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); |
---|
4388 | 5072 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); |
---|
4389 | | - if (spec->quirk == QUIRK_R3DI) |
---|
| 5073 | + if (ca0132_quirk(spec) == QUIRK_R3DI) |
---|
4390 | 5074 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); |
---|
4391 | 5075 | |
---|
4392 | | - tmp = FLOAT_ZERO; |
---|
| 5076 | + if (ca0132_quirk(spec) == QUIRK_AE7) |
---|
| 5077 | + tmp = FLOAT_THREE; |
---|
| 5078 | + else |
---|
| 5079 | + tmp = FLOAT_ZERO; |
---|
4393 | 5080 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); |
---|
4394 | 5081 | |
---|
4395 | | - if (spec->quirk == QUIRK_SBZ) { |
---|
| 5082 | + switch (ca0132_quirk(spec)) { |
---|
| 5083 | + case QUIRK_SBZ: |
---|
| 5084 | + case QUIRK_AE5: |
---|
4396 | 5085 | chipio_write(codec, 0x18B098, 0x00000000); |
---|
4397 | 5086 | chipio_write(codec, 0x18B09C, 0x00000000); |
---|
| 5087 | + break; |
---|
| 5088 | + default: |
---|
| 5089 | + break; |
---|
4398 | 5090 | } |
---|
4399 | | - |
---|
4400 | 5091 | chipio_set_stream_control(codec, 0x03, 1); |
---|
4401 | 5092 | chipio_set_stream_control(codec, 0x04, 1); |
---|
4402 | 5093 | break; |
---|
4403 | 5094 | case FRONT_MIC: |
---|
4404 | | - switch (spec->quirk) { |
---|
| 5095 | + switch (ca0132_quirk(spec)) { |
---|
4405 | 5096 | case QUIRK_SBZ: |
---|
4406 | 5097 | case QUIRK_R3D: |
---|
4407 | | - ca0132_mmio_gpio_set(codec, 0, true); |
---|
4408 | | - ca0132_mmio_gpio_set(codec, 5, false); |
---|
| 5098 | + ca0113_mmio_gpio_set(codec, 0, true); |
---|
| 5099 | + ca0113_mmio_gpio_set(codec, 5, false); |
---|
4409 | 5100 | tmp = FLOAT_THREE; |
---|
4410 | 5101 | break; |
---|
4411 | 5102 | case QUIRK_R3DI: |
---|
4412 | 5103 | r3di_gpio_mic_set(codec, R3DI_FRONT_MIC); |
---|
4413 | 5104 | tmp = FLOAT_ONE; |
---|
4414 | 5105 | break; |
---|
| 5106 | + case QUIRK_AE5: |
---|
| 5107 | + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f); |
---|
| 5108 | + tmp = FLOAT_THREE; |
---|
| 5109 | + break; |
---|
4415 | 5110 | default: |
---|
4416 | 5111 | tmp = FLOAT_ONE; |
---|
4417 | 5112 | break; |
---|
.. | .. |
---|
4419 | 5114 | |
---|
4420 | 5115 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); |
---|
4421 | 5116 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); |
---|
4422 | | - if (spec->quirk == QUIRK_R3DI) |
---|
| 5117 | + if (ca0132_quirk(spec) == QUIRK_R3DI) |
---|
4423 | 5118 | chipio_set_conn_rate(codec, 0x0F, SR_96_000); |
---|
4424 | 5119 | |
---|
4425 | 5120 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); |
---|
.. | .. |
---|
4427 | 5122 | chipio_set_stream_control(codec, 0x03, 1); |
---|
4428 | 5123 | chipio_set_stream_control(codec, 0x04, 1); |
---|
4429 | 5124 | |
---|
4430 | | - if (spec->quirk == QUIRK_SBZ) { |
---|
| 5125 | + switch (ca0132_quirk(spec)) { |
---|
| 5126 | + case QUIRK_SBZ: |
---|
4431 | 5127 | chipio_write(codec, 0x18B098, 0x0000000C); |
---|
4432 | 5128 | chipio_write(codec, 0x18B09C, 0x000000CC); |
---|
| 5129 | + break; |
---|
| 5130 | + case QUIRK_AE5: |
---|
| 5131 | + chipio_write(codec, 0x18B098, 0x0000000C); |
---|
| 5132 | + chipio_write(codec, 0x18B09C, 0x0000004C); |
---|
| 5133 | + break; |
---|
| 5134 | + default: |
---|
| 5135 | + break; |
---|
4433 | 5136 | } |
---|
4434 | 5137 | ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); |
---|
4435 | 5138 | break; |
---|
.. | .. |
---|
4438 | 5141 | |
---|
4439 | 5142 | snd_hda_power_down_pm(codec); |
---|
4440 | 5143 | return 0; |
---|
4441 | | - |
---|
4442 | 5144 | } |
---|
4443 | 5145 | |
---|
4444 | 5146 | /* |
---|
.. | .. |
---|
4497 | 5199 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) |
---|
4498 | 5200 | { |
---|
4499 | 5201 | struct ca0132_spec *spec = codec->spec; |
---|
4500 | | - unsigned int on, tmp; |
---|
| 5202 | + unsigned int on, tmp, channel_cfg; |
---|
4501 | 5203 | int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; |
---|
4502 | 5204 | int err = 0; |
---|
4503 | 5205 | int idx = nid - EFFECT_START_NID; |
---|
.. | .. |
---|
4510 | 5212 | /* if PE if off, turn off out effects. */ |
---|
4511 | 5213 | if (!spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) |
---|
4512 | 5214 | val = 0; |
---|
| 5215 | + if (spec->cur_out_type == SPEAKER_OUT && nid == X_BASS) { |
---|
| 5216 | + channel_cfg = spec->channel_cfg_val; |
---|
| 5217 | + if (channel_cfg != SPEAKER_CHANNELS_2_0 && |
---|
| 5218 | + channel_cfg != SPEAKER_CHANNELS_4_0) |
---|
| 5219 | + val = 0; |
---|
| 5220 | + } |
---|
4513 | 5221 | } |
---|
4514 | 5222 | |
---|
4515 | 5223 | /* for in effect, qualify with CrystalVoice */ |
---|
.. | .. |
---|
4523 | 5231 | val = 0; |
---|
4524 | 5232 | |
---|
4525 | 5233 | /* If Voice Focus on SBZ, set to two channel. */ |
---|
4526 | | - if ((nid == VOICE_FOCUS) && (spec->use_pci_mmio) |
---|
| 5234 | + if ((nid == VOICE_FOCUS) && ca0132_use_pci_mmio(spec) |
---|
4527 | 5235 | && (spec->cur_mic_type != REAR_LINE_IN)) { |
---|
4528 | 5236 | if (spec->effects_switch[CRYSTAL_VOICE - |
---|
4529 | 5237 | EFFECT_START_NID]) { |
---|
.. | .. |
---|
4542 | 5250 | * For SBZ noise reduction, there's an extra command |
---|
4543 | 5251 | * to module ID 0x47. No clue why. |
---|
4544 | 5252 | */ |
---|
4545 | | - if ((nid == NOISE_REDUCTION) && (spec->use_pci_mmio) |
---|
| 5253 | + if ((nid == NOISE_REDUCTION) && ca0132_use_pci_mmio(spec) |
---|
4546 | 5254 | && (spec->cur_mic_type != REAR_LINE_IN)) { |
---|
4547 | 5255 | if (spec->effects_switch[CRYSTAL_VOICE - |
---|
4548 | 5256 | EFFECT_START_NID]) { |
---|
.. | .. |
---|
4558 | 5266 | } |
---|
4559 | 5267 | |
---|
4560 | 5268 | /* If rear line in disable effects. */ |
---|
4561 | | - if (spec->use_alt_functions && |
---|
| 5269 | + if (ca0132_use_alt_functions(spec) && |
---|
4562 | 5270 | spec->in_enum_val == REAR_LINE_IN) |
---|
4563 | 5271 | val = 0; |
---|
4564 | 5272 | } |
---|
.. | .. |
---|
4588 | 5296 | codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n", |
---|
4589 | 5297 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]); |
---|
4590 | 5298 | |
---|
4591 | | - if (spec->use_alt_functions) |
---|
| 5299 | + if (ca0132_use_alt_functions(spec)) |
---|
4592 | 5300 | ca0132_alt_select_out(codec); |
---|
4593 | 5301 | |
---|
4594 | 5302 | i = OUT_EFFECT_START_NID - EFFECT_START_NID; |
---|
.. | .. |
---|
4648 | 5356 | |
---|
4649 | 5357 | /* set correct vipsource */ |
---|
4650 | 5358 | oldval = stop_mic1(codec); |
---|
4651 | | - if (spec->use_alt_functions) |
---|
| 5359 | + if (ca0132_use_alt_functions(spec)) |
---|
4652 | 5360 | ret |= ca0132_alt_set_vipsource(codec, 1); |
---|
4653 | 5361 | else |
---|
4654 | 5362 | ret |= ca0132_set_vipsource(codec, 1); |
---|
.. | .. |
---|
4681 | 5389 | return ret; |
---|
4682 | 5390 | } |
---|
4683 | 5391 | |
---|
| 5392 | +static int ae5_headphone_gain_set(struct hda_codec *codec, long val) |
---|
| 5393 | +{ |
---|
| 5394 | + unsigned int i; |
---|
| 5395 | + |
---|
| 5396 | + for (i = 0; i < 4; i++) |
---|
| 5397 | + ca0113_mmio_command_set(codec, 0x48, 0x11 + i, |
---|
| 5398 | + ae5_headphone_gain_presets[val].vals[i]); |
---|
| 5399 | + return 0; |
---|
| 5400 | +} |
---|
| 5401 | + |
---|
| 5402 | +/* |
---|
| 5403 | + * gpio pin 1 is a relay that switches on/off, apparently setting the headphone |
---|
| 5404 | + * amplifier to handle a 600 ohm load. |
---|
| 5405 | + */ |
---|
| 5406 | +static int zxr_headphone_gain_set(struct hda_codec *codec, long val) |
---|
| 5407 | +{ |
---|
| 5408 | + ca0113_mmio_gpio_set(codec, 1, val); |
---|
| 5409 | + |
---|
| 5410 | + return 0; |
---|
| 5411 | +} |
---|
| 5412 | + |
---|
4684 | 5413 | static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, |
---|
4685 | 5414 | struct snd_ctl_elem_value *ucontrol) |
---|
4686 | 5415 | { |
---|
.. | .. |
---|
4696 | 5425 | auto_jack = |
---|
4697 | 5426 | spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; |
---|
4698 | 5427 | if (!auto_jack) { |
---|
4699 | | - if (spec->use_alt_functions) |
---|
| 5428 | + if (ca0132_use_alt_functions(spec)) |
---|
4700 | 5429 | ca0132_alt_select_out(codec); |
---|
4701 | 5430 | else |
---|
4702 | 5431 | ca0132_select_out(codec); |
---|
.. | .. |
---|
4713 | 5442 | } |
---|
4714 | 5443 | |
---|
4715 | 5444 | if (nid == VNID_HP_ASEL) { |
---|
4716 | | - if (spec->use_alt_functions) |
---|
| 5445 | + if (ca0132_use_alt_functions(spec)) |
---|
4717 | 5446 | ca0132_alt_select_out(codec); |
---|
4718 | 5447 | else |
---|
4719 | 5448 | ca0132_select_out(codec); |
---|
.. | .. |
---|
4744 | 5473 | return ret; |
---|
4745 | 5474 | } |
---|
4746 | 5475 | /* End of control change helpers. */ |
---|
| 5476 | + |
---|
| 5477 | +static void ca0132_alt_bass_redirection_xover_set(struct hda_codec *codec, |
---|
| 5478 | + long idx) |
---|
| 5479 | +{ |
---|
| 5480 | + snd_hda_power_up(codec); |
---|
| 5481 | + |
---|
| 5482 | + dspio_set_param(codec, 0x96, 0x20, SPEAKER_BASS_REDIRECT_XOVER_FREQ, |
---|
| 5483 | + &(float_xbass_xover_lookup[idx]), sizeof(unsigned int)); |
---|
| 5484 | + |
---|
| 5485 | + snd_hda_power_down(codec); |
---|
| 5486 | +} |
---|
| 5487 | + |
---|
4747 | 5488 | /* |
---|
4748 | 5489 | * Below I've added controls to mess with the effect levels, I've only enabled |
---|
4749 | 5490 | * them on the Sound Blaster Z, but they would probably also work on the |
---|
.. | .. |
---|
4752 | 5493 | */ |
---|
4753 | 5494 | |
---|
4754 | 5495 | /* Sets DSP effect level from the sliders above the controls */ |
---|
| 5496 | + |
---|
4755 | 5497 | static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid, |
---|
4756 | 5498 | const unsigned int *lookup, int idx) |
---|
4757 | 5499 | { |
---|
.. | .. |
---|
4797 | 5539 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
---|
4798 | 5540 | struct ca0132_spec *spec = codec->spec; |
---|
4799 | 5541 | long *valp = ucontrol->value.integer.value; |
---|
| 5542 | + hda_nid_t nid = get_amp_nid(kcontrol); |
---|
4800 | 5543 | |
---|
4801 | | - *valp = spec->xbass_xover_freq; |
---|
| 5544 | + if (nid == BASS_REDIRECTION_XOVER) |
---|
| 5545 | + *valp = spec->bass_redirect_xover_freq; |
---|
| 5546 | + else |
---|
| 5547 | + *valp = spec->xbass_xover_freq; |
---|
| 5548 | + |
---|
4802 | 5549 | return 0; |
---|
4803 | 5550 | } |
---|
4804 | 5551 | |
---|
.. | .. |
---|
4852 | 5599 | struct ca0132_spec *spec = codec->spec; |
---|
4853 | 5600 | hda_nid_t nid = get_amp_nid(kcontrol); |
---|
4854 | 5601 | long *valp = ucontrol->value.integer.value; |
---|
| 5602 | + long *cur_val; |
---|
4855 | 5603 | int idx; |
---|
4856 | 5604 | |
---|
| 5605 | + if (nid == BASS_REDIRECTION_XOVER) |
---|
| 5606 | + cur_val = &spec->bass_redirect_xover_freq; |
---|
| 5607 | + else |
---|
| 5608 | + cur_val = &spec->xbass_xover_freq; |
---|
| 5609 | + |
---|
4857 | 5610 | /* any change? */ |
---|
4858 | | - if (spec->xbass_xover_freq == *valp) |
---|
| 5611 | + if (*cur_val == *valp) |
---|
4859 | 5612 | return 0; |
---|
4860 | 5613 | |
---|
4861 | | - spec->xbass_xover_freq = *valp; |
---|
| 5614 | + *cur_val = *valp; |
---|
4862 | 5615 | |
---|
4863 | 5616 | idx = *valp; |
---|
4864 | | - ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx); |
---|
| 5617 | + if (nid == BASS_REDIRECTION_XOVER) |
---|
| 5618 | + ca0132_alt_bass_redirection_xover_set(codec, *cur_val); |
---|
| 5619 | + else |
---|
| 5620 | + ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx); |
---|
4865 | 5621 | |
---|
4866 | 5622 | return 0; |
---|
4867 | 5623 | } |
---|
.. | .. |
---|
4945 | 5701 | return 1; |
---|
4946 | 5702 | } |
---|
4947 | 5703 | |
---|
| 5704 | +/* |
---|
| 5705 | + * Sound BlasterX AE-5 Headphone Gain Controls. |
---|
| 5706 | + */ |
---|
| 5707 | +#define AE5_HEADPHONE_GAIN_MAX 3 |
---|
| 5708 | +static int ae5_headphone_gain_info(struct snd_kcontrol *kcontrol, |
---|
| 5709 | + struct snd_ctl_elem_info *uinfo) |
---|
| 5710 | +{ |
---|
| 5711 | + char *sfx = " Ohms)"; |
---|
| 5712 | + char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
---|
| 5713 | + |
---|
| 5714 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
---|
| 5715 | + uinfo->count = 1; |
---|
| 5716 | + uinfo->value.enumerated.items = AE5_HEADPHONE_GAIN_MAX; |
---|
| 5717 | + if (uinfo->value.enumerated.item >= AE5_HEADPHONE_GAIN_MAX) |
---|
| 5718 | + uinfo->value.enumerated.item = AE5_HEADPHONE_GAIN_MAX - 1; |
---|
| 5719 | + sprintf(namestr, "%s %s", |
---|
| 5720 | + ae5_headphone_gain_presets[uinfo->value.enumerated.item].name, |
---|
| 5721 | + sfx); |
---|
| 5722 | + strcpy(uinfo->value.enumerated.name, namestr); |
---|
| 5723 | + return 0; |
---|
| 5724 | +} |
---|
| 5725 | + |
---|
| 5726 | +static int ae5_headphone_gain_get(struct snd_kcontrol *kcontrol, |
---|
| 5727 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 5728 | +{ |
---|
| 5729 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
---|
| 5730 | + struct ca0132_spec *spec = codec->spec; |
---|
| 5731 | + |
---|
| 5732 | + ucontrol->value.enumerated.item[0] = spec->ae5_headphone_gain_val; |
---|
| 5733 | + return 0; |
---|
| 5734 | +} |
---|
| 5735 | + |
---|
| 5736 | +static int ae5_headphone_gain_put(struct snd_kcontrol *kcontrol, |
---|
| 5737 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 5738 | +{ |
---|
| 5739 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
---|
| 5740 | + struct ca0132_spec *spec = codec->spec; |
---|
| 5741 | + int sel = ucontrol->value.enumerated.item[0]; |
---|
| 5742 | + unsigned int items = AE5_HEADPHONE_GAIN_MAX; |
---|
| 5743 | + |
---|
| 5744 | + if (sel >= items) |
---|
| 5745 | + return 0; |
---|
| 5746 | + |
---|
| 5747 | + codec_dbg(codec, "ae5_headphone_gain: boost=%d\n", |
---|
| 5748 | + sel); |
---|
| 5749 | + |
---|
| 5750 | + spec->ae5_headphone_gain_val = sel; |
---|
| 5751 | + |
---|
| 5752 | + if (spec->out_enum_val == HEADPHONE_OUT) |
---|
| 5753 | + ae5_headphone_gain_set(codec, spec->ae5_headphone_gain_val); |
---|
| 5754 | + |
---|
| 5755 | + return 1; |
---|
| 5756 | +} |
---|
| 5757 | + |
---|
| 5758 | +/* |
---|
| 5759 | + * Sound BlasterX AE-5 sound filter enumerated control. |
---|
| 5760 | + */ |
---|
| 5761 | +#define AE5_SOUND_FILTER_MAX 3 |
---|
| 5762 | + |
---|
| 5763 | +static int ae5_sound_filter_info(struct snd_kcontrol *kcontrol, |
---|
| 5764 | + struct snd_ctl_elem_info *uinfo) |
---|
| 5765 | +{ |
---|
| 5766 | + char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
---|
| 5767 | + |
---|
| 5768 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
---|
| 5769 | + uinfo->count = 1; |
---|
| 5770 | + uinfo->value.enumerated.items = AE5_SOUND_FILTER_MAX; |
---|
| 5771 | + if (uinfo->value.enumerated.item >= AE5_SOUND_FILTER_MAX) |
---|
| 5772 | + uinfo->value.enumerated.item = AE5_SOUND_FILTER_MAX - 1; |
---|
| 5773 | + sprintf(namestr, "%s", |
---|
| 5774 | + ae5_filter_presets[uinfo->value.enumerated.item].name); |
---|
| 5775 | + strcpy(uinfo->value.enumerated.name, namestr); |
---|
| 5776 | + return 0; |
---|
| 5777 | +} |
---|
| 5778 | + |
---|
| 5779 | +static int ae5_sound_filter_get(struct snd_kcontrol *kcontrol, |
---|
| 5780 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 5781 | +{ |
---|
| 5782 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
---|
| 5783 | + struct ca0132_spec *spec = codec->spec; |
---|
| 5784 | + |
---|
| 5785 | + ucontrol->value.enumerated.item[0] = spec->ae5_filter_val; |
---|
| 5786 | + return 0; |
---|
| 5787 | +} |
---|
| 5788 | + |
---|
| 5789 | +static int ae5_sound_filter_put(struct snd_kcontrol *kcontrol, |
---|
| 5790 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 5791 | +{ |
---|
| 5792 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
---|
| 5793 | + struct ca0132_spec *spec = codec->spec; |
---|
| 5794 | + int sel = ucontrol->value.enumerated.item[0]; |
---|
| 5795 | + unsigned int items = AE5_SOUND_FILTER_MAX; |
---|
| 5796 | + |
---|
| 5797 | + if (sel >= items) |
---|
| 5798 | + return 0; |
---|
| 5799 | + |
---|
| 5800 | + codec_dbg(codec, "ae5_sound_filter: %s\n", |
---|
| 5801 | + ae5_filter_presets[sel].name); |
---|
| 5802 | + |
---|
| 5803 | + spec->ae5_filter_val = sel; |
---|
| 5804 | + |
---|
| 5805 | + ca0113_mmio_command_set_type2(codec, 0x48, 0x07, |
---|
| 5806 | + ae5_filter_presets[sel].val); |
---|
| 5807 | + |
---|
| 5808 | + return 1; |
---|
| 5809 | +} |
---|
4948 | 5810 | |
---|
4949 | 5811 | /* |
---|
4950 | 5812 | * Input Select Control for alternative ca0132 codecs. This exists because |
---|
.. | .. |
---|
4982 | 5844 | int sel = ucontrol->value.enumerated.item[0]; |
---|
4983 | 5845 | unsigned int items = IN_SRC_NUM_OF_INPUTS; |
---|
4984 | 5846 | |
---|
| 5847 | + /* |
---|
| 5848 | + * The AE-7 has no front microphone, so limit items to 2: rear mic and |
---|
| 5849 | + * line-in. |
---|
| 5850 | + */ |
---|
| 5851 | + if (ca0132_quirk(spec) == QUIRK_AE7) |
---|
| 5852 | + items = 2; |
---|
| 5853 | + |
---|
4985 | 5854 | if (sel >= items) |
---|
4986 | 5855 | return 0; |
---|
4987 | 5856 | |
---|
.. | .. |
---|
5005 | 5874 | if (uinfo->value.enumerated.item >= NUM_OF_OUTPUTS) |
---|
5006 | 5875 | uinfo->value.enumerated.item = NUM_OF_OUTPUTS - 1; |
---|
5007 | 5876 | strcpy(uinfo->value.enumerated.name, |
---|
5008 | | - alt_out_presets[uinfo->value.enumerated.item].name); |
---|
| 5877 | + out_type_str[uinfo->value.enumerated.item]); |
---|
5009 | 5878 | return 0; |
---|
5010 | 5879 | } |
---|
5011 | 5880 | |
---|
.. | .. |
---|
5032 | 5901 | return 0; |
---|
5033 | 5902 | |
---|
5034 | 5903 | codec_dbg(codec, "ca0132_alt_output_select: sel=%d, preset=%s\n", |
---|
5035 | | - sel, alt_out_presets[sel].name); |
---|
| 5904 | + sel, out_type_str[sel]); |
---|
5036 | 5905 | |
---|
5037 | 5906 | spec->out_enum_val = sel; |
---|
5038 | 5907 | |
---|
5039 | 5908 | auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; |
---|
5040 | 5909 | |
---|
5041 | 5910 | if (!auto_jack) |
---|
| 5911 | + ca0132_alt_select_out(codec); |
---|
| 5912 | + |
---|
| 5913 | + return 1; |
---|
| 5914 | +} |
---|
| 5915 | + |
---|
| 5916 | +/* Select surround output type: 2.1, 4.0, 4.1, or 5.1. */ |
---|
| 5917 | +static int ca0132_alt_speaker_channel_cfg_get_info(struct snd_kcontrol *kcontrol, |
---|
| 5918 | + struct snd_ctl_elem_info *uinfo) |
---|
| 5919 | +{ |
---|
| 5920 | + unsigned int items = SPEAKER_CHANNEL_CFG_COUNT; |
---|
| 5921 | + |
---|
| 5922 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
---|
| 5923 | + uinfo->count = 1; |
---|
| 5924 | + uinfo->value.enumerated.items = items; |
---|
| 5925 | + if (uinfo->value.enumerated.item >= items) |
---|
| 5926 | + uinfo->value.enumerated.item = items - 1; |
---|
| 5927 | + strcpy(uinfo->value.enumerated.name, |
---|
| 5928 | + speaker_channel_cfgs[uinfo->value.enumerated.item].name); |
---|
| 5929 | + return 0; |
---|
| 5930 | +} |
---|
| 5931 | + |
---|
| 5932 | +static int ca0132_alt_speaker_channel_cfg_get(struct snd_kcontrol *kcontrol, |
---|
| 5933 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 5934 | +{ |
---|
| 5935 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
---|
| 5936 | + struct ca0132_spec *spec = codec->spec; |
---|
| 5937 | + |
---|
| 5938 | + ucontrol->value.enumerated.item[0] = spec->channel_cfg_val; |
---|
| 5939 | + return 0; |
---|
| 5940 | +} |
---|
| 5941 | + |
---|
| 5942 | +static int ca0132_alt_speaker_channel_cfg_put(struct snd_kcontrol *kcontrol, |
---|
| 5943 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 5944 | +{ |
---|
| 5945 | + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
---|
| 5946 | + struct ca0132_spec *spec = codec->spec; |
---|
| 5947 | + int sel = ucontrol->value.enumerated.item[0]; |
---|
| 5948 | + unsigned int items = SPEAKER_CHANNEL_CFG_COUNT; |
---|
| 5949 | + |
---|
| 5950 | + if (sel >= items) |
---|
| 5951 | + return 0; |
---|
| 5952 | + |
---|
| 5953 | + codec_dbg(codec, "ca0132_alt_speaker_channels: sel=%d, channels=%s\n", |
---|
| 5954 | + sel, speaker_channel_cfgs[sel].name); |
---|
| 5955 | + |
---|
| 5956 | + spec->channel_cfg_val = sel; |
---|
| 5957 | + |
---|
| 5958 | + if (spec->out_enum_val == SPEAKER_OUT) |
---|
5042 | 5959 | ca0132_alt_select_out(codec); |
---|
5043 | 5960 | |
---|
5044 | 5961 | return 1; |
---|
.. | .. |
---|
5265 | 6182 | return 0; |
---|
5266 | 6183 | } |
---|
5267 | 6184 | |
---|
| 6185 | + if (nid == ZXR_HEADPHONE_GAIN) { |
---|
| 6186 | + *valp = spec->zxr_gain_set; |
---|
| 6187 | + return 0; |
---|
| 6188 | + } |
---|
| 6189 | + |
---|
| 6190 | + if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) { |
---|
| 6191 | + *valp = spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT]; |
---|
| 6192 | + return 0; |
---|
| 6193 | + } |
---|
| 6194 | + |
---|
| 6195 | + if (nid == BASS_REDIRECTION) { |
---|
| 6196 | + *valp = spec->bass_redirection_val; |
---|
| 6197 | + return 0; |
---|
| 6198 | + } |
---|
| 6199 | + |
---|
5268 | 6200 | return 0; |
---|
5269 | 6201 | } |
---|
5270 | 6202 | |
---|
.. | .. |
---|
5321 | 6253 | /* mic boost */ |
---|
5322 | 6254 | if (nid == spec->input_pins[0]) { |
---|
5323 | 6255 | spec->cur_mic_boost = *valp; |
---|
5324 | | - if (spec->use_alt_functions) { |
---|
| 6256 | + if (ca0132_use_alt_functions(spec)) { |
---|
5325 | 6257 | if (spec->in_enum_val != REAR_LINE_IN) |
---|
5326 | 6258 | changed = ca0132_mic_boost_set(codec, *valp); |
---|
5327 | 6259 | } else { |
---|
.. | .. |
---|
5331 | 6263 | } |
---|
5332 | 6264 | |
---|
5333 | 6265 | goto exit; |
---|
| 6266 | + } |
---|
| 6267 | + |
---|
| 6268 | + if (nid == ZXR_HEADPHONE_GAIN) { |
---|
| 6269 | + spec->zxr_gain_set = *valp; |
---|
| 6270 | + if (spec->cur_out_type == HEADPHONE_OUT) |
---|
| 6271 | + changed = zxr_headphone_gain_set(codec, *valp); |
---|
| 6272 | + else |
---|
| 6273 | + changed = 0; |
---|
| 6274 | + |
---|
| 6275 | + goto exit; |
---|
| 6276 | + } |
---|
| 6277 | + |
---|
| 6278 | + if (nid == SPEAKER_FULL_RANGE_FRONT || nid == SPEAKER_FULL_RANGE_REAR) { |
---|
| 6279 | + spec->speaker_range_val[nid - SPEAKER_FULL_RANGE_FRONT] = *valp; |
---|
| 6280 | + if (spec->cur_out_type == SPEAKER_OUT) |
---|
| 6281 | + ca0132_alt_set_full_range_speaker(codec); |
---|
| 6282 | + |
---|
| 6283 | + changed = 0; |
---|
| 6284 | + } |
---|
| 6285 | + |
---|
| 6286 | + if (nid == BASS_REDIRECTION) { |
---|
| 6287 | + spec->bass_redirection_val = *valp; |
---|
| 6288 | + if (spec->cur_out_type == SPEAKER_OUT) |
---|
| 6289 | + ca0132_alt_surround_set_bass_redirection(codec, *valp); |
---|
| 6290 | + |
---|
| 6291 | + changed = 0; |
---|
5334 | 6292 | } |
---|
5335 | 6293 | |
---|
5336 | 6294 | exit: |
---|
.. | .. |
---|
5491 | 6449 | int ch = get_amp_channels(kcontrol); |
---|
5492 | 6450 | long *valp = ucontrol->value.integer.value; |
---|
5493 | 6451 | hda_nid_t vnid = 0; |
---|
5494 | | - int changed = 1; |
---|
| 6452 | + int changed; |
---|
5495 | 6453 | |
---|
5496 | 6454 | switch (nid) { |
---|
5497 | 6455 | case 0x02: |
---|
.. | .. |
---|
5607 | 6565 | /* If using alt_controls, add FX: prefix. But, don't add FX: |
---|
5608 | 6566 | * prefix to OutFX or InFX enable controls. |
---|
5609 | 6567 | */ |
---|
5610 | | - if ((spec->use_alt_controls) && (nid <= IN_EFFECT_END_NID)) |
---|
| 6568 | + if (ca0132_use_alt_controls(spec) && (nid <= IN_EFFECT_END_NID)) |
---|
5611 | 6569 | sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]); |
---|
5612 | 6570 | else |
---|
5613 | 6571 | sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); |
---|
.. | .. |
---|
5674 | 6632 | } |
---|
5675 | 6633 | |
---|
5676 | 6634 | /* |
---|
| 6635 | + * Add a control for selecting channel count on speaker output. Setting this |
---|
| 6636 | + * allows the DSP to do bass redirection and channel upmixing on surround |
---|
| 6637 | + * configurations. |
---|
| 6638 | + */ |
---|
| 6639 | +static int ca0132_alt_add_speaker_channel_cfg_enum(struct hda_codec *codec) |
---|
| 6640 | +{ |
---|
| 6641 | + struct snd_kcontrol_new knew = |
---|
| 6642 | + HDA_CODEC_MUTE_MONO("Surround Channel Config", |
---|
| 6643 | + SPEAKER_CHANNEL_CFG_ENUM, 1, 0, HDA_OUTPUT); |
---|
| 6644 | + knew.info = ca0132_alt_speaker_channel_cfg_get_info; |
---|
| 6645 | + knew.get = ca0132_alt_speaker_channel_cfg_get; |
---|
| 6646 | + knew.put = ca0132_alt_speaker_channel_cfg_put; |
---|
| 6647 | + return snd_hda_ctl_add(codec, SPEAKER_CHANNEL_CFG_ENUM, |
---|
| 6648 | + snd_ctl_new1(&knew, codec)); |
---|
| 6649 | +} |
---|
| 6650 | + |
---|
| 6651 | +/* |
---|
| 6652 | + * Full range front stereo and rear surround switches. When these are set to |
---|
| 6653 | + * full range, the lower frequencies from these channels are no longer |
---|
| 6654 | + * redirected to the LFE channel. |
---|
| 6655 | + */ |
---|
| 6656 | +static int ca0132_alt_add_front_full_range_switch(struct hda_codec *codec) |
---|
| 6657 | +{ |
---|
| 6658 | + struct snd_kcontrol_new knew = |
---|
| 6659 | + CA0132_CODEC_MUTE_MONO("Full-Range Front Speakers", |
---|
| 6660 | + SPEAKER_FULL_RANGE_FRONT, 1, HDA_OUTPUT); |
---|
| 6661 | + |
---|
| 6662 | + return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_FRONT, |
---|
| 6663 | + snd_ctl_new1(&knew, codec)); |
---|
| 6664 | +} |
---|
| 6665 | + |
---|
| 6666 | +static int ca0132_alt_add_rear_full_range_switch(struct hda_codec *codec) |
---|
| 6667 | +{ |
---|
| 6668 | + struct snd_kcontrol_new knew = |
---|
| 6669 | + CA0132_CODEC_MUTE_MONO("Full-Range Rear Speakers", |
---|
| 6670 | + SPEAKER_FULL_RANGE_REAR, 1, HDA_OUTPUT); |
---|
| 6671 | + |
---|
| 6672 | + return snd_hda_ctl_add(codec, SPEAKER_FULL_RANGE_REAR, |
---|
| 6673 | + snd_ctl_new1(&knew, codec)); |
---|
| 6674 | +} |
---|
| 6675 | + |
---|
| 6676 | +/* |
---|
| 6677 | + * Bass redirection redirects audio below the crossover frequency to the LFE |
---|
| 6678 | + * channel on speakers that are set as not being full-range. On configurations |
---|
| 6679 | + * without an LFE channel, it does nothing. Bass redirection seems to be the |
---|
| 6680 | + * replacement for X-Bass on configurations with an LFE channel. |
---|
| 6681 | + */ |
---|
| 6682 | +static int ca0132_alt_add_bass_redirection_crossover(struct hda_codec *codec) |
---|
| 6683 | +{ |
---|
| 6684 | + const char *namestr = "Bass Redirection Crossover"; |
---|
| 6685 | + struct snd_kcontrol_new knew = |
---|
| 6686 | + HDA_CODEC_VOLUME_MONO(namestr, BASS_REDIRECTION_XOVER, 1, 0, |
---|
| 6687 | + HDA_OUTPUT); |
---|
| 6688 | + |
---|
| 6689 | + knew.tlv.c = NULL; |
---|
| 6690 | + knew.info = ca0132_alt_xbass_xover_slider_info; |
---|
| 6691 | + knew.get = ca0132_alt_xbass_xover_slider_ctl_get; |
---|
| 6692 | + knew.put = ca0132_alt_xbass_xover_slider_put; |
---|
| 6693 | + |
---|
| 6694 | + return snd_hda_ctl_add(codec, BASS_REDIRECTION_XOVER, |
---|
| 6695 | + snd_ctl_new1(&knew, codec)); |
---|
| 6696 | +} |
---|
| 6697 | + |
---|
| 6698 | +static int ca0132_alt_add_bass_redirection_switch(struct hda_codec *codec) |
---|
| 6699 | +{ |
---|
| 6700 | + const char *namestr = "Bass Redirection"; |
---|
| 6701 | + struct snd_kcontrol_new knew = |
---|
| 6702 | + CA0132_CODEC_MUTE_MONO(namestr, BASS_REDIRECTION, 1, |
---|
| 6703 | + HDA_OUTPUT); |
---|
| 6704 | + |
---|
| 6705 | + return snd_hda_ctl_add(codec, BASS_REDIRECTION, |
---|
| 6706 | + snd_ctl_new1(&knew, codec)); |
---|
| 6707 | +} |
---|
| 6708 | + |
---|
| 6709 | +/* |
---|
5677 | 6710 | * Create an Input Source enumerated control for the alternate ca0132 codecs |
---|
5678 | 6711 | * because the front microphone has no auto-detect, and Line-in has to be set |
---|
5679 | 6712 | * somehow. |
---|
.. | .. |
---|
5708 | 6741 | } |
---|
5709 | 6742 | |
---|
5710 | 6743 | /* |
---|
5711 | | - * Need to create slave controls for the alternate codecs that have surround |
---|
| 6744 | + * Add headphone gain enumerated control for the AE-5. This switches between |
---|
| 6745 | + * three modes, low, medium, and high. When non-headphone outputs are selected, |
---|
| 6746 | + * it is automatically set to high. This is the same behavior as Windows. |
---|
| 6747 | + */ |
---|
| 6748 | +static int ae5_add_headphone_gain_enum(struct hda_codec *codec) |
---|
| 6749 | +{ |
---|
| 6750 | + struct snd_kcontrol_new knew = |
---|
| 6751 | + HDA_CODEC_MUTE_MONO("AE-5: Headphone Gain", |
---|
| 6752 | + AE5_HEADPHONE_GAIN_ENUM, 1, 0, HDA_OUTPUT); |
---|
| 6753 | + knew.info = ae5_headphone_gain_info; |
---|
| 6754 | + knew.get = ae5_headphone_gain_get; |
---|
| 6755 | + knew.put = ae5_headphone_gain_put; |
---|
| 6756 | + return snd_hda_ctl_add(codec, AE5_HEADPHONE_GAIN_ENUM, |
---|
| 6757 | + snd_ctl_new1(&knew, codec)); |
---|
| 6758 | +} |
---|
| 6759 | + |
---|
| 6760 | +/* |
---|
| 6761 | + * Add sound filter enumerated control for the AE-5. This adds three different |
---|
| 6762 | + * settings: Slow Roll Off, Minimum Phase, and Fast Roll Off. From what I've |
---|
| 6763 | + * read into it, it changes the DAC's interpolation filter. |
---|
| 6764 | + */ |
---|
| 6765 | +static int ae5_add_sound_filter_enum(struct hda_codec *codec) |
---|
| 6766 | +{ |
---|
| 6767 | + struct snd_kcontrol_new knew = |
---|
| 6768 | + HDA_CODEC_MUTE_MONO("AE-5: Sound Filter", |
---|
| 6769 | + AE5_SOUND_FILTER_ENUM, 1, 0, HDA_OUTPUT); |
---|
| 6770 | + knew.info = ae5_sound_filter_info; |
---|
| 6771 | + knew.get = ae5_sound_filter_get; |
---|
| 6772 | + knew.put = ae5_sound_filter_put; |
---|
| 6773 | + return snd_hda_ctl_add(codec, AE5_SOUND_FILTER_ENUM, |
---|
| 6774 | + snd_ctl_new1(&knew, codec)); |
---|
| 6775 | +} |
---|
| 6776 | + |
---|
| 6777 | +static int zxr_add_headphone_gain_switch(struct hda_codec *codec) |
---|
| 6778 | +{ |
---|
| 6779 | + struct snd_kcontrol_new knew = |
---|
| 6780 | + CA0132_CODEC_MUTE_MONO("ZxR: 600 Ohm Gain", |
---|
| 6781 | + ZXR_HEADPHONE_GAIN, 1, HDA_OUTPUT); |
---|
| 6782 | + |
---|
| 6783 | + return snd_hda_ctl_add(codec, ZXR_HEADPHONE_GAIN, |
---|
| 6784 | + snd_ctl_new1(&knew, codec)); |
---|
| 6785 | +} |
---|
| 6786 | + |
---|
| 6787 | +/* |
---|
| 6788 | + * Need to create follower controls for the alternate codecs that have surround |
---|
5712 | 6789 | * capabilities. |
---|
5713 | 6790 | */ |
---|
5714 | | -static const char * const ca0132_alt_slave_pfxs[] = { |
---|
| 6791 | +static const char * const ca0132_alt_follower_pfxs[] = { |
---|
5715 | 6792 | "Front", "Surround", "Center", "LFE", NULL, |
---|
5716 | 6793 | }; |
---|
5717 | 6794 | |
---|
.. | .. |
---|
5839 | 6916 | if (err < 0) |
---|
5840 | 6917 | return err; |
---|
5841 | 6918 | } |
---|
5842 | | - /* Setup vmaster with surround slaves for desktop ca0132 devices */ |
---|
5843 | | - if (spec->use_alt_functions) { |
---|
| 6919 | + /* Setup vmaster with surround followers for desktop ca0132 devices */ |
---|
| 6920 | + if (ca0132_use_alt_functions(spec)) { |
---|
5844 | 6921 | snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT, |
---|
5845 | 6922 | spec->tlv); |
---|
5846 | 6923 | snd_hda_add_vmaster(codec, "Master Playback Volume", |
---|
5847 | | - spec->tlv, ca0132_alt_slave_pfxs, |
---|
| 6924 | + spec->tlv, ca0132_alt_follower_pfxs, |
---|
5848 | 6925 | "Playback Volume"); |
---|
5849 | 6926 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
---|
5850 | | - NULL, ca0132_alt_slave_pfxs, |
---|
| 6927 | + NULL, ca0132_alt_follower_pfxs, |
---|
5851 | 6928 | "Playback Switch", |
---|
5852 | 6929 | true, &spec->vmaster_mute.sw_kctl); |
---|
5853 | | - |
---|
| 6930 | + if (err < 0) |
---|
| 6931 | + return err; |
---|
5854 | 6932 | } |
---|
5855 | 6933 | |
---|
5856 | 6934 | /* Add in and out effects controls. |
---|
.. | .. |
---|
5859 | 6937 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; |
---|
5860 | 6938 | for (i = 0; i < num_fx; i++) { |
---|
5861 | 6939 | /* Desktop cards break if Echo Cancellation is used. */ |
---|
5862 | | - if (spec->use_pci_mmio) { |
---|
| 6940 | + if (ca0132_use_pci_mmio(spec)) { |
---|
5863 | 6941 | if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID + |
---|
5864 | 6942 | OUT_EFFECTS_COUNT)) |
---|
5865 | 6943 | continue; |
---|
.. | .. |
---|
5876 | 6954 | * EQ presets, and Smart Volume presets. Also, change names to add FX |
---|
5877 | 6955 | * prefix, and change PlayEnhancement and CrystalVoice to match. |
---|
5878 | 6956 | */ |
---|
5879 | | - if (spec->use_alt_controls) { |
---|
5880 | | - ca0132_alt_add_svm_enum(codec); |
---|
5881 | | - add_ca0132_alt_eq_presets(codec); |
---|
| 6957 | + if (ca0132_use_alt_controls(spec)) { |
---|
| 6958 | + err = ca0132_alt_add_svm_enum(codec); |
---|
| 6959 | + if (err < 0) |
---|
| 6960 | + return err; |
---|
| 6961 | + |
---|
| 6962 | + err = add_ca0132_alt_eq_presets(codec); |
---|
| 6963 | + if (err < 0) |
---|
| 6964 | + return err; |
---|
| 6965 | + |
---|
5882 | 6966 | err = add_fx_switch(codec, PLAY_ENHANCEMENT, |
---|
5883 | 6967 | "Enable OutFX", 0); |
---|
5884 | 6968 | if (err < 0) |
---|
.. | .. |
---|
5915 | 6999 | if (err < 0) |
---|
5916 | 7000 | return err; |
---|
5917 | 7001 | } |
---|
5918 | | - add_voicefx(codec); |
---|
| 7002 | + err = add_voicefx(codec); |
---|
| 7003 | + if (err < 0) |
---|
| 7004 | + return err; |
---|
5919 | 7005 | |
---|
5920 | 7006 | /* |
---|
5921 | 7007 | * If the codec uses alt_functions, you need the enumerated controls |
---|
5922 | 7008 | * to select the new outputs and inputs, plus add the new mic boost |
---|
5923 | 7009 | * setting control. |
---|
5924 | 7010 | */ |
---|
5925 | | - if (spec->use_alt_functions) { |
---|
5926 | | - ca0132_alt_add_output_enum(codec); |
---|
5927 | | - ca0132_alt_add_input_enum(codec); |
---|
5928 | | - ca0132_alt_add_mic_boost_enum(codec); |
---|
| 7011 | + if (ca0132_use_alt_functions(spec)) { |
---|
| 7012 | + err = ca0132_alt_add_output_enum(codec); |
---|
| 7013 | + if (err < 0) |
---|
| 7014 | + return err; |
---|
| 7015 | + err = ca0132_alt_add_speaker_channel_cfg_enum(codec); |
---|
| 7016 | + if (err < 0) |
---|
| 7017 | + return err; |
---|
| 7018 | + err = ca0132_alt_add_front_full_range_switch(codec); |
---|
| 7019 | + if (err < 0) |
---|
| 7020 | + return err; |
---|
| 7021 | + err = ca0132_alt_add_rear_full_range_switch(codec); |
---|
| 7022 | + if (err < 0) |
---|
| 7023 | + return err; |
---|
| 7024 | + err = ca0132_alt_add_bass_redirection_crossover(codec); |
---|
| 7025 | + if (err < 0) |
---|
| 7026 | + return err; |
---|
| 7027 | + err = ca0132_alt_add_bass_redirection_switch(codec); |
---|
| 7028 | + if (err < 0) |
---|
| 7029 | + return err; |
---|
| 7030 | + err = ca0132_alt_add_mic_boost_enum(codec); |
---|
| 7031 | + if (err < 0) |
---|
| 7032 | + return err; |
---|
| 7033 | + /* |
---|
| 7034 | + * ZxR only has microphone input, there is no front panel |
---|
| 7035 | + * header on the card, and aux-in is handled by the DBPro board. |
---|
| 7036 | + */ |
---|
| 7037 | + if (ca0132_quirk(spec) != QUIRK_ZXR) { |
---|
| 7038 | + err = ca0132_alt_add_input_enum(codec); |
---|
| 7039 | + if (err < 0) |
---|
| 7040 | + return err; |
---|
| 7041 | + } |
---|
5929 | 7042 | } |
---|
| 7043 | + |
---|
| 7044 | + switch (ca0132_quirk(spec)) { |
---|
| 7045 | + case QUIRK_AE5: |
---|
| 7046 | + case QUIRK_AE7: |
---|
| 7047 | + err = ae5_add_headphone_gain_enum(codec); |
---|
| 7048 | + if (err < 0) |
---|
| 7049 | + return err; |
---|
| 7050 | + err = ae5_add_sound_filter_enum(codec); |
---|
| 7051 | + if (err < 0) |
---|
| 7052 | + return err; |
---|
| 7053 | + break; |
---|
| 7054 | + case QUIRK_ZXR: |
---|
| 7055 | + err = zxr_add_headphone_gain_switch(codec); |
---|
| 7056 | + if (err < 0) |
---|
| 7057 | + return err; |
---|
| 7058 | + break; |
---|
| 7059 | + default: |
---|
| 7060 | + break; |
---|
| 7061 | + } |
---|
| 7062 | + |
---|
5930 | 7063 | #ifdef ENABLE_TUNING_CONTROLS |
---|
5931 | 7064 | add_tuning_ctls(codec); |
---|
5932 | 7065 | #endif |
---|
.. | .. |
---|
5952 | 7085 | return err; |
---|
5953 | 7086 | } |
---|
5954 | 7087 | |
---|
5955 | | - if (spec->use_alt_functions) |
---|
| 7088 | + if (ca0132_use_alt_functions(spec)) |
---|
5956 | 7089 | ca0132_alt_add_chmap_ctls(codec); |
---|
| 7090 | + |
---|
| 7091 | + return 0; |
---|
| 7092 | +} |
---|
| 7093 | + |
---|
| 7094 | +static int dbpro_build_controls(struct hda_codec *codec) |
---|
| 7095 | +{ |
---|
| 7096 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7097 | + int err = 0; |
---|
| 7098 | + |
---|
| 7099 | + if (spec->dig_out) { |
---|
| 7100 | + err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out, |
---|
| 7101 | + spec->dig_out); |
---|
| 7102 | + if (err < 0) |
---|
| 7103 | + return err; |
---|
| 7104 | + } |
---|
| 7105 | + |
---|
| 7106 | + if (spec->dig_in) { |
---|
| 7107 | + err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in); |
---|
| 7108 | + if (err < 0) |
---|
| 7109 | + return err; |
---|
| 7110 | + } |
---|
5957 | 7111 | |
---|
5958 | 7112 | return 0; |
---|
5959 | 7113 | } |
---|
.. | .. |
---|
6009 | 7163 | info = snd_hda_codec_pcm_new(codec, "CA0132 Analog"); |
---|
6010 | 7164 | if (!info) |
---|
6011 | 7165 | return -ENOMEM; |
---|
6012 | | - if (spec->use_alt_functions) { |
---|
| 7166 | + if (ca0132_use_alt_functions(spec)) { |
---|
6013 | 7167 | info->own_chmap = true; |
---|
6014 | 7168 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap |
---|
6015 | 7169 | = ca0132_alt_chmaps; |
---|
.. | .. |
---|
6023 | 7177 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; |
---|
6024 | 7178 | |
---|
6025 | 7179 | /* With the DSP enabled, desktops don't use this ADC. */ |
---|
6026 | | - if (!spec->use_alt_functions) { |
---|
| 7180 | + if (!ca0132_use_alt_functions(spec)) { |
---|
6027 | 7181 | info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2"); |
---|
6028 | 7182 | if (!info) |
---|
6029 | 7183 | return -ENOMEM; |
---|
.. | .. |
---|
6039 | 7193 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; |
---|
6040 | 7194 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1; |
---|
6041 | 7195 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[2]; |
---|
| 7196 | + |
---|
| 7197 | + if (!spec->dig_out && !spec->dig_in) |
---|
| 7198 | + return 0; |
---|
| 7199 | + |
---|
| 7200 | + info = snd_hda_codec_pcm_new(codec, "CA0132 Digital"); |
---|
| 7201 | + if (!info) |
---|
| 7202 | + return -ENOMEM; |
---|
| 7203 | + info->pcm_type = HDA_PCM_TYPE_SPDIF; |
---|
| 7204 | + if (spec->dig_out) { |
---|
| 7205 | + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = |
---|
| 7206 | + ca0132_pcm_digital_playback; |
---|
| 7207 | + info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out; |
---|
| 7208 | + } |
---|
| 7209 | + if (spec->dig_in) { |
---|
| 7210 | + info->stream[SNDRV_PCM_STREAM_CAPTURE] = |
---|
| 7211 | + ca0132_pcm_digital_capture; |
---|
| 7212 | + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; |
---|
| 7213 | + } |
---|
| 7214 | + |
---|
| 7215 | + return 0; |
---|
| 7216 | +} |
---|
| 7217 | + |
---|
| 7218 | +static int dbpro_build_pcms(struct hda_codec *codec) |
---|
| 7219 | +{ |
---|
| 7220 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7221 | + struct hda_pcm *info; |
---|
| 7222 | + |
---|
| 7223 | + info = snd_hda_codec_pcm_new(codec, "CA0132 Alt Analog"); |
---|
| 7224 | + if (!info) |
---|
| 7225 | + return -ENOMEM; |
---|
| 7226 | + info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; |
---|
| 7227 | + info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1; |
---|
| 7228 | + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; |
---|
| 7229 | + |
---|
6042 | 7230 | |
---|
6043 | 7231 | if (!spec->dig_out && !spec->dig_in) |
---|
6044 | 7232 | return 0; |
---|
.. | .. |
---|
6187 | 7375 | * Bit 6: set to select Data2, clear for Data1 |
---|
6188 | 7376 | * Bit 7: set to enable DMic, clear for AMic |
---|
6189 | 7377 | */ |
---|
6190 | | - if (spec->quirk == QUIRK_ALIENWARE_M17XR4) |
---|
| 7378 | + if (ca0132_quirk(spec) == QUIRK_ALIENWARE_M17XR4) |
---|
6191 | 7379 | val = 0x33; |
---|
6192 | 7380 | else |
---|
6193 | 7381 | val = 0x23; |
---|
.. | .. |
---|
6241 | 7429 | } |
---|
6242 | 7430 | |
---|
6243 | 7431 | /* |
---|
6244 | | - * Recon3D r3d_setup_defaults sub functions. |
---|
| 7432 | + * Default speaker tuning values setup for alternative codecs. |
---|
6245 | 7433 | */ |
---|
| 7434 | +static const unsigned int sbz_default_delay_values[] = { |
---|
| 7435 | + /* Non-zero values are floating point 0.000198. */ |
---|
| 7436 | + 0x394f9e38, 0x394f9e38, 0x00000000, 0x00000000, 0x00000000, 0x00000000 |
---|
| 7437 | +}; |
---|
6246 | 7438 | |
---|
6247 | | -static void r3d_dsp_scp_startup(struct hda_codec *codec) |
---|
| 7439 | +static const unsigned int zxr_default_delay_values[] = { |
---|
| 7440 | + /* Non-zero values are floating point 0.000220. */ |
---|
| 7441 | + 0x00000000, 0x00000000, 0x3966afcd, 0x3966afcd, 0x3966afcd, 0x3966afcd |
---|
| 7442 | +}; |
---|
| 7443 | + |
---|
| 7444 | +static const unsigned int ae5_default_delay_values[] = { |
---|
| 7445 | + /* Non-zero values are floating point 0.000100. */ |
---|
| 7446 | + 0x00000000, 0x00000000, 0x38d1b717, 0x38d1b717, 0x38d1b717, 0x38d1b717 |
---|
| 7447 | +}; |
---|
| 7448 | + |
---|
| 7449 | +/* |
---|
| 7450 | + * If we never change these, probably only need them on initialization. |
---|
| 7451 | + */ |
---|
| 7452 | +static void ca0132_alt_init_speaker_tuning(struct hda_codec *codec) |
---|
6248 | 7453 | { |
---|
6249 | | - unsigned int tmp; |
---|
| 7454 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7455 | + unsigned int i, tmp, start_req, end_req; |
---|
| 7456 | + const unsigned int *values; |
---|
6250 | 7457 | |
---|
6251 | | - tmp = 0x00000000; |
---|
6252 | | - dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); |
---|
| 7458 | + switch (ca0132_quirk(spec)) { |
---|
| 7459 | + case QUIRK_SBZ: |
---|
| 7460 | + values = sbz_default_delay_values; |
---|
| 7461 | + break; |
---|
| 7462 | + case QUIRK_ZXR: |
---|
| 7463 | + values = zxr_default_delay_values; |
---|
| 7464 | + break; |
---|
| 7465 | + case QUIRK_AE5: |
---|
| 7466 | + case QUIRK_AE7: |
---|
| 7467 | + values = ae5_default_delay_values; |
---|
| 7468 | + break; |
---|
| 7469 | + default: |
---|
| 7470 | + values = sbz_default_delay_values; |
---|
| 7471 | + break; |
---|
| 7472 | + } |
---|
6253 | 7473 | |
---|
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); |
---|
6284 | 7474 | tmp = FLOAT_ZERO; |
---|
6285 | | - dspio_set_uint_param(codec, 0x80, 0x01, tmp); |
---|
| 7475 | + dspio_set_uint_param(codec, 0x96, SPEAKER_TUNING_ENABLE_CENTER_EQ, tmp); |
---|
| 7476 | + |
---|
| 7477 | + start_req = SPEAKER_TUNING_FRONT_LEFT_VOL_LEVEL; |
---|
| 7478 | + end_req = SPEAKER_TUNING_REAR_RIGHT_VOL_LEVEL; |
---|
| 7479 | + for (i = start_req; i < end_req + 1; i++) |
---|
| 7480 | + dspio_set_uint_param(codec, 0x96, i, tmp); |
---|
| 7481 | + |
---|
| 7482 | + start_req = SPEAKER_TUNING_FRONT_LEFT_INVERT; |
---|
| 7483 | + end_req = SPEAKER_TUNING_REAR_RIGHT_INVERT; |
---|
| 7484 | + for (i = start_req; i < end_req + 1; i++) |
---|
| 7485 | + dspio_set_uint_param(codec, 0x96, i, tmp); |
---|
| 7486 | + |
---|
| 7487 | + |
---|
| 7488 | + for (i = 0; i < 6; i++) |
---|
| 7489 | + dspio_set_uint_param(codec, 0x96, |
---|
| 7490 | + SPEAKER_TUNING_FRONT_LEFT_DELAY + i, values[i]); |
---|
6286 | 7491 | } |
---|
6287 | 7492 | |
---|
6288 | 7493 | /* |
---|
6289 | | - * Initialize Sound Blaster Z analog microphones. |
---|
| 7494 | + * Creates a dummy stream to bind the output to. This seems to have to be done |
---|
| 7495 | + * after changing the main outputs source and destination streams. |
---|
6290 | 7496 | */ |
---|
6291 | | -static void sbz_init_analog_mics(struct hda_codec *codec) |
---|
| 7497 | +static void ca0132_alt_create_dummy_stream(struct hda_codec *codec) |
---|
6292 | 7498 | { |
---|
| 7499 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7500 | + unsigned int stream_format; |
---|
| 7501 | + |
---|
| 7502 | + stream_format = snd_hdac_calc_stream_format(48000, 2, |
---|
| 7503 | + SNDRV_PCM_FORMAT_S32_LE, 32, 0); |
---|
| 7504 | + |
---|
| 7505 | + snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, |
---|
| 7506 | + 0, stream_format); |
---|
| 7507 | + |
---|
| 7508 | + snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); |
---|
| 7509 | +} |
---|
| 7510 | + |
---|
| 7511 | +/* |
---|
| 7512 | + * Initialize mic for non-chromebook ca0132 implementations. |
---|
| 7513 | + */ |
---|
| 7514 | +static void ca0132_alt_init_analog_mics(struct hda_codec *codec) |
---|
| 7515 | +{ |
---|
| 7516 | + struct ca0132_spec *spec = codec->spec; |
---|
6293 | 7517 | unsigned int tmp; |
---|
6294 | 7518 | |
---|
6295 | 7519 | /* Mic 1 Setup */ |
---|
6296 | 7520 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); |
---|
6297 | 7521 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); |
---|
6298 | | - tmp = FLOAT_THREE; |
---|
| 7522 | + if (ca0132_quirk(spec) == QUIRK_R3DI) { |
---|
| 7523 | + chipio_set_conn_rate(codec, 0x0F, SR_96_000); |
---|
| 7524 | + tmp = FLOAT_ONE; |
---|
| 7525 | + } else |
---|
| 7526 | + tmp = FLOAT_THREE; |
---|
6299 | 7527 | dspio_set_uint_param(codec, 0x80, 0x00, tmp); |
---|
6300 | 7528 | |
---|
6301 | | - /* Mic 2 Setup, even though it isn't connected on SBZ */ |
---|
| 7529 | + /* Mic 2 setup (not present on desktop cards) */ |
---|
6302 | 7530 | chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000); |
---|
6303 | 7531 | chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000); |
---|
| 7532 | + if (ca0132_quirk(spec) == QUIRK_R3DI) |
---|
| 7533 | + chipio_set_conn_rate(codec, 0x0F, SR_96_000); |
---|
6304 | 7534 | tmp = FLOAT_ZERO; |
---|
6305 | 7535 | dspio_set_uint_param(codec, 0x80, 0x01, tmp); |
---|
6306 | | - |
---|
6307 | 7536 | } |
---|
6308 | 7537 | |
---|
6309 | 7538 | /* |
---|
.. | .. |
---|
6336 | 7565 | codec_dbg(codec, "Connect Streams exited, mutex released.\n"); |
---|
6337 | 7566 | |
---|
6338 | 7567 | mutex_unlock(&spec->chipio_mutex); |
---|
6339 | | - |
---|
6340 | 7568 | } |
---|
6341 | 7569 | |
---|
6342 | 7570 | /* |
---|
.. | .. |
---|
6363 | 7591 | chipio_set_stream_channels(codec, 0x0C, 6); |
---|
6364 | 7592 | chipio_set_stream_control(codec, 0x0C, 1); |
---|
6365 | 7593 | /* No clue what these control */ |
---|
6366 | | - chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0); |
---|
6367 | | - chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1); |
---|
6368 | | - chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2); |
---|
6369 | | - chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3); |
---|
6370 | | - chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4); |
---|
6371 | | - chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5); |
---|
6372 | | - chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6); |
---|
6373 | | - chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7); |
---|
6374 | | - chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8); |
---|
6375 | | - chipio_write_no_mutex(codec, 0x190054, 0x0001edc9); |
---|
6376 | | - chipio_write_no_mutex(codec, 0x190058, 0x0001eaca); |
---|
6377 | | - chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb); |
---|
6378 | | - |
---|
| 7594 | + if (ca0132_quirk(spec) == QUIRK_SBZ) { |
---|
| 7595 | + chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0); |
---|
| 7596 | + chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1); |
---|
| 7597 | + chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2); |
---|
| 7598 | + chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3); |
---|
| 7599 | + chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4); |
---|
| 7600 | + chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5); |
---|
| 7601 | + chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6); |
---|
| 7602 | + chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7); |
---|
| 7603 | + chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8); |
---|
| 7604 | + chipio_write_no_mutex(codec, 0x190054, 0x0001edc9); |
---|
| 7605 | + chipio_write_no_mutex(codec, 0x190058, 0x0001eaca); |
---|
| 7606 | + chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb); |
---|
| 7607 | + } else if (ca0132_quirk(spec) == QUIRK_ZXR) { |
---|
| 7608 | + chipio_write_no_mutex(codec, 0x190038, 0x000140c2); |
---|
| 7609 | + chipio_write_no_mutex(codec, 0x19003c, 0x000141c3); |
---|
| 7610 | + chipio_write_no_mutex(codec, 0x190040, 0x000150c4); |
---|
| 7611 | + chipio_write_no_mutex(codec, 0x190044, 0x000151c5); |
---|
| 7612 | + chipio_write_no_mutex(codec, 0x190050, 0x000142c8); |
---|
| 7613 | + chipio_write_no_mutex(codec, 0x190054, 0x000143c9); |
---|
| 7614 | + chipio_write_no_mutex(codec, 0x190058, 0x000152ca); |
---|
| 7615 | + chipio_write_no_mutex(codec, 0x19005c, 0x000153cb); |
---|
| 7616 | + } |
---|
6379 | 7617 | chipio_write_no_mutex(codec, 0x19042c, 0x00000001); |
---|
6380 | 7618 | |
---|
6381 | 7619 | codec_dbg(codec, "Startup Data exited, mutex released.\n"); |
---|
.. | .. |
---|
6383 | 7621 | } |
---|
6384 | 7622 | |
---|
6385 | 7623 | /* |
---|
6386 | | - * Sound Blaster Z uses these after DSP is loaded. Weird SCP commands |
---|
6387 | | - * without a 0x20 source like normal. |
---|
| 7624 | + * Custom DSP SCP commands where the src value is 0x00 instead of 0x20. This is |
---|
| 7625 | + * done after the DSP is loaded. |
---|
6388 | 7626 | */ |
---|
6389 | | -static void sbz_dsp_scp_startup(struct hda_codec *codec) |
---|
| 7627 | +static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec) |
---|
6390 | 7628 | { |
---|
6391 | | - unsigned int tmp; |
---|
| 7629 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7630 | + unsigned int tmp, i; |
---|
6392 | 7631 | |
---|
6393 | | - tmp = 0x00000003; |
---|
6394 | | - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
6395 | | - |
---|
6396 | | - tmp = 0x00000000; |
---|
6397 | | - dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); |
---|
6398 | | - |
---|
6399 | | - tmp = 0x00000001; |
---|
6400 | | - dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); |
---|
6401 | | - |
---|
6402 | | - tmp = 0x00000004; |
---|
6403 | | - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
6404 | | - |
---|
6405 | | - tmp = 0x00000005; |
---|
6406 | | - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
6407 | | - |
---|
6408 | | - tmp = 0x00000000; |
---|
6409 | | - dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
6410 | | - |
---|
| 7632 | + /* |
---|
| 7633 | + * Gotta run these twice, or else mic works inconsistently. Not clear |
---|
| 7634 | + * why this is, but multiple tests have confirmed it. |
---|
| 7635 | + */ |
---|
| 7636 | + for (i = 0; i < 2; i++) { |
---|
| 7637 | + switch (ca0132_quirk(spec)) { |
---|
| 7638 | + case QUIRK_SBZ: |
---|
| 7639 | + case QUIRK_AE5: |
---|
| 7640 | + case QUIRK_AE7: |
---|
| 7641 | + tmp = 0x00000003; |
---|
| 7642 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
| 7643 | + tmp = 0x00000000; |
---|
| 7644 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); |
---|
| 7645 | + tmp = 0x00000001; |
---|
| 7646 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); |
---|
| 7647 | + tmp = 0x00000004; |
---|
| 7648 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
| 7649 | + tmp = 0x00000005; |
---|
| 7650 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
| 7651 | + tmp = 0x00000000; |
---|
| 7652 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
| 7653 | + break; |
---|
| 7654 | + case QUIRK_R3D: |
---|
| 7655 | + case QUIRK_R3DI: |
---|
| 7656 | + tmp = 0x00000000; |
---|
| 7657 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp); |
---|
| 7658 | + tmp = 0x00000001; |
---|
| 7659 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp); |
---|
| 7660 | + tmp = 0x00000004; |
---|
| 7661 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
| 7662 | + tmp = 0x00000005; |
---|
| 7663 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
| 7664 | + tmp = 0x00000000; |
---|
| 7665 | + dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); |
---|
| 7666 | + break; |
---|
| 7667 | + default: |
---|
| 7668 | + break; |
---|
| 7669 | + } |
---|
| 7670 | + msleep(100); |
---|
| 7671 | + } |
---|
6411 | 7672 | } |
---|
6412 | 7673 | |
---|
6413 | | -static void sbz_dsp_initial_mic_setup(struct hda_codec *codec) |
---|
| 7674 | +static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec) |
---|
6414 | 7675 | { |
---|
| 7676 | + struct ca0132_spec *spec = codec->spec; |
---|
6415 | 7677 | unsigned int tmp; |
---|
6416 | 7678 | |
---|
6417 | 7679 | chipio_set_stream_control(codec, 0x03, 0); |
---|
.. | .. |
---|
6426 | 7688 | chipio_set_stream_control(codec, 0x03, 1); |
---|
6427 | 7689 | chipio_set_stream_control(codec, 0x04, 1); |
---|
6428 | 7690 | |
---|
6429 | | - chipio_write(codec, 0x18b098, 0x0000000c); |
---|
6430 | | - chipio_write(codec, 0x18b09C, 0x0000000c); |
---|
| 7691 | + switch (ca0132_quirk(spec)) { |
---|
| 7692 | + case QUIRK_SBZ: |
---|
| 7693 | + chipio_write(codec, 0x18b098, 0x0000000c); |
---|
| 7694 | + chipio_write(codec, 0x18b09C, 0x0000000c); |
---|
| 7695 | + break; |
---|
| 7696 | + case QUIRK_AE5: |
---|
| 7697 | + chipio_write(codec, 0x18b098, 0x0000000c); |
---|
| 7698 | + chipio_write(codec, 0x18b09c, 0x0000004c); |
---|
| 7699 | + break; |
---|
| 7700 | + default: |
---|
| 7701 | + break; |
---|
| 7702 | + } |
---|
| 7703 | +} |
---|
| 7704 | + |
---|
| 7705 | +static void ae5_post_dsp_register_set(struct hda_codec *codec) |
---|
| 7706 | +{ |
---|
| 7707 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7708 | + |
---|
| 7709 | + chipio_8051_write_direct(codec, 0x93, 0x10); |
---|
| 7710 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7711 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); |
---|
| 7712 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7713 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); |
---|
| 7714 | + |
---|
| 7715 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7716 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7717 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7718 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7719 | + writeb(0x00, spec->mem_base + 0x100); |
---|
| 7720 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7721 | + writeb(0x00, spec->mem_base + 0x100); |
---|
| 7722 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7723 | + writeb(0x00, spec->mem_base + 0x100); |
---|
| 7724 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7725 | + writeb(0x00, spec->mem_base + 0x100); |
---|
| 7726 | + writeb(0xff, spec->mem_base + 0x304); |
---|
| 7727 | + |
---|
| 7728 | + ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x3f); |
---|
| 7729 | + ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f); |
---|
| 7730 | + ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); |
---|
| 7731 | +} |
---|
| 7732 | + |
---|
| 7733 | +static void ae5_post_dsp_param_setup(struct hda_codec *codec) |
---|
| 7734 | +{ |
---|
| 7735 | + /* |
---|
| 7736 | + * Param3 in the 8051's memory is represented by the ascii string 'mch' |
---|
| 7737 | + * which seems to be 'multichannel'. This is also mentioned in the |
---|
| 7738 | + * AE-5's registry values in Windows. |
---|
| 7739 | + */ |
---|
| 7740 | + chipio_set_control_param(codec, 3, 0); |
---|
| 7741 | + /* |
---|
| 7742 | + * I believe ASI is 'audio serial interface' and that it's used to |
---|
| 7743 | + * change colors on the external LED strip connected to the AE-5. |
---|
| 7744 | + */ |
---|
| 7745 | + chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1); |
---|
| 7746 | + |
---|
| 7747 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83); |
---|
| 7748 | + chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); |
---|
| 7749 | + |
---|
| 7750 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7751 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92); |
---|
| 7752 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7753 | + VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa); |
---|
| 7754 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7755 | + VENDOR_CHIPIO_8051_DATA_WRITE, 0x22); |
---|
| 7756 | +} |
---|
| 7757 | + |
---|
| 7758 | +static void ae5_post_dsp_pll_setup(struct hda_codec *codec) |
---|
| 7759 | +{ |
---|
| 7760 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7761 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41); |
---|
| 7762 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7763 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8); |
---|
| 7764 | + |
---|
| 7765 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7766 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x45); |
---|
| 7767 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7768 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcc); |
---|
| 7769 | + |
---|
| 7770 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7771 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x40); |
---|
| 7772 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7773 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcb); |
---|
| 7774 | + |
---|
| 7775 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7776 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); |
---|
| 7777 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7778 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); |
---|
| 7779 | + |
---|
| 7780 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7781 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x51); |
---|
| 7782 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7783 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0x8d); |
---|
| 7784 | +} |
---|
| 7785 | + |
---|
| 7786 | +static void ae5_post_dsp_stream_setup(struct hda_codec *codec) |
---|
| 7787 | +{ |
---|
| 7788 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7789 | + |
---|
| 7790 | + mutex_lock(&spec->chipio_mutex); |
---|
| 7791 | + |
---|
| 7792 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81); |
---|
| 7793 | + |
---|
| 7794 | + chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000); |
---|
| 7795 | + |
---|
| 7796 | + chipio_set_stream_channels(codec, 0x0C, 6); |
---|
| 7797 | + chipio_set_stream_control(codec, 0x0C, 1); |
---|
| 7798 | + |
---|
| 7799 | + chipio_set_stream_source_dest(codec, 0x5, 0x43, 0x0); |
---|
| 7800 | + |
---|
| 7801 | + chipio_set_stream_source_dest(codec, 0x18, 0x9, 0xd0); |
---|
| 7802 | + chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000); |
---|
| 7803 | + chipio_set_stream_channels(codec, 0x18, 6); |
---|
| 7804 | + chipio_set_stream_control(codec, 0x18, 1); |
---|
| 7805 | + |
---|
| 7806 | + chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4); |
---|
| 7807 | + |
---|
| 7808 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7809 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); |
---|
| 7810 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7811 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); |
---|
| 7812 | + |
---|
| 7813 | + ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80); |
---|
| 7814 | + |
---|
| 7815 | + mutex_unlock(&spec->chipio_mutex); |
---|
| 7816 | +} |
---|
| 7817 | + |
---|
| 7818 | +static void ae5_post_dsp_startup_data(struct hda_codec *codec) |
---|
| 7819 | +{ |
---|
| 7820 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7821 | + |
---|
| 7822 | + mutex_lock(&spec->chipio_mutex); |
---|
| 7823 | + |
---|
| 7824 | + chipio_write_no_mutex(codec, 0x189000, 0x0001f101); |
---|
| 7825 | + chipio_write_no_mutex(codec, 0x189004, 0x0001f101); |
---|
| 7826 | + chipio_write_no_mutex(codec, 0x189024, 0x00014004); |
---|
| 7827 | + chipio_write_no_mutex(codec, 0x189028, 0x0002000f); |
---|
| 7828 | + |
---|
| 7829 | + ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05); |
---|
| 7830 | + chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7); |
---|
| 7831 | + ca0113_mmio_command_set(codec, 0x48, 0x0b, 0x12); |
---|
| 7832 | + ca0113_mmio_command_set(codec, 0x48, 0x04, 0x00); |
---|
| 7833 | + ca0113_mmio_command_set(codec, 0x48, 0x06, 0x48); |
---|
| 7834 | + ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05); |
---|
| 7835 | + ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); |
---|
| 7836 | + ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00); |
---|
| 7837 | + ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00); |
---|
| 7838 | + ca0113_mmio_gpio_set(codec, 0, true); |
---|
| 7839 | + ca0113_mmio_gpio_set(codec, 1, true); |
---|
| 7840 | + ca0113_mmio_command_set(codec, 0x48, 0x07, 0x80); |
---|
| 7841 | + |
---|
| 7842 | + chipio_write_no_mutex(codec, 0x18b03c, 0x00000012); |
---|
| 7843 | + |
---|
| 7844 | + ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00); |
---|
| 7845 | + ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00); |
---|
| 7846 | + |
---|
| 7847 | + mutex_unlock(&spec->chipio_mutex); |
---|
| 7848 | +} |
---|
| 7849 | + |
---|
| 7850 | +static const unsigned int ae7_port_set_data[] = { |
---|
| 7851 | + 0x0001e0c0, 0x0001e1c1, 0x0001e4c2, 0x0001e5c3, 0x0001e2c4, 0x0001e3c5, |
---|
| 7852 | + 0x0001e8c6, 0x0001e9c7, 0x0001ecc8, 0x0001edc9, 0x0001eaca, 0x0001ebcb |
---|
| 7853 | +}; |
---|
| 7854 | + |
---|
| 7855 | +static void ae7_post_dsp_setup_ports(struct hda_codec *codec) |
---|
| 7856 | +{ |
---|
| 7857 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7858 | + unsigned int i, count, addr; |
---|
| 7859 | + |
---|
| 7860 | + mutex_lock(&spec->chipio_mutex); |
---|
| 7861 | + |
---|
| 7862 | + chipio_set_stream_channels(codec, 0x0c, 6); |
---|
| 7863 | + chipio_set_stream_control(codec, 0x0c, 1); |
---|
| 7864 | + |
---|
| 7865 | + count = ARRAY_SIZE(ae7_port_set_data); |
---|
| 7866 | + addr = 0x190030; |
---|
| 7867 | + for (i = 0; i < count; i++) { |
---|
| 7868 | + chipio_write_no_mutex(codec, addr, ae7_port_set_data[i]); |
---|
| 7869 | + |
---|
| 7870 | + /* Addresses are incremented by 4-bytes. */ |
---|
| 7871 | + addr += 0x04; |
---|
| 7872 | + } |
---|
| 7873 | + |
---|
| 7874 | + /* |
---|
| 7875 | + * Port setting always ends with a write of 0x1 to address 0x19042c. |
---|
| 7876 | + */ |
---|
| 7877 | + chipio_write_no_mutex(codec, 0x19042c, 0x00000001); |
---|
| 7878 | + |
---|
| 7879 | + ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00); |
---|
| 7880 | + ca0113_mmio_command_set(codec, 0x48, 0x0d, 0x40); |
---|
| 7881 | + ca0113_mmio_command_set(codec, 0x48, 0x17, 0x00); |
---|
| 7882 | + ca0113_mmio_command_set(codec, 0x48, 0x19, 0x00); |
---|
| 7883 | + ca0113_mmio_command_set(codec, 0x48, 0x11, 0xff); |
---|
| 7884 | + ca0113_mmio_command_set(codec, 0x48, 0x12, 0xff); |
---|
| 7885 | + ca0113_mmio_command_set(codec, 0x48, 0x13, 0xff); |
---|
| 7886 | + ca0113_mmio_command_set(codec, 0x48, 0x14, 0x7f); |
---|
| 7887 | + |
---|
| 7888 | + mutex_unlock(&spec->chipio_mutex); |
---|
| 7889 | +} |
---|
| 7890 | + |
---|
| 7891 | +static void ae7_post_dsp_asi_stream_setup(struct hda_codec *codec) |
---|
| 7892 | +{ |
---|
| 7893 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7894 | + |
---|
| 7895 | + mutex_lock(&spec->chipio_mutex); |
---|
| 7896 | + |
---|
| 7897 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81); |
---|
| 7898 | + ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00); |
---|
| 7899 | + |
---|
| 7900 | + chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000); |
---|
| 7901 | + chipio_set_stream_channels(codec, 0x0c, 6); |
---|
| 7902 | + chipio_set_stream_control(codec, 0x0c, 1); |
---|
| 7903 | + |
---|
| 7904 | + chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00); |
---|
| 7905 | + chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0); |
---|
| 7906 | + |
---|
| 7907 | + chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000); |
---|
| 7908 | + chipio_set_stream_channels(codec, 0x18, 6); |
---|
| 7909 | + chipio_set_stream_control(codec, 0x18, 1); |
---|
| 7910 | + |
---|
| 7911 | + chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4); |
---|
| 7912 | + |
---|
| 7913 | + mutex_unlock(&spec->chipio_mutex); |
---|
| 7914 | +} |
---|
| 7915 | + |
---|
| 7916 | +static void ae7_post_dsp_pll_setup(struct hda_codec *codec) |
---|
| 7917 | +{ |
---|
| 7918 | + static const unsigned int addr[] = { |
---|
| 7919 | + 0x41, 0x45, 0x40, 0x43, 0x51 |
---|
| 7920 | + }; |
---|
| 7921 | + static const unsigned int data[] = { |
---|
| 7922 | + 0xc8, 0xcc, 0xcb, 0xc7, 0x8d |
---|
| 7923 | + }; |
---|
| 7924 | + unsigned int i; |
---|
| 7925 | + |
---|
| 7926 | + for (i = 0; i < ARRAY_SIZE(addr); i++) { |
---|
| 7927 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7928 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, addr[i]); |
---|
| 7929 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7930 | + VENDOR_CHIPIO_PLL_PMU_WRITE, data[i]); |
---|
| 7931 | + } |
---|
| 7932 | +} |
---|
| 7933 | + |
---|
| 7934 | +static void ae7_post_dsp_asi_setup_ports(struct hda_codec *codec) |
---|
| 7935 | +{ |
---|
| 7936 | + struct ca0132_spec *spec = codec->spec; |
---|
| 7937 | + static const unsigned int target[] = { |
---|
| 7938 | + 0x0b, 0x04, 0x06, 0x0a, 0x0c, 0x11, 0x12, 0x13, 0x14 |
---|
| 7939 | + }; |
---|
| 7940 | + static const unsigned int data[] = { |
---|
| 7941 | + 0x12, 0x00, 0x48, 0x05, 0x5f, 0xff, 0xff, 0xff, 0x7f |
---|
| 7942 | + }; |
---|
| 7943 | + unsigned int i; |
---|
| 7944 | + |
---|
| 7945 | + mutex_lock(&spec->chipio_mutex); |
---|
| 7946 | + |
---|
| 7947 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7948 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); |
---|
| 7949 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 7950 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); |
---|
| 7951 | + |
---|
| 7952 | + chipio_write_no_mutex(codec, 0x189000, 0x0001f101); |
---|
| 7953 | + chipio_write_no_mutex(codec, 0x189004, 0x0001f101); |
---|
| 7954 | + chipio_write_no_mutex(codec, 0x189024, 0x00014004); |
---|
| 7955 | + chipio_write_no_mutex(codec, 0x189028, 0x0002000f); |
---|
| 7956 | + |
---|
| 7957 | + ae7_post_dsp_pll_setup(codec); |
---|
| 7958 | + chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7); |
---|
| 7959 | + |
---|
| 7960 | + for (i = 0; i < ARRAY_SIZE(target); i++) |
---|
| 7961 | + ca0113_mmio_command_set(codec, 0x48, target[i], data[i]); |
---|
| 7962 | + |
---|
| 7963 | + ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83); |
---|
| 7964 | + ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00); |
---|
| 7965 | + ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00); |
---|
| 7966 | + |
---|
| 7967 | + chipio_set_stream_source_dest(codec, 0x21, 0x64, 0x56); |
---|
| 7968 | + chipio_set_stream_channels(codec, 0x21, 2); |
---|
| 7969 | + chipio_set_conn_rate_no_mutex(codec, 0x56, SR_8_000); |
---|
| 7970 | + |
---|
| 7971 | + chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_NODE_ID, 0x09); |
---|
| 7972 | + /* |
---|
| 7973 | + * In the 8051's memory, this param is referred to as 'n2sid', which I |
---|
| 7974 | + * believe is 'node to streamID'. It seems to be a way to assign a |
---|
| 7975 | + * stream to a given HDA node. |
---|
| 7976 | + */ |
---|
| 7977 | + chipio_set_control_param_no_mutex(codec, 0x20, 0x21); |
---|
| 7978 | + |
---|
| 7979 | + chipio_write_no_mutex(codec, 0x18b038, 0x00000088); |
---|
| 7980 | + |
---|
| 7981 | + /* |
---|
| 7982 | + * Now, at this point on Windows, an actual stream is setup and |
---|
| 7983 | + * seemingly sends data to the HDA node 0x09, which is the digital |
---|
| 7984 | + * audio input node. This is left out here, because obviously I don't |
---|
| 7985 | + * know what data is being sent. Interestingly, the AE-5 seems to go |
---|
| 7986 | + * through the motions of getting here and never actually takes this |
---|
| 7987 | + * step, but the AE-7 does. |
---|
| 7988 | + */ |
---|
| 7989 | + |
---|
| 7990 | + ca0113_mmio_gpio_set(codec, 0, 1); |
---|
| 7991 | + ca0113_mmio_gpio_set(codec, 1, 1); |
---|
| 7992 | + |
---|
| 7993 | + ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83); |
---|
| 7994 | + chipio_write_no_mutex(codec, 0x18b03c, 0x00000000); |
---|
| 7995 | + ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00); |
---|
| 7996 | + ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00); |
---|
| 7997 | + |
---|
| 7998 | + chipio_set_stream_source_dest(codec, 0x05, 0x43, 0x00); |
---|
| 7999 | + chipio_set_stream_source_dest(codec, 0x18, 0x09, 0xd0); |
---|
| 8000 | + |
---|
| 8001 | + chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000); |
---|
| 8002 | + chipio_set_stream_channels(codec, 0x18, 6); |
---|
| 8003 | + |
---|
| 8004 | + /* |
---|
| 8005 | + * Runs again, this has been repeated a few times, but I'm just |
---|
| 8006 | + * following what the Windows driver does. |
---|
| 8007 | + */ |
---|
| 8008 | + ae7_post_dsp_pll_setup(codec); |
---|
| 8009 | + chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7); |
---|
| 8010 | + |
---|
| 8011 | + mutex_unlock(&spec->chipio_mutex); |
---|
| 8012 | +} |
---|
| 8013 | + |
---|
| 8014 | +/* |
---|
| 8015 | + * The Windows driver has commands that seem to setup ASI, which I believe to |
---|
| 8016 | + * be some sort of audio serial interface. My current speculation is that it's |
---|
| 8017 | + * related to communicating with the new DAC. |
---|
| 8018 | + */ |
---|
| 8019 | +static void ae7_post_dsp_asi_setup(struct hda_codec *codec) |
---|
| 8020 | +{ |
---|
| 8021 | + chipio_8051_write_direct(codec, 0x93, 0x10); |
---|
| 8022 | + |
---|
| 8023 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 8024 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); |
---|
| 8025 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 8026 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); |
---|
| 8027 | + |
---|
| 8028 | + ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83); |
---|
| 8029 | + ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f); |
---|
| 8030 | + |
---|
| 8031 | + chipio_set_control_param(codec, 3, 3); |
---|
| 8032 | + chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1); |
---|
| 8033 | + |
---|
| 8034 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83); |
---|
| 8035 | + chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); |
---|
| 8036 | + snd_hda_codec_write(codec, 0x17, 0, 0x794, 0x00); |
---|
| 8037 | + |
---|
| 8038 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 8039 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92); |
---|
| 8040 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 8041 | + VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa); |
---|
| 8042 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 8043 | + VENDOR_CHIPIO_8051_DATA_WRITE, 0x22); |
---|
| 8044 | + |
---|
| 8045 | + ae7_post_dsp_pll_setup(codec); |
---|
| 8046 | + ae7_post_dsp_asi_stream_setup(codec); |
---|
| 8047 | + |
---|
| 8048 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 8049 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43); |
---|
| 8050 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 8051 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7); |
---|
| 8052 | + |
---|
| 8053 | + ae7_post_dsp_asi_setup_ports(codec); |
---|
6431 | 8054 | } |
---|
6432 | 8055 | |
---|
6433 | 8056 | /* |
---|
.. | .. |
---|
6488 | 8111 | if (spec->dsp_state != DSP_DOWNLOADED) |
---|
6489 | 8112 | return; |
---|
6490 | 8113 | |
---|
6491 | | - r3d_dsp_scp_startup(codec); |
---|
6492 | | - |
---|
6493 | | - r3d_dsp_initial_mic_setup(codec); |
---|
| 8114 | + ca0132_alt_dsp_scp_startup(codec); |
---|
| 8115 | + ca0132_alt_init_analog_mics(codec); |
---|
6494 | 8116 | |
---|
6495 | 8117 | /*remove DSP headroom*/ |
---|
6496 | 8118 | tmp = FLOAT_ZERO; |
---|
.. | .. |
---|
6504 | 8126 | /* Set speaker source? */ |
---|
6505 | 8127 | dspio_set_uint_param(codec, 0x32, 0x00, tmp); |
---|
6506 | 8128 | |
---|
6507 | | - if (spec->quirk == QUIRK_R3DI) |
---|
| 8129 | + if (ca0132_quirk(spec) == QUIRK_R3DI) |
---|
6508 | 8130 | r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED); |
---|
| 8131 | + |
---|
| 8132 | + /* Disable mute on Center/LFE. */ |
---|
| 8133 | + if (ca0132_quirk(spec) == QUIRK_R3D) { |
---|
| 8134 | + ca0113_mmio_gpio_set(codec, 2, false); |
---|
| 8135 | + ca0113_mmio_gpio_set(codec, 4, true); |
---|
| 8136 | + } |
---|
6509 | 8137 | |
---|
6510 | 8138 | /* Setup effect defaults */ |
---|
6511 | 8139 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; |
---|
.. | .. |
---|
6526 | 8154 | static void sbz_setup_defaults(struct hda_codec *codec) |
---|
6527 | 8155 | { |
---|
6528 | 8156 | struct ca0132_spec *spec = codec->spec; |
---|
6529 | | - unsigned int tmp, stream_format; |
---|
| 8157 | + unsigned int tmp; |
---|
6530 | 8158 | int num_fx; |
---|
6531 | 8159 | int idx, i; |
---|
6532 | 8160 | |
---|
6533 | 8161 | if (spec->dsp_state != DSP_DOWNLOADED) |
---|
6534 | 8162 | return; |
---|
6535 | 8163 | |
---|
6536 | | - sbz_dsp_scp_startup(codec); |
---|
6537 | | - |
---|
6538 | | - sbz_init_analog_mics(codec); |
---|
6539 | | - |
---|
| 8164 | + ca0132_alt_dsp_scp_startup(codec); |
---|
| 8165 | + ca0132_alt_init_analog_mics(codec); |
---|
6540 | 8166 | sbz_connect_streams(codec); |
---|
6541 | | - |
---|
6542 | 8167 | sbz_chipio_startup_data(codec); |
---|
6543 | 8168 | |
---|
6544 | 8169 | chipio_set_stream_control(codec, 0x03, 1); |
---|
.. | .. |
---|
6564 | 8189 | /* Set speaker source? */ |
---|
6565 | 8190 | dspio_set_uint_param(codec, 0x32, 0x00, tmp); |
---|
6566 | 8191 | |
---|
6567 | | - sbz_dsp_initial_mic_setup(codec); |
---|
6568 | | - |
---|
| 8192 | + ca0132_alt_dsp_initial_mic_setup(codec); |
---|
6569 | 8193 | |
---|
6570 | 8194 | /* out, in effects + voicefx */ |
---|
6571 | 8195 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; |
---|
.. | .. |
---|
6578 | 8202 | } |
---|
6579 | 8203 | } |
---|
6580 | 8204 | |
---|
| 8205 | + ca0132_alt_init_speaker_tuning(codec); |
---|
| 8206 | + |
---|
| 8207 | + ca0132_alt_create_dummy_stream(codec); |
---|
| 8208 | +} |
---|
| 8209 | + |
---|
| 8210 | +/* |
---|
| 8211 | + * Setup default parameters for the Sound BlasterX AE-5 DSP. |
---|
| 8212 | + */ |
---|
| 8213 | +static void ae5_setup_defaults(struct hda_codec *codec) |
---|
| 8214 | +{ |
---|
| 8215 | + struct ca0132_spec *spec = codec->spec; |
---|
| 8216 | + unsigned int tmp; |
---|
| 8217 | + int num_fx; |
---|
| 8218 | + int idx, i; |
---|
| 8219 | + |
---|
| 8220 | + if (spec->dsp_state != DSP_DOWNLOADED) |
---|
| 8221 | + return; |
---|
| 8222 | + |
---|
| 8223 | + ca0132_alt_dsp_scp_startup(codec); |
---|
| 8224 | + ca0132_alt_init_analog_mics(codec); |
---|
| 8225 | + chipio_set_stream_control(codec, 0x03, 1); |
---|
| 8226 | + chipio_set_stream_control(codec, 0x04, 1); |
---|
| 8227 | + |
---|
| 8228 | + /* New, unknown SCP req's */ |
---|
| 8229 | + tmp = FLOAT_ZERO; |
---|
| 8230 | + dspio_set_uint_param(codec, 0x96, 0x29, tmp); |
---|
| 8231 | + dspio_set_uint_param(codec, 0x96, 0x2a, tmp); |
---|
| 8232 | + dspio_set_uint_param(codec, 0x80, 0x0d, tmp); |
---|
| 8233 | + dspio_set_uint_param(codec, 0x80, 0x0e, tmp); |
---|
| 8234 | + |
---|
| 8235 | + ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f); |
---|
| 8236 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
| 8237 | + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); |
---|
| 8238 | + |
---|
| 8239 | + /* Internal loopback off */ |
---|
| 8240 | + tmp = FLOAT_ONE; |
---|
| 8241 | + dspio_set_uint_param(codec, 0x37, 0x08, tmp); |
---|
| 8242 | + dspio_set_uint_param(codec, 0x37, 0x10, tmp); |
---|
| 8243 | + |
---|
| 8244 | + /*remove DSP headroom*/ |
---|
| 8245 | + tmp = FLOAT_ZERO; |
---|
| 8246 | + dspio_set_uint_param(codec, 0x96, 0x3C, tmp); |
---|
| 8247 | + |
---|
| 8248 | + /* set WUH source */ |
---|
| 8249 | + tmp = FLOAT_TWO; |
---|
| 8250 | + dspio_set_uint_param(codec, 0x31, 0x00, tmp); |
---|
| 8251 | + chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); |
---|
| 8252 | + |
---|
| 8253 | + /* Set speaker source? */ |
---|
| 8254 | + dspio_set_uint_param(codec, 0x32, 0x00, tmp); |
---|
| 8255 | + |
---|
| 8256 | + ca0132_alt_dsp_initial_mic_setup(codec); |
---|
| 8257 | + ae5_post_dsp_register_set(codec); |
---|
| 8258 | + ae5_post_dsp_param_setup(codec); |
---|
| 8259 | + ae5_post_dsp_pll_setup(codec); |
---|
| 8260 | + ae5_post_dsp_stream_setup(codec); |
---|
| 8261 | + ae5_post_dsp_startup_data(codec); |
---|
| 8262 | + |
---|
| 8263 | + /* out, in effects + voicefx */ |
---|
| 8264 | + num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; |
---|
| 8265 | + for (idx = 0; idx < num_fx; idx++) { |
---|
| 8266 | + for (i = 0; i <= ca0132_effects[idx].params; i++) { |
---|
| 8267 | + dspio_set_uint_param(codec, |
---|
| 8268 | + ca0132_effects[idx].mid, |
---|
| 8269 | + ca0132_effects[idx].reqs[i], |
---|
| 8270 | + ca0132_effects[idx].def_vals[i]); |
---|
| 8271 | + } |
---|
| 8272 | + } |
---|
| 8273 | + |
---|
| 8274 | + ca0132_alt_init_speaker_tuning(codec); |
---|
| 8275 | + |
---|
| 8276 | + ca0132_alt_create_dummy_stream(codec); |
---|
| 8277 | +} |
---|
| 8278 | + |
---|
| 8279 | +/* |
---|
| 8280 | + * Setup default parameters for the Sound Blaster AE-7 DSP. |
---|
| 8281 | + */ |
---|
| 8282 | +static void ae7_setup_defaults(struct hda_codec *codec) |
---|
| 8283 | +{ |
---|
| 8284 | + struct ca0132_spec *spec = codec->spec; |
---|
| 8285 | + unsigned int tmp; |
---|
| 8286 | + int num_fx; |
---|
| 8287 | + int idx, i; |
---|
| 8288 | + |
---|
| 8289 | + if (spec->dsp_state != DSP_DOWNLOADED) |
---|
| 8290 | + return; |
---|
| 8291 | + |
---|
| 8292 | + ca0132_alt_dsp_scp_startup(codec); |
---|
| 8293 | + ca0132_alt_init_analog_mics(codec); |
---|
| 8294 | + ae7_post_dsp_setup_ports(codec); |
---|
| 8295 | + |
---|
| 8296 | + tmp = FLOAT_ZERO; |
---|
| 8297 | + dspio_set_uint_param(codec, 0x96, |
---|
| 8298 | + SPEAKER_TUNING_FRONT_LEFT_INVERT, tmp); |
---|
| 8299 | + dspio_set_uint_param(codec, 0x96, |
---|
| 8300 | + SPEAKER_TUNING_FRONT_RIGHT_INVERT, tmp); |
---|
| 8301 | + |
---|
| 8302 | + ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f); |
---|
| 8303 | + |
---|
| 8304 | + /* New, unknown SCP req's */ |
---|
| 8305 | + dspio_set_uint_param(codec, 0x80, 0x0d, tmp); |
---|
| 8306 | + dspio_set_uint_param(codec, 0x80, 0x0e, tmp); |
---|
| 8307 | + |
---|
| 8308 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
| 8309 | + |
---|
| 8310 | + /* Internal loopback off */ |
---|
| 8311 | + tmp = FLOAT_ONE; |
---|
| 8312 | + dspio_set_uint_param(codec, 0x37, 0x08, tmp); |
---|
| 8313 | + dspio_set_uint_param(codec, 0x37, 0x10, tmp); |
---|
| 8314 | + |
---|
| 8315 | + /*remove DSP headroom*/ |
---|
| 8316 | + tmp = FLOAT_ZERO; |
---|
| 8317 | + dspio_set_uint_param(codec, 0x96, 0x3C, tmp); |
---|
| 8318 | + |
---|
| 8319 | + /* set WUH source */ |
---|
| 8320 | + tmp = FLOAT_TWO; |
---|
| 8321 | + dspio_set_uint_param(codec, 0x31, 0x00, tmp); |
---|
| 8322 | + chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); |
---|
| 8323 | + |
---|
| 8324 | + /* Set speaker source? */ |
---|
| 8325 | + dspio_set_uint_param(codec, 0x32, 0x00, tmp); |
---|
| 8326 | + ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00); |
---|
| 8327 | + |
---|
6581 | 8328 | /* |
---|
6582 | | - * Have to make a stream to bind the sound output to, otherwise |
---|
6583 | | - * you'll get dead audio. Before I did this, it would bind to an |
---|
6584 | | - * audio input, and would never work |
---|
| 8329 | + * This is the second time we've called this, but this is seemingly |
---|
| 8330 | + * what Windows does. |
---|
6585 | 8331 | */ |
---|
6586 | | - stream_format = snd_hdac_calc_stream_format(48000, 2, |
---|
6587 | | - SNDRV_PCM_FORMAT_S32_LE, 32, 0); |
---|
| 8332 | + ca0132_alt_init_analog_mics(codec); |
---|
6588 | 8333 | |
---|
6589 | | - snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, |
---|
6590 | | - 0, stream_format); |
---|
| 8334 | + ae7_post_dsp_asi_setup(codec); |
---|
6591 | 8335 | |
---|
6592 | | - snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); |
---|
| 8336 | + /* |
---|
| 8337 | + * Not sure why, but these are both set to 1. They're only set to 0 |
---|
| 8338 | + * upon shutdown. |
---|
| 8339 | + */ |
---|
| 8340 | + ca0113_mmio_gpio_set(codec, 0, true); |
---|
| 8341 | + ca0113_mmio_gpio_set(codec, 1, true); |
---|
6593 | 8342 | |
---|
6594 | | - snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id, |
---|
6595 | | - 0, stream_format); |
---|
| 8343 | + /* Volume control related. */ |
---|
| 8344 | + ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x04); |
---|
| 8345 | + ca0113_mmio_command_set(codec, 0x48, 0x10, 0x04); |
---|
| 8346 | + ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x80); |
---|
6596 | 8347 | |
---|
6597 | | - snd_hda_codec_cleanup_stream(codec, spec->dacs[0]); |
---|
| 8348 | + /* out, in effects + voicefx */ |
---|
| 8349 | + num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1; |
---|
| 8350 | + for (idx = 0; idx < num_fx; idx++) { |
---|
| 8351 | + for (i = 0; i <= ca0132_effects[idx].params; i++) { |
---|
| 8352 | + dspio_set_uint_param(codec, |
---|
| 8353 | + ca0132_effects[idx].mid, |
---|
| 8354 | + ca0132_effects[idx].reqs[i], |
---|
| 8355 | + ca0132_effects[idx].def_vals[i]); |
---|
| 8356 | + } |
---|
| 8357 | + } |
---|
| 8358 | + |
---|
| 8359 | + ca0132_alt_init_speaker_tuning(codec); |
---|
| 8360 | + |
---|
| 8361 | + ca0132_alt_create_dummy_stream(codec); |
---|
6598 | 8362 | } |
---|
6599 | 8363 | |
---|
6600 | 8364 | /* |
---|
.. | .. |
---|
6604 | 8368 | { |
---|
6605 | 8369 | struct ca0132_spec *spec = codec->spec; |
---|
6606 | 8370 | |
---|
6607 | | - if (spec->use_alt_functions) { |
---|
| 8371 | + if (ca0132_use_alt_functions(spec)) { |
---|
6608 | 8372 | chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1); |
---|
6609 | 8373 | chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1); |
---|
6610 | 8374 | chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1); |
---|
.. | .. |
---|
6637 | 8401 | { |
---|
6638 | 8402 | struct ca0132_spec *spec = codec->spec; |
---|
6639 | 8403 | |
---|
6640 | | - if (spec->use_alt_functions) { |
---|
| 8404 | + if (ca0132_use_alt_functions(spec)) { |
---|
6641 | 8405 | chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); |
---|
6642 | 8406 | chipio_set_conn_rate(codec, 0x0B, SR_48_000); |
---|
6643 | 8407 | chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0); |
---|
.. | .. |
---|
6668 | 8432 | bool dsp_loaded = false; |
---|
6669 | 8433 | struct ca0132_spec *spec = codec->spec; |
---|
6670 | 8434 | const struct dsp_image_seg *dsp_os_image; |
---|
6671 | | - const struct firmware *fw_entry; |
---|
| 8435 | + const struct firmware *fw_entry = NULL; |
---|
6672 | 8436 | /* |
---|
6673 | 8437 | * Alternate firmwares for different variants. The Recon3Di apparently |
---|
6674 | 8438 | * can use the default firmware, but I'll leave the option in case |
---|
6675 | 8439 | * it needs it again. |
---|
6676 | 8440 | */ |
---|
6677 | | - switch (spec->quirk) { |
---|
| 8441 | + switch (ca0132_quirk(spec)) { |
---|
6678 | 8442 | case QUIRK_SBZ: |
---|
6679 | | - if (request_firmware(&fw_entry, SBZ_EFX_FILE, |
---|
6680 | | - codec->card->dev) != 0) { |
---|
6681 | | - codec_dbg(codec, "SBZ alt firmware not detected. "); |
---|
6682 | | - spec->alt_firmware_present = false; |
---|
6683 | | - } else { |
---|
6684 | | - codec_dbg(codec, "Sound Blaster Z firmware selected."); |
---|
6685 | | - spec->alt_firmware_present = true; |
---|
6686 | | - } |
---|
| 8443 | + case QUIRK_R3D: |
---|
| 8444 | + case QUIRK_AE5: |
---|
| 8445 | + if (request_firmware(&fw_entry, DESKTOP_EFX_FILE, |
---|
| 8446 | + codec->card->dev) != 0) |
---|
| 8447 | + codec_dbg(codec, "Desktop firmware not found."); |
---|
| 8448 | + else |
---|
| 8449 | + codec_dbg(codec, "Desktop firmware selected."); |
---|
6687 | 8450 | break; |
---|
6688 | 8451 | case QUIRK_R3DI: |
---|
6689 | 8452 | if (request_firmware(&fw_entry, R3DI_EFX_FILE, |
---|
6690 | | - codec->card->dev) != 0) { |
---|
| 8453 | + codec->card->dev) != 0) |
---|
6691 | 8454 | codec_dbg(codec, "Recon3Di alt firmware not detected."); |
---|
6692 | | - spec->alt_firmware_present = false; |
---|
6693 | | - } else { |
---|
| 8455 | + else |
---|
6694 | 8456 | codec_dbg(codec, "Recon3Di firmware selected."); |
---|
6695 | | - spec->alt_firmware_present = true; |
---|
6696 | | - } |
---|
6697 | 8457 | break; |
---|
6698 | 8458 | default: |
---|
6699 | | - spec->alt_firmware_present = false; |
---|
6700 | 8459 | break; |
---|
6701 | 8460 | } |
---|
6702 | 8461 | /* |
---|
6703 | 8462 | * Use default ctefx.bin if no alt firmware is detected, or if none |
---|
6704 | 8463 | * exists for your particular codec. |
---|
6705 | 8464 | */ |
---|
6706 | | - if (!spec->alt_firmware_present) { |
---|
| 8465 | + if (!fw_entry) { |
---|
6707 | 8466 | codec_dbg(codec, "Default firmware selected."); |
---|
6708 | 8467 | if (request_firmware(&fw_entry, EFX_FILE, |
---|
6709 | 8468 | codec->card->dev) != 0) |
---|
.. | .. |
---|
6746 | 8505 | } |
---|
6747 | 8506 | |
---|
6748 | 8507 | /* For codecs using alt functions, this is already done earlier */ |
---|
6749 | | - if (spec->dsp_state == DSP_DOWNLOADED && (!spec->use_alt_functions)) |
---|
| 8508 | + if (spec->dsp_state == DSP_DOWNLOADED && !ca0132_use_alt_functions(spec)) |
---|
6750 | 8509 | ca0132_set_dsp_msr(codec, true); |
---|
6751 | 8510 | } |
---|
6752 | 8511 | |
---|
.. | .. |
---|
6784 | 8543 | { |
---|
6785 | 8544 | struct ca0132_spec *spec = codec->spec; |
---|
6786 | 8545 | |
---|
6787 | | - if (spec->use_alt_functions) |
---|
| 8546 | + if (ca0132_use_alt_functions(spec)) |
---|
6788 | 8547 | ca0132_alt_select_in(codec); |
---|
6789 | 8548 | else |
---|
6790 | 8549 | ca0132_select_mic(codec); |
---|
.. | .. |
---|
6799 | 8558 | snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, |
---|
6800 | 8559 | ca0132_process_dsp_response); |
---|
6801 | 8560 | /* Front headphone jack detection */ |
---|
6802 | | - if (spec->use_alt_functions) |
---|
| 8561 | + if (ca0132_use_alt_functions(spec)) |
---|
6803 | 8562 | snd_hda_jack_detect_enable_callback(codec, |
---|
6804 | 8563 | spec->unsol_tag_front_hp, hp_callback); |
---|
6805 | 8564 | } |
---|
.. | .. |
---|
6809 | 8568 | */ |
---|
6810 | 8569 | |
---|
6811 | 8570 | /* Sends before DSP download. */ |
---|
6812 | | -static struct hda_verb ca0132_base_init_verbs[] = { |
---|
| 8571 | +static const struct hda_verb ca0132_base_init_verbs[] = { |
---|
6813 | 8572 | /*enable ct extension*/ |
---|
6814 | 8573 | {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1}, |
---|
6815 | 8574 | {} |
---|
6816 | 8575 | }; |
---|
6817 | 8576 | |
---|
6818 | 8577 | /* Send at exit. */ |
---|
6819 | | -static struct hda_verb ca0132_base_exit_verbs[] = { |
---|
| 8578 | +static const struct hda_verb ca0132_base_exit_verbs[] = { |
---|
6820 | 8579 | /*set afg to D3*/ |
---|
6821 | 8580 | {0x01, AC_VERB_SET_POWER_STATE, 0x03}, |
---|
6822 | 8581 | /*disable ct extension*/ |
---|
.. | .. |
---|
6826 | 8585 | |
---|
6827 | 8586 | /* Other verbs tables. Sends after DSP download. */ |
---|
6828 | 8587 | |
---|
6829 | | -static struct hda_verb ca0132_init_verbs0[] = { |
---|
| 8588 | +static const struct hda_verb ca0132_init_verbs0[] = { |
---|
6830 | 8589 | /* chip init verbs */ |
---|
6831 | 8590 | {0x15, 0x70D, 0xF0}, |
---|
6832 | 8591 | {0x15, 0x70E, 0xFE}, |
---|
.. | .. |
---|
6859 | 8618 | }; |
---|
6860 | 8619 | |
---|
6861 | 8620 | /* Extra init verbs for desktop cards. */ |
---|
6862 | | -static struct hda_verb ca0132_init_verbs1[] = { |
---|
| 8621 | +static const struct hda_verb ca0132_init_verbs1[] = { |
---|
6863 | 8622 | {0x15, 0x70D, 0x20}, |
---|
6864 | 8623 | {0x15, 0x70E, 0x19}, |
---|
6865 | 8624 | {0x15, 0x707, 0x00}, |
---|
.. | .. |
---|
6889 | 8648 | mutex_init(&spec->chipio_mutex); |
---|
6890 | 8649 | |
---|
6891 | 8650 | spec->cur_out_type = SPEAKER_OUT; |
---|
6892 | | - if (!spec->use_alt_functions) |
---|
| 8651 | + if (!ca0132_use_alt_functions(spec)) |
---|
6893 | 8652 | spec->cur_mic_type = DIGITAL_MIC; |
---|
6894 | 8653 | else |
---|
6895 | 8654 | spec->cur_mic_type = REAR_MIC; |
---|
.. | .. |
---|
6915 | 8674 | * Sets defaults for the effect slider controls, only for alternative |
---|
6916 | 8675 | * ca0132 codecs. Also sets x-bass crossover frequency to 80hz. |
---|
6917 | 8676 | */ |
---|
6918 | | - if (spec->use_alt_controls) { |
---|
| 8677 | + if (ca0132_use_alt_controls(spec)) { |
---|
| 8678 | + /* Set speakers to default to full range. */ |
---|
| 8679 | + spec->speaker_range_val[0] = 1; |
---|
| 8680 | + spec->speaker_range_val[1] = 1; |
---|
| 8681 | + |
---|
6919 | 8682 | spec->xbass_xover_freq = 8; |
---|
6920 | 8683 | for (i = 0; i < EFFECT_LEVEL_SLIDERS; i++) |
---|
6921 | 8684 | spec->fx_ctl_val[i] = effect_slider_defaults[i]; |
---|
| 8685 | + |
---|
| 8686 | + spec->bass_redirect_xover_freq = 8; |
---|
6922 | 8687 | } |
---|
6923 | 8688 | |
---|
6924 | 8689 | spec->voicefx_val = 0; |
---|
6925 | 8690 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1; |
---|
6926 | 8691 | spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0; |
---|
| 8692 | + |
---|
| 8693 | + /* |
---|
| 8694 | + * The ZxR doesn't have a front panel header, and it's line-in is on |
---|
| 8695 | + * the daughter board. So, there is no input enum control, and we need |
---|
| 8696 | + * to make sure that spec->in_enum_val is set properly. |
---|
| 8697 | + */ |
---|
| 8698 | + if (ca0132_quirk(spec) == QUIRK_ZXR) |
---|
| 8699 | + spec->in_enum_val = REAR_MIC; |
---|
6927 | 8700 | |
---|
6928 | 8701 | #ifdef ENABLE_TUNING_CONTROLS |
---|
6929 | 8702 | ca0132_init_tuning_defaults(codec); |
---|
.. | .. |
---|
6952 | 8725 | for (i = 0; i < 8; i++) |
---|
6953 | 8726 | writeb(0xb3, spec->mem_base + 0x304); |
---|
6954 | 8727 | |
---|
6955 | | - ca0132_mmio_gpio_set(codec, 0, false); |
---|
6956 | | - ca0132_mmio_gpio_set(codec, 1, false); |
---|
6957 | | - ca0132_mmio_gpio_set(codec, 4, true); |
---|
6958 | | - ca0132_mmio_gpio_set(codec, 5, false); |
---|
6959 | | - ca0132_mmio_gpio_set(codec, 7, false); |
---|
| 8728 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
| 8729 | + ca0113_mmio_gpio_set(codec, 1, false); |
---|
| 8730 | + ca0113_mmio_gpio_set(codec, 4, true); |
---|
| 8731 | + ca0113_mmio_gpio_set(codec, 5, false); |
---|
| 8732 | + ca0113_mmio_gpio_set(codec, 7, false); |
---|
6960 | 8733 | } |
---|
6961 | 8734 | |
---|
6962 | 8735 | static void sbz_set_pin_ctl_default(struct hda_codec *codec) |
---|
6963 | 8736 | { |
---|
6964 | | - hda_nid_t pins[5] = {0x0B, 0x0C, 0x0E, 0x12, 0x13}; |
---|
| 8737 | + static const hda_nid_t pins[] = {0x0B, 0x0C, 0x0E, 0x12, 0x13}; |
---|
6965 | 8738 | unsigned int i; |
---|
6966 | 8739 | |
---|
6967 | 8740 | snd_hda_codec_write(codec, 0x11, 0, |
---|
6968 | 8741 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40); |
---|
6969 | 8742 | |
---|
6970 | | - for (i = 0; i < 5; i++) |
---|
| 8743 | + for (i = 0; i < ARRAY_SIZE(pins); i++) |
---|
6971 | 8744 | snd_hda_codec_write(codec, pins[i], 0, |
---|
6972 | 8745 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00); |
---|
6973 | 8746 | } |
---|
6974 | 8747 | |
---|
6975 | 8748 | static void ca0132_clear_unsolicited(struct hda_codec *codec) |
---|
6976 | 8749 | { |
---|
6977 | | - hda_nid_t pins[7] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13}; |
---|
| 8750 | + static const hda_nid_t pins[] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13}; |
---|
6978 | 8751 | unsigned int i; |
---|
6979 | 8752 | |
---|
6980 | | - for (i = 0; i < 7; i++) { |
---|
| 8753 | + for (i = 0; i < ARRAY_SIZE(pins); i++) { |
---|
6981 | 8754 | snd_hda_codec_write(codec, pins[i], 0, |
---|
6982 | 8755 | AC_VERB_SET_UNSOLICITED_ENABLE, 0x00); |
---|
6983 | 8756 | } |
---|
.. | .. |
---|
6997 | 8770 | if (data >= 0) |
---|
6998 | 8771 | snd_hda_codec_write(codec, 0x01, 0, |
---|
6999 | 8772 | AC_VERB_SET_GPIO_DATA, data); |
---|
| 8773 | +} |
---|
| 8774 | + |
---|
| 8775 | +static void zxr_dbpro_power_state_shutdown(struct hda_codec *codec) |
---|
| 8776 | +{ |
---|
| 8777 | + static const hda_nid_t pins[] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01}; |
---|
| 8778 | + unsigned int i; |
---|
| 8779 | + |
---|
| 8780 | + for (i = 0; i < ARRAY_SIZE(pins); i++) |
---|
| 8781 | + snd_hda_codec_write(codec, pins[i], 0, |
---|
| 8782 | + AC_VERB_SET_POWER_STATE, 0x03); |
---|
7000 | 8783 | } |
---|
7001 | 8784 | |
---|
7002 | 8785 | static void sbz_exit_chip(struct hda_codec *codec) |
---|
.. | .. |
---|
7039 | 8822 | ca0132_clear_unsolicited(codec); |
---|
7040 | 8823 | snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); |
---|
7041 | 8824 | snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b); |
---|
| 8825 | +} |
---|
| 8826 | + |
---|
| 8827 | +static void ae5_exit_chip(struct hda_codec *codec) |
---|
| 8828 | +{ |
---|
| 8829 | + chipio_set_stream_control(codec, 0x03, 0); |
---|
| 8830 | + chipio_set_stream_control(codec, 0x04, 0); |
---|
| 8831 | + |
---|
| 8832 | + ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f); |
---|
| 8833 | + ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); |
---|
| 8834 | + ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); |
---|
| 8835 | + ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00); |
---|
| 8836 | + ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00); |
---|
| 8837 | + ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x00); |
---|
| 8838 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
| 8839 | + ca0113_mmio_gpio_set(codec, 1, false); |
---|
| 8840 | + |
---|
| 8841 | + snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); |
---|
| 8842 | + snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); |
---|
| 8843 | + |
---|
| 8844 | + chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); |
---|
| 8845 | + |
---|
| 8846 | + chipio_set_stream_control(codec, 0x18, 0); |
---|
| 8847 | + chipio_set_stream_control(codec, 0x0c, 0); |
---|
| 8848 | + |
---|
| 8849 | + snd_hda_codec_write(codec, 0x01, 0, 0x724, 0x83); |
---|
| 8850 | +} |
---|
| 8851 | + |
---|
| 8852 | +static void ae7_exit_chip(struct hda_codec *codec) |
---|
| 8853 | +{ |
---|
| 8854 | + chipio_set_stream_control(codec, 0x18, 0); |
---|
| 8855 | + chipio_set_stream_source_dest(codec, 0x21, 0xc8, 0xc8); |
---|
| 8856 | + chipio_set_stream_channels(codec, 0x21, 0); |
---|
| 8857 | + chipio_set_control_param(codec, CONTROL_PARAM_NODE_ID, 0x09); |
---|
| 8858 | + chipio_set_control_param(codec, 0x20, 0x01); |
---|
| 8859 | + |
---|
| 8860 | + chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0); |
---|
| 8861 | + |
---|
| 8862 | + chipio_set_stream_control(codec, 0x18, 0); |
---|
| 8863 | + chipio_set_stream_control(codec, 0x0c, 0); |
---|
| 8864 | + |
---|
| 8865 | + ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00); |
---|
| 8866 | + snd_hda_codec_write(codec, 0x15, 0, 0x724, 0x83); |
---|
| 8867 | + ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83); |
---|
| 8868 | + ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00); |
---|
| 8869 | + ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x00); |
---|
| 8870 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
| 8871 | + ca0113_mmio_gpio_set(codec, 1, false); |
---|
| 8872 | + ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f); |
---|
| 8873 | + |
---|
| 8874 | + snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); |
---|
| 8875 | + snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); |
---|
| 8876 | +} |
---|
| 8877 | + |
---|
| 8878 | +static void zxr_exit_chip(struct hda_codec *codec) |
---|
| 8879 | +{ |
---|
| 8880 | + chipio_set_stream_control(codec, 0x03, 0); |
---|
| 8881 | + chipio_set_stream_control(codec, 0x04, 0); |
---|
| 8882 | + chipio_set_stream_control(codec, 0x14, 0); |
---|
| 8883 | + chipio_set_stream_control(codec, 0x0C, 0); |
---|
| 8884 | + |
---|
| 8885 | + chipio_set_conn_rate(codec, 0x41, SR_192_000); |
---|
| 8886 | + chipio_set_conn_rate(codec, 0x91, SR_192_000); |
---|
| 8887 | + |
---|
| 8888 | + chipio_write(codec, 0x18a020, 0x00000083); |
---|
| 8889 | + |
---|
| 8890 | + snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); |
---|
| 8891 | + snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53); |
---|
| 8892 | + |
---|
| 8893 | + ca0132_clear_unsolicited(codec); |
---|
| 8894 | + sbz_set_pin_ctl_default(codec); |
---|
| 8895 | + snd_hda_codec_write(codec, 0x0B, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x00); |
---|
| 8896 | + |
---|
| 8897 | + ca0113_mmio_gpio_set(codec, 5, false); |
---|
| 8898 | + ca0113_mmio_gpio_set(codec, 2, false); |
---|
| 8899 | + ca0113_mmio_gpio_set(codec, 3, false); |
---|
| 8900 | + ca0113_mmio_gpio_set(codec, 0, false); |
---|
| 8901 | + ca0113_mmio_gpio_set(codec, 4, true); |
---|
| 8902 | + ca0113_mmio_gpio_set(codec, 0, true); |
---|
| 8903 | + ca0113_mmio_gpio_set(codec, 5, true); |
---|
| 8904 | + ca0113_mmio_gpio_set(codec, 2, false); |
---|
| 8905 | + ca0113_mmio_gpio_set(codec, 3, false); |
---|
7042 | 8906 | } |
---|
7043 | 8907 | |
---|
7044 | 8908 | static void ca0132_exit_chip(struct hda_codec *codec) |
---|
.. | .. |
---|
7144 | 9008 | writel(0x00820680, spec->mem_base + 0x01C); |
---|
7145 | 9009 | writel(0x00820680, spec->mem_base + 0x01C); |
---|
7146 | 9010 | |
---|
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 | | - |
---|
7152 | 9011 | chipio_write(codec, 0x18b0a4, 0x000000c2); |
---|
7153 | 9012 | |
---|
7154 | 9013 | snd_hda_codec_write(codec, 0x11, 0, |
---|
.. | .. |
---|
7157 | 9016 | |
---|
7158 | 9017 | static void r3d_pre_dsp_setup(struct hda_codec *codec) |
---|
7159 | 9018 | { |
---|
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 | | - |
---|
7166 | 9019 | chipio_write(codec, 0x18b0a4, 0x000000c2); |
---|
7167 | 9020 | |
---|
7168 | 9021 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
.. | .. |
---|
7205 | 9058 | * what they do, or if they're necessary. Could possibly |
---|
7206 | 9059 | * be removed. Figure they're better to leave in. |
---|
7207 | 9060 | */ |
---|
| 9061 | +static const unsigned int ca0113_mmio_init_address_sbz[] = { |
---|
| 9062 | + 0x400, 0x408, 0x40c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c, |
---|
| 9063 | + 0xc0c, 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04 |
---|
| 9064 | +}; |
---|
| 9065 | + |
---|
| 9066 | +static const unsigned int ca0113_mmio_init_data_sbz[] = { |
---|
| 9067 | + 0x00000030, 0x00000000, 0x00000003, 0x00000003, 0x00000003, |
---|
| 9068 | + 0x00000003, 0x000000c1, 0x000000f1, 0x00000001, 0x000000c7, |
---|
| 9069 | + 0x000000c1, 0x00000080 |
---|
| 9070 | +}; |
---|
| 9071 | + |
---|
| 9072 | +static const unsigned int ca0113_mmio_init_data_zxr[] = { |
---|
| 9073 | + 0x00000030, 0x00000000, 0x00000000, 0x00000003, 0x00000003, |
---|
| 9074 | + 0x00000003, 0x00000001, 0x000000f1, 0x00000001, 0x000000c7, |
---|
| 9075 | + 0x000000c1, 0x00000080 |
---|
| 9076 | +}; |
---|
| 9077 | + |
---|
| 9078 | +static const unsigned int ca0113_mmio_init_address_ae5[] = { |
---|
| 9079 | + 0x400, 0x42c, 0x46c, 0x4ac, 0x4ec, 0x43c, 0x47c, 0x4bc, 0x4fc, 0x408, |
---|
| 9080 | + 0x100, 0x410, 0x40c, 0x100, 0x100, 0x830, 0x86c, 0x800, 0x86c, 0x800, |
---|
| 9081 | + 0x804, 0x20c, 0x01c, 0xc0c, 0xc00, 0xc04, 0xc0c, 0xc0c, 0xc0c, 0xc0c, |
---|
| 9082 | + 0xc08, 0xc08, 0xc08, 0xc08, 0xc08, 0xc04, 0x01c |
---|
| 9083 | +}; |
---|
| 9084 | + |
---|
| 9085 | +static const unsigned int ca0113_mmio_init_data_ae5[] = { |
---|
| 9086 | + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
---|
| 9087 | + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, |
---|
| 9088 | + 0x00000600, 0x00000014, 0x00000001, 0x0000060f, 0x0000070f, |
---|
| 9089 | + 0x00000aff, 0x00000000, 0x0000006b, 0x00000001, 0x0000006b, |
---|
| 9090 | + 0x00000057, 0x00800000, 0x00880680, 0x00000080, 0x00000030, |
---|
| 9091 | + 0x00000000, 0x00000000, 0x00000003, 0x00000003, 0x00000003, |
---|
| 9092 | + 0x00000001, 0x000000f1, 0x00000001, 0x000000c7, 0x000000c1, |
---|
| 9093 | + 0x00000080, 0x00880680 |
---|
| 9094 | +}; |
---|
| 9095 | + |
---|
| 9096 | +static void ca0132_mmio_init_sbz(struct hda_codec *codec) |
---|
| 9097 | +{ |
---|
| 9098 | + struct ca0132_spec *spec = codec->spec; |
---|
| 9099 | + unsigned int tmp[2], i, count, cur_addr; |
---|
| 9100 | + const unsigned int *addr, *data; |
---|
| 9101 | + |
---|
| 9102 | + addr = ca0113_mmio_init_address_sbz; |
---|
| 9103 | + for (i = 0; i < 3; i++) |
---|
| 9104 | + writel(0x00000000, spec->mem_base + addr[i]); |
---|
| 9105 | + |
---|
| 9106 | + cur_addr = i; |
---|
| 9107 | + switch (ca0132_quirk(spec)) { |
---|
| 9108 | + case QUIRK_ZXR: |
---|
| 9109 | + tmp[0] = 0x00880480; |
---|
| 9110 | + tmp[1] = 0x00000080; |
---|
| 9111 | + break; |
---|
| 9112 | + case QUIRK_SBZ: |
---|
| 9113 | + tmp[0] = 0x00820680; |
---|
| 9114 | + tmp[1] = 0x00000083; |
---|
| 9115 | + break; |
---|
| 9116 | + case QUIRK_R3D: |
---|
| 9117 | + tmp[0] = 0x00880680; |
---|
| 9118 | + tmp[1] = 0x00000083; |
---|
| 9119 | + break; |
---|
| 9120 | + default: |
---|
| 9121 | + tmp[0] = 0x00000000; |
---|
| 9122 | + tmp[1] = 0x00000000; |
---|
| 9123 | + break; |
---|
| 9124 | + } |
---|
| 9125 | + |
---|
| 9126 | + for (i = 0; i < 2; i++) |
---|
| 9127 | + writel(tmp[i], spec->mem_base + addr[cur_addr + i]); |
---|
| 9128 | + |
---|
| 9129 | + cur_addr += i; |
---|
| 9130 | + |
---|
| 9131 | + switch (ca0132_quirk(spec)) { |
---|
| 9132 | + case QUIRK_ZXR: |
---|
| 9133 | + count = ARRAY_SIZE(ca0113_mmio_init_data_zxr); |
---|
| 9134 | + data = ca0113_mmio_init_data_zxr; |
---|
| 9135 | + break; |
---|
| 9136 | + default: |
---|
| 9137 | + count = ARRAY_SIZE(ca0113_mmio_init_data_sbz); |
---|
| 9138 | + data = ca0113_mmio_init_data_sbz; |
---|
| 9139 | + break; |
---|
| 9140 | + } |
---|
| 9141 | + |
---|
| 9142 | + for (i = 0; i < count; i++) |
---|
| 9143 | + writel(data[i], spec->mem_base + addr[cur_addr + i]); |
---|
| 9144 | +} |
---|
| 9145 | + |
---|
| 9146 | +static void ca0132_mmio_init_ae5(struct hda_codec *codec) |
---|
| 9147 | +{ |
---|
| 9148 | + struct ca0132_spec *spec = codec->spec; |
---|
| 9149 | + const unsigned int *addr, *data; |
---|
| 9150 | + unsigned int i, count; |
---|
| 9151 | + |
---|
| 9152 | + addr = ca0113_mmio_init_address_ae5; |
---|
| 9153 | + data = ca0113_mmio_init_data_ae5; |
---|
| 9154 | + count = ARRAY_SIZE(ca0113_mmio_init_data_ae5); |
---|
| 9155 | + |
---|
| 9156 | + if (ca0132_quirk(spec) == QUIRK_AE7) { |
---|
| 9157 | + writel(0x00000680, spec->mem_base + 0x1c); |
---|
| 9158 | + writel(0x00880680, spec->mem_base + 0x1c); |
---|
| 9159 | + } |
---|
| 9160 | + |
---|
| 9161 | + for (i = 0; i < count; i++) { |
---|
| 9162 | + /* |
---|
| 9163 | + * AE-7 shares all writes with the AE-5, except that it writes |
---|
| 9164 | + * a different value to 0x20c. |
---|
| 9165 | + */ |
---|
| 9166 | + if (i == 21 && ca0132_quirk(spec) == QUIRK_AE7) { |
---|
| 9167 | + writel(0x00800001, spec->mem_base + addr[i]); |
---|
| 9168 | + continue; |
---|
| 9169 | + } |
---|
| 9170 | + |
---|
| 9171 | + writel(data[i], spec->mem_base + addr[i]); |
---|
| 9172 | + } |
---|
| 9173 | + |
---|
| 9174 | + if (ca0132_quirk(spec) == QUIRK_AE5) |
---|
| 9175 | + writel(0x00880680, spec->mem_base + 0x1c); |
---|
| 9176 | +} |
---|
| 9177 | + |
---|
7208 | 9178 | static void ca0132_mmio_init(struct hda_codec *codec) |
---|
7209 | 9179 | { |
---|
7210 | 9180 | struct ca0132_spec *spec = codec->spec; |
---|
7211 | 9181 | |
---|
7212 | | - writel(0x00000000, spec->mem_base + 0x400); |
---|
7213 | | - writel(0x00000000, spec->mem_base + 0x408); |
---|
7214 | | - writel(0x00000000, spec->mem_base + 0x40C); |
---|
7215 | | - writel(0x00880680, spec->mem_base + 0x01C); |
---|
7216 | | - writel(0x00000083, spec->mem_base + 0xC0C); |
---|
7217 | | - writel(0x00000030, spec->mem_base + 0xC00); |
---|
7218 | | - writel(0x00000000, spec->mem_base + 0xC04); |
---|
7219 | | - writel(0x00000003, spec->mem_base + 0xC0C); |
---|
7220 | | - writel(0x00000003, spec->mem_base + 0xC0C); |
---|
7221 | | - writel(0x00000003, spec->mem_base + 0xC0C); |
---|
7222 | | - writel(0x00000003, spec->mem_base + 0xC0C); |
---|
7223 | | - writel(0x000000C1, spec->mem_base + 0xC08); |
---|
7224 | | - writel(0x000000F1, spec->mem_base + 0xC08); |
---|
7225 | | - writel(0x00000001, spec->mem_base + 0xC08); |
---|
7226 | | - writel(0x000000C7, spec->mem_base + 0xC08); |
---|
7227 | | - writel(0x000000C1, spec->mem_base + 0xC08); |
---|
7228 | | - writel(0x00000080, spec->mem_base + 0xC04); |
---|
| 9182 | + switch (ca0132_quirk(spec)) { |
---|
| 9183 | + case QUIRK_R3D: |
---|
| 9184 | + case QUIRK_SBZ: |
---|
| 9185 | + case QUIRK_ZXR: |
---|
| 9186 | + ca0132_mmio_init_sbz(codec); |
---|
| 9187 | + break; |
---|
| 9188 | + case QUIRK_AE5: |
---|
| 9189 | + ca0132_mmio_init_ae5(codec); |
---|
| 9190 | + break; |
---|
| 9191 | + default: |
---|
| 9192 | + break; |
---|
| 9193 | + } |
---|
| 9194 | +} |
---|
| 9195 | + |
---|
| 9196 | +static const unsigned int ca0132_ae5_register_set_addresses[] = { |
---|
| 9197 | + 0x304, 0x304, 0x304, 0x304, 0x100, 0x304, 0x100, 0x304, 0x100, 0x304, |
---|
| 9198 | + 0x100, 0x304, 0x86c, 0x800, 0x86c, 0x800, 0x804 |
---|
| 9199 | +}; |
---|
| 9200 | + |
---|
| 9201 | +static const unsigned char ca0132_ae5_register_set_data[] = { |
---|
| 9202 | + 0x0f, 0x0e, 0x1f, 0x0c, 0x3f, 0x08, 0x7f, 0x00, 0xff, 0x00, 0x6b, |
---|
| 9203 | + 0x01, 0x6b, 0x57 |
---|
| 9204 | +}; |
---|
| 9205 | + |
---|
| 9206 | +/* |
---|
| 9207 | + * This function writes to some SFR's, does some region2 writes, and then |
---|
| 9208 | + * eventually resets the codec with the 0x7ff verb. Not quite sure why it does |
---|
| 9209 | + * what it does. |
---|
| 9210 | + */ |
---|
| 9211 | +static void ae5_register_set(struct hda_codec *codec) |
---|
| 9212 | +{ |
---|
| 9213 | + struct ca0132_spec *spec = codec->spec; |
---|
| 9214 | + unsigned int count = ARRAY_SIZE(ca0132_ae5_register_set_addresses); |
---|
| 9215 | + const unsigned int *addr = ca0132_ae5_register_set_addresses; |
---|
| 9216 | + const unsigned char *data = ca0132_ae5_register_set_data; |
---|
| 9217 | + unsigned int i, cur_addr; |
---|
| 9218 | + unsigned char tmp[3]; |
---|
| 9219 | + |
---|
| 9220 | + if (ca0132_quirk(spec) == QUIRK_AE7) { |
---|
| 9221 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9222 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41); |
---|
| 9223 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9224 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8); |
---|
| 9225 | + } |
---|
| 9226 | + |
---|
| 9227 | + chipio_8051_write_direct(codec, 0x93, 0x10); |
---|
| 9228 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9229 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44); |
---|
| 9230 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9231 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2); |
---|
| 9232 | + |
---|
| 9233 | + if (ca0132_quirk(spec) == QUIRK_AE7) { |
---|
| 9234 | + tmp[0] = 0x03; |
---|
| 9235 | + tmp[1] = 0x03; |
---|
| 9236 | + tmp[2] = 0x07; |
---|
| 9237 | + } else { |
---|
| 9238 | + tmp[0] = 0x0f; |
---|
| 9239 | + tmp[1] = 0x0f; |
---|
| 9240 | + tmp[2] = 0x0f; |
---|
| 9241 | + } |
---|
| 9242 | + |
---|
| 9243 | + for (i = cur_addr = 0; i < 3; i++, cur_addr++) |
---|
| 9244 | + writeb(tmp[i], spec->mem_base + addr[cur_addr]); |
---|
| 9245 | + |
---|
| 9246 | + /* |
---|
| 9247 | + * First writes are in single bytes, final are in 4 bytes. So, we use |
---|
| 9248 | + * writeb, then writel. |
---|
| 9249 | + */ |
---|
| 9250 | + for (i = 0; cur_addr < 12; i++, cur_addr++) |
---|
| 9251 | + writeb(data[i], spec->mem_base + addr[cur_addr]); |
---|
| 9252 | + |
---|
| 9253 | + for (; cur_addr < count; i++, cur_addr++) |
---|
| 9254 | + writel(data[i], spec->mem_base + addr[cur_addr]); |
---|
| 9255 | + |
---|
| 9256 | + writel(0x00800001, spec->mem_base + 0x20c); |
---|
| 9257 | + |
---|
| 9258 | + if (ca0132_quirk(spec) == QUIRK_AE7) { |
---|
| 9259 | + ca0113_mmio_command_set_type2(codec, 0x48, 0x07, 0x83); |
---|
| 9260 | + ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f); |
---|
| 9261 | + } else { |
---|
| 9262 | + ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f); |
---|
| 9263 | + } |
---|
| 9264 | + |
---|
| 9265 | + chipio_8051_write_direct(codec, 0x90, 0x00); |
---|
| 9266 | + chipio_8051_write_direct(codec, 0x90, 0x10); |
---|
| 9267 | + |
---|
| 9268 | + if (ca0132_quirk(spec) == QUIRK_AE5) |
---|
| 9269 | + ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83); |
---|
| 9270 | + |
---|
| 9271 | + chipio_write(codec, 0x18b0a4, 0x000000c2); |
---|
| 9272 | + |
---|
| 9273 | + snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00); |
---|
| 9274 | + snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00); |
---|
7229 | 9275 | } |
---|
7230 | 9276 | |
---|
7231 | 9277 | /* |
---|
.. | .. |
---|
7239 | 9285 | |
---|
7240 | 9286 | ca0132_alt_vol_setup(codec); |
---|
7241 | 9287 | |
---|
7242 | | - switch (spec->quirk) { |
---|
| 9288 | + switch (ca0132_quirk(spec)) { |
---|
7243 | 9289 | case QUIRK_SBZ: |
---|
7244 | 9290 | codec_dbg(codec, "SBZ alt_init"); |
---|
7245 | 9291 | ca0132_gpio_init(codec); |
---|
.. | .. |
---|
7260 | 9306 | r3d_pre_dsp_setup(codec); |
---|
7261 | 9307 | snd_hda_sequence_write(codec, spec->chip_init_verbs); |
---|
7262 | 9308 | snd_hda_sequence_write(codec, spec->desktop_init_verbs); |
---|
| 9309 | + break; |
---|
| 9310 | + case QUIRK_AE5: |
---|
| 9311 | + ca0132_gpio_init(codec); |
---|
| 9312 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9313 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49); |
---|
| 9314 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9315 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88); |
---|
| 9316 | + chipio_write(codec, 0x18b030, 0x00000020); |
---|
| 9317 | + snd_hda_sequence_write(codec, spec->chip_init_verbs); |
---|
| 9318 | + snd_hda_sequence_write(codec, spec->desktop_init_verbs); |
---|
| 9319 | + ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f); |
---|
| 9320 | + break; |
---|
| 9321 | + case QUIRK_AE7: |
---|
| 9322 | + ca0132_gpio_init(codec); |
---|
| 9323 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9324 | + VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49); |
---|
| 9325 | + snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
| 9326 | + VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88); |
---|
| 9327 | + snd_hda_sequence_write(codec, spec->chip_init_verbs); |
---|
| 9328 | + snd_hda_sequence_write(codec, spec->desktop_init_verbs); |
---|
| 9329 | + chipio_write(codec, 0x18b008, 0x000000f8); |
---|
| 9330 | + chipio_write(codec, 0x18b008, 0x000000f0); |
---|
| 9331 | + chipio_write(codec, 0x18b030, 0x00000020); |
---|
| 9332 | + ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f); |
---|
| 9333 | + break; |
---|
| 9334 | + case QUIRK_ZXR: |
---|
| 9335 | + snd_hda_sequence_write(codec, spec->chip_init_verbs); |
---|
| 9336 | + snd_hda_sequence_write(codec, spec->desktop_init_verbs); |
---|
| 9337 | + break; |
---|
| 9338 | + default: |
---|
7263 | 9339 | break; |
---|
7264 | 9340 | } |
---|
7265 | 9341 | } |
---|
.. | .. |
---|
7287 | 9363 | spec->dsp_reload = true; |
---|
7288 | 9364 | spec->dsp_state = DSP_DOWNLOAD_INIT; |
---|
7289 | 9365 | } else { |
---|
7290 | | - if (spec->quirk == QUIRK_SBZ) |
---|
| 9366 | + if (ca0132_quirk(spec) == QUIRK_SBZ) |
---|
7291 | 9367 | sbz_dsp_startup_check(codec); |
---|
7292 | 9368 | return 0; |
---|
7293 | 9369 | } |
---|
.. | .. |
---|
7297 | 9373 | spec->dsp_state = DSP_DOWNLOAD_INIT; |
---|
7298 | 9374 | spec->curr_chip_addx = INVALID_CHIP_ADDRESS; |
---|
7299 | 9375 | |
---|
7300 | | - if (spec->use_pci_mmio) |
---|
| 9376 | + if (ca0132_use_pci_mmio(spec)) |
---|
7301 | 9377 | ca0132_mmio_init(codec); |
---|
7302 | 9378 | |
---|
7303 | 9379 | snd_hda_power_up_pm(codec); |
---|
| 9380 | + |
---|
| 9381 | + if (ca0132_quirk(spec) == QUIRK_AE5 || ca0132_quirk(spec) == QUIRK_AE7) |
---|
| 9382 | + ae5_register_set(codec); |
---|
7304 | 9383 | |
---|
7305 | 9384 | ca0132_init_unsol(codec); |
---|
7306 | 9385 | ca0132_init_params(codec); |
---|
.. | .. |
---|
7308 | 9387 | |
---|
7309 | 9388 | snd_hda_sequence_write(codec, spec->base_init_verbs); |
---|
7310 | 9389 | |
---|
7311 | | - if (spec->use_alt_functions) |
---|
| 9390 | + if (ca0132_use_alt_functions(spec)) |
---|
7312 | 9391 | ca0132_alt_init(codec); |
---|
7313 | 9392 | |
---|
7314 | 9393 | ca0132_download_dsp(codec); |
---|
7315 | 9394 | |
---|
7316 | 9395 | ca0132_refresh_widget_caps(codec); |
---|
7317 | 9396 | |
---|
7318 | | - switch (spec->quirk) { |
---|
| 9397 | + switch (ca0132_quirk(spec)) { |
---|
7319 | 9398 | case QUIRK_R3DI: |
---|
7320 | 9399 | case QUIRK_R3D: |
---|
7321 | 9400 | r3d_setup_defaults(codec); |
---|
7322 | 9401 | break; |
---|
7323 | 9402 | case QUIRK_SBZ: |
---|
| 9403 | + case QUIRK_ZXR: |
---|
7324 | 9404 | sbz_setup_defaults(codec); |
---|
| 9405 | + break; |
---|
| 9406 | + case QUIRK_AE5: |
---|
| 9407 | + ae5_setup_defaults(codec); |
---|
| 9408 | + break; |
---|
| 9409 | + case QUIRK_AE7: |
---|
| 9410 | + ae7_setup_defaults(codec); |
---|
7325 | 9411 | break; |
---|
7326 | 9412 | default: |
---|
7327 | 9413 | ca0132_setup_defaults(codec); |
---|
.. | .. |
---|
7340 | 9426 | |
---|
7341 | 9427 | init_input(codec, cfg->dig_in_pin, spec->dig_in); |
---|
7342 | 9428 | |
---|
7343 | | - if (!spec->use_alt_functions) { |
---|
| 9429 | + if (!ca0132_use_alt_functions(spec)) { |
---|
7344 | 9430 | snd_hda_sequence_write(codec, spec->chip_init_verbs); |
---|
7345 | 9431 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, |
---|
7346 | 9432 | VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D); |
---|
.. | .. |
---|
7348 | 9434 | VENDOR_CHIPIO_PARAM_EX_VALUE_SET, 0x20); |
---|
7349 | 9435 | } |
---|
7350 | 9436 | |
---|
7351 | | - if (spec->quirk == QUIRK_SBZ) |
---|
| 9437 | + if (ca0132_quirk(spec) == QUIRK_SBZ) |
---|
7352 | 9438 | ca0132_gpio_setup(codec); |
---|
7353 | 9439 | |
---|
7354 | 9440 | snd_hda_sequence_write(codec, spec->spec_init_verbs); |
---|
7355 | | - if (spec->use_alt_functions) { |
---|
| 9441 | + if (ca0132_use_alt_functions(spec)) { |
---|
7356 | 9442 | ca0132_alt_select_out(codec); |
---|
7357 | 9443 | ca0132_alt_select_in(codec); |
---|
7358 | 9444 | } else { |
---|
.. | .. |
---|
7376 | 9462 | return 0; |
---|
7377 | 9463 | } |
---|
7378 | 9464 | |
---|
| 9465 | +static int dbpro_init(struct hda_codec *codec) |
---|
| 9466 | +{ |
---|
| 9467 | + struct ca0132_spec *spec = codec->spec; |
---|
| 9468 | + struct auto_pin_cfg *cfg = &spec->autocfg; |
---|
| 9469 | + unsigned int i; |
---|
| 9470 | + |
---|
| 9471 | + init_output(codec, cfg->dig_out_pins[0], spec->dig_out); |
---|
| 9472 | + init_input(codec, cfg->dig_in_pin, spec->dig_in); |
---|
| 9473 | + |
---|
| 9474 | + for (i = 0; i < spec->num_inputs; i++) |
---|
| 9475 | + init_input(codec, spec->input_pins[i], spec->adcs[i]); |
---|
| 9476 | + |
---|
| 9477 | + return 0; |
---|
| 9478 | +} |
---|
| 9479 | + |
---|
7379 | 9480 | static void ca0132_free(struct hda_codec *codec) |
---|
7380 | 9481 | { |
---|
7381 | 9482 | struct ca0132_spec *spec = codec->spec; |
---|
7382 | 9483 | |
---|
7383 | 9484 | cancel_delayed_work_sync(&spec->unsol_hp_work); |
---|
7384 | 9485 | snd_hda_power_up(codec); |
---|
7385 | | - switch (spec->quirk) { |
---|
| 9486 | + switch (ca0132_quirk(spec)) { |
---|
7386 | 9487 | case QUIRK_SBZ: |
---|
7387 | 9488 | sbz_exit_chip(codec); |
---|
| 9489 | + break; |
---|
| 9490 | + case QUIRK_ZXR: |
---|
| 9491 | + zxr_exit_chip(codec); |
---|
7388 | 9492 | break; |
---|
7389 | 9493 | case QUIRK_R3D: |
---|
7390 | 9494 | r3d_exit_chip(codec); |
---|
7391 | 9495 | break; |
---|
| 9496 | + case QUIRK_AE5: |
---|
| 9497 | + ae5_exit_chip(codec); |
---|
| 9498 | + break; |
---|
| 9499 | + case QUIRK_AE7: |
---|
| 9500 | + ae7_exit_chip(codec); |
---|
| 9501 | + break; |
---|
7392 | 9502 | case QUIRK_R3DI: |
---|
7393 | 9503 | r3di_gpio_shutdown(codec); |
---|
| 9504 | + break; |
---|
| 9505 | + default: |
---|
7394 | 9506 | break; |
---|
7395 | 9507 | } |
---|
7396 | 9508 | |
---|
.. | .. |
---|
7402 | 9514 | if (spec->mem_base) |
---|
7403 | 9515 | pci_iounmap(codec->bus->pci, spec->mem_base); |
---|
7404 | 9516 | #endif |
---|
| 9517 | + kfree(spec->spec_init_verbs); |
---|
| 9518 | + kfree(codec->spec); |
---|
| 9519 | +} |
---|
| 9520 | + |
---|
| 9521 | +static void dbpro_free(struct hda_codec *codec) |
---|
| 9522 | +{ |
---|
| 9523 | + struct ca0132_spec *spec = codec->spec; |
---|
| 9524 | + |
---|
| 9525 | + zxr_dbpro_power_state_shutdown(codec); |
---|
| 9526 | + |
---|
7405 | 9527 | kfree(spec->spec_init_verbs); |
---|
7406 | 9528 | kfree(codec->spec); |
---|
7407 | 9529 | } |
---|
.. | .. |
---|
7433 | 9555 | .reboot_notify = ca0132_reboot_notify, |
---|
7434 | 9556 | }; |
---|
7435 | 9557 | |
---|
| 9558 | +static const struct hda_codec_ops dbpro_patch_ops = { |
---|
| 9559 | + .build_controls = dbpro_build_controls, |
---|
| 9560 | + .build_pcms = dbpro_build_pcms, |
---|
| 9561 | + .init = dbpro_init, |
---|
| 9562 | + .free = dbpro_free, |
---|
| 9563 | +}; |
---|
| 9564 | + |
---|
7436 | 9565 | static void ca0132_config(struct hda_codec *codec) |
---|
7437 | 9566 | { |
---|
7438 | 9567 | struct ca0132_spec *spec = codec->spec; |
---|
.. | .. |
---|
7444 | 9573 | spec->multiout.dac_nids = spec->dacs; |
---|
7445 | 9574 | spec->multiout.num_dacs = 3; |
---|
7446 | 9575 | |
---|
7447 | | - if (!spec->use_alt_functions) |
---|
| 9576 | + if (!ca0132_use_alt_functions(spec)) |
---|
7448 | 9577 | spec->multiout.max_channels = 2; |
---|
7449 | 9578 | else |
---|
7450 | 9579 | spec->multiout.max_channels = 6; |
---|
7451 | 9580 | |
---|
7452 | | - switch (spec->quirk) { |
---|
| 9581 | + switch (ca0132_quirk(spec)) { |
---|
7453 | 9582 | case QUIRK_ALIENWARE: |
---|
7454 | | - codec_dbg(codec, "ca0132_config: QUIRK_ALIENWARE applied.\n"); |
---|
| 9583 | + codec_dbg(codec, "%s: QUIRK_ALIENWARE applied.\n", __func__); |
---|
7455 | 9584 | snd_hda_apply_pincfgs(codec, alienware_pincfgs); |
---|
| 9585 | + break; |
---|
| 9586 | + case QUIRK_SBZ: |
---|
| 9587 | + codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__); |
---|
| 9588 | + snd_hda_apply_pincfgs(codec, sbz_pincfgs); |
---|
| 9589 | + break; |
---|
| 9590 | + case QUIRK_ZXR: |
---|
| 9591 | + codec_dbg(codec, "%s: QUIRK_ZXR applied.\n", __func__); |
---|
| 9592 | + snd_hda_apply_pincfgs(codec, zxr_pincfgs); |
---|
| 9593 | + break; |
---|
| 9594 | + case QUIRK_R3D: |
---|
| 9595 | + codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__); |
---|
| 9596 | + snd_hda_apply_pincfgs(codec, r3d_pincfgs); |
---|
| 9597 | + break; |
---|
| 9598 | + case QUIRK_R3DI: |
---|
| 9599 | + codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__); |
---|
| 9600 | + snd_hda_apply_pincfgs(codec, r3di_pincfgs); |
---|
| 9601 | + break; |
---|
| 9602 | + case QUIRK_AE5: |
---|
| 9603 | + codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__); |
---|
| 9604 | + snd_hda_apply_pincfgs(codec, ae5_pincfgs); |
---|
| 9605 | + break; |
---|
| 9606 | + case QUIRK_AE7: |
---|
| 9607 | + codec_dbg(codec, "%s: QUIRK_AE7 applied.\n", __func__); |
---|
| 9608 | + snd_hda_apply_pincfgs(codec, ae7_pincfgs); |
---|
| 9609 | + break; |
---|
| 9610 | + default: |
---|
| 9611 | + break; |
---|
| 9612 | + } |
---|
7456 | 9613 | |
---|
| 9614 | + switch (ca0132_quirk(spec)) { |
---|
| 9615 | + case QUIRK_ALIENWARE: |
---|
7457 | 9616 | spec->num_outputs = 2; |
---|
7458 | 9617 | spec->out_pins[0] = 0x0b; /* speaker out */ |
---|
7459 | 9618 | spec->out_pins[1] = 0x0f; |
---|
.. | .. |
---|
7473 | 9632 | break; |
---|
7474 | 9633 | case QUIRK_SBZ: |
---|
7475 | 9634 | 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 | | - |
---|
7485 | 9635 | spec->num_outputs = 2; |
---|
7486 | 9636 | spec->out_pins[0] = 0x0B; /* Line out */ |
---|
7487 | 9637 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ |
---|
.. | .. |
---|
7506 | 9656 | spec->multiout.dig_out_nid = spec->dig_out; |
---|
7507 | 9657 | spec->dig_in = 0x09; |
---|
7508 | 9658 | break; |
---|
7509 | | - case QUIRK_R3DI: |
---|
7510 | | - codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__); |
---|
7511 | | - snd_hda_apply_pincfgs(codec, r3di_pincfgs); |
---|
| 9659 | + case QUIRK_ZXR: |
---|
| 9660 | + spec->num_outputs = 2; |
---|
| 9661 | + spec->out_pins[0] = 0x0B; /* Line out */ |
---|
| 9662 | + spec->out_pins[1] = 0x0F; /* Rear headphone out */ |
---|
| 9663 | + spec->out_pins[2] = 0x10; /* Center/LFE */ |
---|
| 9664 | + spec->out_pins[3] = 0x11; /* Rear surround */ |
---|
| 9665 | + spec->shared_out_nid = 0x2; |
---|
| 9666 | + spec->unsol_tag_hp = spec->out_pins[1]; |
---|
| 9667 | + spec->unsol_tag_front_hp = spec->out_pins[2]; |
---|
7512 | 9668 | |
---|
| 9669 | + spec->adcs[0] = 0x7; /* Rear Mic / Line-in */ |
---|
| 9670 | + spec->adcs[1] = 0x8; /* Not connected, no front mic */ |
---|
| 9671 | + spec->adcs[2] = 0xa; /* what u hear */ |
---|
| 9672 | + |
---|
| 9673 | + spec->num_inputs = 2; |
---|
| 9674 | + spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */ |
---|
| 9675 | + spec->input_pins[1] = 0x13; /* What U Hear */ |
---|
| 9676 | + spec->shared_mic_nid = 0x7; |
---|
| 9677 | + spec->unsol_tag_amic1 = spec->input_pins[0]; |
---|
| 9678 | + break; |
---|
| 9679 | + case QUIRK_ZXR_DBPRO: |
---|
| 9680 | + spec->adcs[0] = 0x8; /* ZxR DBPro Aux In */ |
---|
| 9681 | + |
---|
| 9682 | + spec->num_inputs = 1; |
---|
| 9683 | + spec->input_pins[0] = 0x11; /* RCA Line-in */ |
---|
| 9684 | + |
---|
| 9685 | + spec->dig_out = 0x05; |
---|
| 9686 | + spec->multiout.dig_out_nid = spec->dig_out; |
---|
| 9687 | + |
---|
| 9688 | + spec->dig_in = 0x09; |
---|
| 9689 | + break; |
---|
| 9690 | + case QUIRK_AE5: |
---|
| 9691 | + case QUIRK_AE7: |
---|
| 9692 | + spec->num_outputs = 2; |
---|
| 9693 | + spec->out_pins[0] = 0x0B; /* Line out */ |
---|
| 9694 | + spec->out_pins[1] = 0x11; /* Rear headphone out */ |
---|
| 9695 | + spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/ |
---|
| 9696 | + spec->out_pins[3] = 0x0F; /* Rear surround */ |
---|
| 9697 | + spec->shared_out_nid = 0x2; |
---|
| 9698 | + spec->unsol_tag_hp = spec->out_pins[1]; |
---|
| 9699 | + spec->unsol_tag_front_hp = spec->out_pins[2]; |
---|
| 9700 | + |
---|
| 9701 | + spec->adcs[0] = 0x7; /* Rear Mic / Line-in */ |
---|
| 9702 | + spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */ |
---|
| 9703 | + spec->adcs[2] = 0xa; /* what u hear */ |
---|
| 9704 | + |
---|
| 9705 | + spec->num_inputs = 2; |
---|
| 9706 | + spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */ |
---|
| 9707 | + spec->input_pins[1] = 0x13; /* What U Hear */ |
---|
| 9708 | + spec->shared_mic_nid = 0x7; |
---|
| 9709 | + spec->unsol_tag_amic1 = spec->input_pins[0]; |
---|
| 9710 | + |
---|
| 9711 | + /* SPDIF I/O */ |
---|
| 9712 | + spec->dig_out = 0x05; |
---|
| 9713 | + spec->multiout.dig_out_nid = spec->dig_out; |
---|
| 9714 | + break; |
---|
| 9715 | + case QUIRK_R3DI: |
---|
7513 | 9716 | spec->num_outputs = 2; |
---|
7514 | 9717 | spec->out_pins[0] = 0x0B; /* Line out */ |
---|
7515 | 9718 | spec->out_pins[1] = 0x0F; /* Rear headphone out */ |
---|
.. | .. |
---|
7566 | 9769 | struct ca0132_spec *spec = codec->spec; |
---|
7567 | 9770 | |
---|
7568 | 9771 | spec->chip_init_verbs = ca0132_init_verbs0; |
---|
7569 | | - if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3D) |
---|
| 9772 | + /* |
---|
| 9773 | + * Since desktop cards use pci_mmio, this can be used to determine |
---|
| 9774 | + * whether or not to use these verbs instead of a separate bool. |
---|
| 9775 | + */ |
---|
| 9776 | + if (ca0132_use_pci_mmio(spec)) |
---|
7570 | 9777 | spec->desktop_init_verbs = ca0132_init_verbs1; |
---|
7571 | 9778 | spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS, |
---|
7572 | 9779 | sizeof(struct hda_verb), |
---|
.. | .. |
---|
7598 | 9805 | return 0; |
---|
7599 | 9806 | } |
---|
7600 | 9807 | |
---|
| 9808 | +/* |
---|
| 9809 | + * The Sound Blaster ZxR shares the same PCI subsystem ID as some regular |
---|
| 9810 | + * Sound Blaster Z cards. However, they have different HDA codec subsystem |
---|
| 9811 | + * ID's. So, we check for the ZxR's subsystem ID, as well as the DBPro |
---|
| 9812 | + * daughter boards ID. |
---|
| 9813 | + */ |
---|
| 9814 | +static void sbz_detect_quirk(struct hda_codec *codec) |
---|
| 9815 | +{ |
---|
| 9816 | + struct ca0132_spec *spec = codec->spec; |
---|
| 9817 | + |
---|
| 9818 | + switch (codec->core.subsystem_id) { |
---|
| 9819 | + case 0x11020033: |
---|
| 9820 | + spec->quirk = QUIRK_ZXR; |
---|
| 9821 | + break; |
---|
| 9822 | + case 0x1102003f: |
---|
| 9823 | + spec->quirk = QUIRK_ZXR_DBPRO; |
---|
| 9824 | + break; |
---|
| 9825 | + default: |
---|
| 9826 | + spec->quirk = QUIRK_SBZ; |
---|
| 9827 | + break; |
---|
| 9828 | + } |
---|
| 9829 | +} |
---|
| 9830 | + |
---|
7601 | 9831 | static int patch_ca0132(struct hda_codec *codec) |
---|
7602 | 9832 | { |
---|
7603 | 9833 | struct ca0132_spec *spec; |
---|
.. | .. |
---|
7612 | 9842 | codec->spec = spec; |
---|
7613 | 9843 | spec->codec = codec; |
---|
7614 | 9844 | |
---|
7615 | | - codec->patch_ops = ca0132_patch_ops; |
---|
7616 | | - codec->pcm_format_first = 1; |
---|
7617 | | - codec->no_sticky_stream = 1; |
---|
7618 | | - |
---|
7619 | 9845 | /* Detect codec quirk */ |
---|
7620 | 9846 | quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks); |
---|
7621 | 9847 | if (quirk) |
---|
7622 | 9848 | spec->quirk = quirk->value; |
---|
7623 | 9849 | else |
---|
7624 | 9850 | spec->quirk = QUIRK_NONE; |
---|
| 9851 | + if (ca0132_quirk(spec) == QUIRK_SBZ) |
---|
| 9852 | + sbz_detect_quirk(codec); |
---|
| 9853 | + |
---|
| 9854 | + if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) |
---|
| 9855 | + codec->patch_ops = dbpro_patch_ops; |
---|
| 9856 | + else |
---|
| 9857 | + codec->patch_ops = ca0132_patch_ops; |
---|
| 9858 | + |
---|
| 9859 | + codec->pcm_format_first = 1; |
---|
| 9860 | + codec->no_sticky_stream = 1; |
---|
| 9861 | + |
---|
7625 | 9862 | |
---|
7626 | 9863 | spec->dsp_state = DSP_DOWNLOAD_INIT; |
---|
7627 | 9864 | spec->num_mixers = 1; |
---|
7628 | 9865 | |
---|
7629 | 9866 | /* Set which mixers each quirk uses. */ |
---|
7630 | | - switch (spec->quirk) { |
---|
| 9867 | + switch (ca0132_quirk(spec)) { |
---|
7631 | 9868 | case QUIRK_SBZ: |
---|
7632 | 9869 | spec->mixers[0] = desktop_mixer; |
---|
7633 | 9870 | snd_hda_codec_set_name(codec, "Sound Blaster Z"); |
---|
| 9871 | + break; |
---|
| 9872 | + case QUIRK_ZXR: |
---|
| 9873 | + spec->mixers[0] = desktop_mixer; |
---|
| 9874 | + snd_hda_codec_set_name(codec, "Sound Blaster ZxR"); |
---|
| 9875 | + break; |
---|
| 9876 | + case QUIRK_ZXR_DBPRO: |
---|
7634 | 9877 | break; |
---|
7635 | 9878 | case QUIRK_R3D: |
---|
7636 | 9879 | spec->mixers[0] = desktop_mixer; |
---|
.. | .. |
---|
7640 | 9883 | spec->mixers[0] = r3di_mixer; |
---|
7641 | 9884 | snd_hda_codec_set_name(codec, "Recon3Di"); |
---|
7642 | 9885 | break; |
---|
| 9886 | + case QUIRK_AE5: |
---|
| 9887 | + spec->mixers[0] = desktop_mixer; |
---|
| 9888 | + snd_hda_codec_set_name(codec, "Sound BlasterX AE-5"); |
---|
| 9889 | + break; |
---|
| 9890 | + case QUIRK_AE7: |
---|
| 9891 | + spec->mixers[0] = desktop_mixer; |
---|
| 9892 | + snd_hda_codec_set_name(codec, "Sound Blaster AE-7"); |
---|
| 9893 | + break; |
---|
7643 | 9894 | default: |
---|
7644 | 9895 | spec->mixers[0] = ca0132_mixer; |
---|
7645 | 9896 | break; |
---|
7646 | 9897 | } |
---|
7647 | 9898 | |
---|
7648 | 9899 | /* Setup whether or not to use alt functions/controls/pci_mmio */ |
---|
7649 | | - switch (spec->quirk) { |
---|
| 9900 | + switch (ca0132_quirk(spec)) { |
---|
7650 | 9901 | case QUIRK_SBZ: |
---|
7651 | 9902 | case QUIRK_R3D: |
---|
| 9903 | + case QUIRK_AE5: |
---|
| 9904 | + case QUIRK_AE7: |
---|
| 9905 | + case QUIRK_ZXR: |
---|
7652 | 9906 | spec->use_alt_controls = true; |
---|
7653 | 9907 | spec->use_alt_functions = true; |
---|
7654 | 9908 | spec->use_pci_mmio = true; |
---|
.. | .. |
---|
7665 | 9919 | break; |
---|
7666 | 9920 | } |
---|
7667 | 9921 | |
---|
| 9922 | +#ifdef CONFIG_PCI |
---|
7668 | 9923 | if (spec->use_pci_mmio) { |
---|
7669 | 9924 | spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20); |
---|
7670 | 9925 | if (spec->mem_base == NULL) { |
---|
.. | .. |
---|
7672 | 9927 | spec->quirk = QUIRK_NONE; |
---|
7673 | 9928 | } |
---|
7674 | 9929 | } |
---|
| 9930 | +#endif |
---|
7675 | 9931 | |
---|
7676 | 9932 | spec->base_init_verbs = ca0132_base_init_verbs; |
---|
7677 | 9933 | spec->base_exit_verbs = ca0132_base_exit_verbs; |
---|
.. | .. |
---|
7700 | 9956 | /* |
---|
7701 | 9957 | * patch entries |
---|
7702 | 9958 | */ |
---|
7703 | | -static struct hda_device_id snd_hda_id_ca0132[] = { |
---|
| 9959 | +static const struct hda_device_id snd_hda_id_ca0132[] = { |
---|
7704 | 9960 | HDA_CODEC_ENTRY(0x11020011, "CA0132", patch_ca0132), |
---|
7705 | 9961 | {} /* terminator */ |
---|
7706 | 9962 | }; |
---|