aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_cirrus.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-07-06 07:00:57 -0400
committerTakashi Iwai <tiwai@suse.de>2009-07-06 07:02:44 -0400
commit40c20fa05a29766565f56ede17d0ffa539e1c9a9 (patch)
treee990bb08e0671f7e49eb2e0cf55a56ee4b992dfe /sound/pci/hda/patch_cirrus.c
parentea35929b886975a240660b3ba6c61826761731ad (diff)
ALSA: hda - Add CS420x-specific coef setup
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_cirrus.c')
-rw-r--r--sound/pci/hda/patch_cirrus.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 8e33214abeb4..2187383cdfd6 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -58,6 +58,64 @@ struct cs_spec {
58 unsigned int mic_detect:1; 58 unsigned int mic_detect:1;
59}; 59};
60 60
61/* Vendor-specific processing widget */
62#define CS420X_VENDOR_NID 0x11
63#define CS_DIG_OUT1_PIN_NID 0x10
64#define CS_DIG_OUT2_PIN_NID 0x15
65#define CS_DMIC1_PIN_NID 0x12
66#define CS_DMIC2_PIN_NID 0x0e
67
68/* coef indices */
69#define IDX_SPDIF_STAT 0x0000
70#define IDX_SPDIF_CTL 0x0001
71#define IDX_ADC_CFG 0x0002
72/* SZC bitmask, 4 modes below:
73 * 0 = immediate,
74 * 1 = digital immediate, analog zero-cross
75 * 2 = digtail & analog soft-ramp
76 * 3 = digital soft-ramp, analog zero-cross
77 */
78#define CS_COEF_ADC_SZC_MASK (3 << 0)
79#define CS_COEF_ADC_MIC_SZC_MODE (3 << 0) /* SZC setup for mic */
80#define CS_COEF_ADC_LI_SZC_MODE (3 << 0) /* SZC setup for line-in */
81/* PGA mode: 0 = differential, 1 = signle-ended */
82#define CS_COEF_ADC_MIC_PGA_MODE (1 << 5) /* PGA setup for mic */
83#define CS_COEF_ADC_LI_PGA_MODE (1 << 6) /* PGA setup for line-in */
84#define IDX_DAC_CFG 0x0003
85/* SZC bitmask, 4 modes below:
86 * 0 = Immediate
87 * 1 = zero-cross
88 * 2 = soft-ramp
89 * 3 = soft-ramp on zero-cross
90 */
91#define CS_COEF_DAC_HP_SZC_MODE (3 << 0) /* nid 0x02 */
92#define CS_COEF_DAC_LO_SZC_MODE (3 << 2) /* nid 0x03 */
93#define CS_COEF_DAC_SPK_SZC_MODE (3 << 4) /* nid 0x04 */
94
95#define IDX_BEEP_CFG 0x0004
96/* 0x0008 - test reg key */
97/* 0x0009 - 0x0014 -> 12 test regs */
98/* 0x0015 - visibility reg */
99
100
101static int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
102{
103 snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
104 AC_VERB_SET_COEF_INDEX, idx);
105 return snd_hda_codec_read(codec, CS420X_VENDOR_NID, 0,
106 AC_VERB_GET_PROC_COEF, 0);
107}
108
109static void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
110 unsigned int coef)
111{
112 snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
113 AC_VERB_SET_COEF_INDEX, idx);
114 snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
115 AC_VERB_SET_PROC_COEF, coef);
116}
117
118
61#define HP_EVENT 1 119#define HP_EVENT 1
62#define MIC_EVENT 2 120#define MIC_EVENT 2
63 121
@@ -295,6 +353,14 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
295 return 0; 353 return 0;
296} 354}
297 355
356static int is_active_pin(struct hda_codec *codec, hda_nid_t nid)
357{
358 struct cs_spec *spec = codec->spec;
359 unsigned int val;
360 val = snd_hda_codec_get_pincfg(codec, nid);
361 return (get_defcfg_connect(val) != AC_JACK_PORT_NONE);
362}
363
298static int parse_output(struct hda_codec *codec) 364static int parse_output(struct hda_codec *codec)
299{ 365{
300 struct cs_spec *spec = codec->spec; 366 struct cs_spec *spec = codec->spec;
@@ -833,6 +899,7 @@ static void init_input(struct hda_codec *codec)
833{ 899{
834 struct cs_spec *spec = codec->spec; 900 struct cs_spec *spec = codec->spec;
835 struct auto_pin_cfg *cfg = &spec->autocfg; 901 struct auto_pin_cfg *cfg = &spec->autocfg;
902 unsigned int coef;
836 int i; 903 int i;
837 904
838 for (i = 0; i < AUTO_PIN_LAST; i++) { 905 for (i = 0; i < AUTO_PIN_LAST; i++) {
@@ -861,14 +928,57 @@ static void init_input(struct hda_codec *codec)
861 change_cur_input(codec, spec->cur_input, 1); 928 change_cur_input(codec, spec->cur_input, 1);
862 if (spec->mic_detect) 929 if (spec->mic_detect)
863 cs_automic(codec); 930 cs_automic(codec);
931
932 coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
933 if (is_active_pin(codec, CS_DMIC2_PIN_NID))
934 coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */
935 if (is_active_pin(codec, CS_DMIC1_PIN_NID))
936 coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0
937 * No effect if SPDIF_OUT2 is slected in
938 * IDX_SPDIF_CTL.
939 */
940 cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
941}
942
943static struct hda_verb cs_coef_init_verbs[] = {
944 {0x11, AC_VERB_SET_PROC_STATE, 1},
945 {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
946 {0x11, AC_VERB_SET_PROC_COEF,
947 (0x002a /* DAC1/2/3 SZCMode Soft Ramp */
948 | 0x0040 /* Mute DACs on FIFO error */
949 | 0x1000 /* Enable DACs High Pass Filter */
950 | 0x0400 /* Disable Coefficient Auto increment */
951 )},
952 /* Beep */
953 {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
954 {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
955
956 {} /* terminator */
957};
958
959/* SPDIF setup */
960static void init_digital(struct hda_codec *codec)
961{
962 unsigned int coef;
963
964 coef = 0x0002; /* SRC_MUTE soft-mute on SPDIF (if no lock) */
965 coef |= 0x0008; /* Replace with mute on error */
966 if (is_active_pin(codec, CS_DIG_OUT2_PIN_NID))
967 coef |= 0x4000; /* RX to TX1 or TX2 Loopthru / SPDIF2
968 * SPDIF_OUT2 is shared with GPIO1 and
969 * DMIC_SDA2.
970 */
971 cs_vendor_coef_set(codec, IDX_SPDIF_CTL, coef);
864} 972}
865 973
866static int cs_init(struct hda_codec *codec) 974static int cs_init(struct hda_codec *codec)
867{ 975{
868 struct cs_spec *spec = codec->spec; 976 struct cs_spec *spec = codec->spec;
869 977
978 snd_hda_sequence_write(codec, cs_coef_init_verbs);
870 init_output(codec); 979 init_output(codec);
871 init_input(codec); 980 init_input(codec);
981 init_digital(codec);
872 return 0; 982 return 0;
873} 983}
874 984