Merge branches 'for-32/i2c/omap-v4', 'for-32/i2c/imx-dt', 'for-32/i2c/eg20t-v4',...
[pandora-kernel.git] / sound / pci / hda / alc680_quirks.c
1 /*
2  * ALC680 quirk models
3  * included by patch_realtek.c
4  */
5
6 /* ALC680 models */
7 enum {
8         ALC680_AUTO,
9         ALC680_BASE,
10         ALC680_MODEL_LAST,
11 };
12
13 #define ALC680_DIGIN_NID        ALC880_DIGIN_NID
14 #define ALC680_DIGOUT_NID       ALC880_DIGOUT_NID
15 #define alc680_modes            alc260_modes
16
17 static const hda_nid_t alc680_dac_nids[3] = {
18         /* Lout1, Lout2, hp */
19         0x02, 0x03, 0x04
20 };
21
22 static const hda_nid_t alc680_adc_nids[3] = {
23         /* ADC0-2 */
24         /* DMIC, MIC, Line-in*/
25         0x07, 0x08, 0x09
26 };
27
28 /*
29  * Analog capture ADC cgange
30  */
31 static hda_nid_t alc680_get_cur_adc(struct hda_codec *codec)
32 {
33         static hda_nid_t pins[] = {0x18, 0x19};
34         static hda_nid_t adcs[] = {0x08, 0x09};
35         int i;
36
37         for (i = 0; i < ARRAY_SIZE(pins); i++) {
38                 if (!is_jack_detectable(codec, pins[i]))
39                         continue;
40                 if (snd_hda_jack_detect(codec, pins[i]))
41                         return adcs[i];
42         }
43         return 0x07;
44 }
45
46 static void alc680_rec_autoswitch(struct hda_codec *codec)
47 {
48         struct alc_spec *spec = codec->spec;
49         hda_nid_t nid = alc680_get_cur_adc(codec);
50         if (spec->cur_adc && nid != spec->cur_adc) {
51                 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
52                 spec->cur_adc = nid;
53                 snd_hda_codec_setup_stream(codec, nid,
54                                            spec->cur_adc_stream_tag, 0,
55                                            spec->cur_adc_format);
56         }
57 }
58
59 static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
60                                       struct hda_codec *codec,
61                                       unsigned int stream_tag,
62                                       unsigned int format,
63                                       struct snd_pcm_substream *substream)
64 {
65         struct alc_spec *spec = codec->spec;
66         hda_nid_t nid = alc680_get_cur_adc(codec);
67
68         spec->cur_adc = nid;
69         spec->cur_adc_stream_tag = stream_tag;
70         spec->cur_adc_format = format;
71         snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
72         return 0;
73 }
74
75 static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
76                                       struct hda_codec *codec,
77                                       struct snd_pcm_substream *substream)
78 {
79         struct alc_spec *spec = codec->spec;
80         snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
81         spec->cur_adc = 0;
82         return 0;
83 }
84
85 static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
86         .substreams = 1, /* can be overridden */
87         .channels_min = 2,
88         .channels_max = 2,
89         /* NID is set in alc_build_pcms */
90         .ops = {
91                 .prepare = alc680_capture_pcm_prepare,
92                 .cleanup = alc680_capture_pcm_cleanup
93         },
94 };
95
96 static const struct snd_kcontrol_new alc680_base_mixer[] = {
97         /* output mixer control */
98         HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
99         HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
100         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
101         HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
102         HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT),
103         HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
104         HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT),
105         { }
106 };
107
108 static const struct hda_bind_ctls alc680_bind_cap_vol = {
109         .ops = &snd_hda_bind_vol,
110         .values = {
111                 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
112                 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
113                 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
114                 0
115         },
116 };
117
118 static const struct hda_bind_ctls alc680_bind_cap_switch = {
119         .ops = &snd_hda_bind_sw,
120         .values = {
121                 HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
122                 HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
123                 HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
124                 0
125         },
126 };
127
128 static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
129         HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
130         HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
131         { } /* end */
132 };
133
134 /*
135  * generic initialization of ADC, input mixers and output mixers
136  */
137 static const struct hda_verb alc680_init_verbs[] = {
138         {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
139         {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
140         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
141
142         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
143         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
144         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
145         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
146         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
147         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
148
149         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
150         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
151         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
152         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
153         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
154
155         {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT   | AC_USRSP_EN},
156         {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT  | AC_USRSP_EN},
157         {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT  | AC_USRSP_EN},
158
159         { }
160 };
161
162 /* toggle speaker-output according to the hp-jack state */
163 static void alc680_base_setup(struct hda_codec *codec)
164 {
165         struct alc_spec *spec = codec->spec;
166
167         spec->autocfg.hp_pins[0] = 0x16;
168         spec->autocfg.speaker_pins[0] = 0x14;
169         spec->autocfg.speaker_pins[1] = 0x15;
170         spec->autocfg.num_inputs = 2;
171         spec->autocfg.inputs[0].pin = 0x18;
172         spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
173         spec->autocfg.inputs[1].pin = 0x19;
174         spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
175         spec->automute = 1;
176         spec->automute_mode = ALC_AUTOMUTE_AMP;
177 }
178
179 static void alc680_unsol_event(struct hda_codec *codec,
180                                            unsigned int res)
181 {
182         if ((res >> 26) == ALC_HP_EVENT)
183                 alc_hp_automute(codec);
184         if ((res >> 26) == ALC_MIC_EVENT)
185                 alc680_rec_autoswitch(codec);
186 }
187
188 static void alc680_inithook(struct hda_codec *codec)
189 {
190         alc_hp_automute(codec);
191         alc680_rec_autoswitch(codec);
192 }
193
194 /*
195  * configuration and preset
196  */
197 static const char * const alc680_models[ALC680_MODEL_LAST] = {
198         [ALC680_BASE]           = "base",
199         [ALC680_AUTO]           = "auto",
200 };
201
202 static const struct snd_pci_quirk alc680_cfg_tbl[] = {
203         SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
204         {}
205 };
206
207 static const struct alc_config_preset alc680_presets[] = {
208         [ALC680_BASE] = {
209                 .mixers = { alc680_base_mixer },
210                 .cap_mixer =  alc680_master_capture_mixer,
211                 .init_verbs = { alc680_init_verbs },
212                 .num_dacs = ARRAY_SIZE(alc680_dac_nids),
213                 .dac_nids = alc680_dac_nids,
214                 .dig_out_nid = ALC680_DIGOUT_NID,
215                 .num_channel_mode = ARRAY_SIZE(alc680_modes),
216                 .channel_mode = alc680_modes,
217                 .unsol_event = alc680_unsol_event,
218                 .setup = alc680_base_setup,
219                 .init_hook = alc680_inithook,
220
221         },
222 };