diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 1274 |
1 files changed, 1082 insertions, 192 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f9b2c435a130..caf48edaa921 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -24,7 +24,6 @@ | |||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <sound/driver.h> | ||
28 | #include <linux/init.h> | 27 | #include <linux/init.h> |
29 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
@@ -35,7 +34,8 @@ | |||
35 | #include "hda_local.h" | 34 | #include "hda_local.h" |
36 | 35 | ||
37 | #define NUM_CONTROL_ALLOC 32 | 36 | #define NUM_CONTROL_ALLOC 32 |
38 | #define STAC_HP_EVENT 0x37 | 37 | #define STAC_PWR_EVENT 0x20 |
38 | #define STAC_HP_EVENT 0x30 | ||
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | STAC_REF, | 41 | STAC_REF, |
@@ -62,6 +62,16 @@ enum { | |||
62 | }; | 62 | }; |
63 | 63 | ||
64 | enum { | 64 | enum { |
65 | STAC_92HD73XX_REF, | ||
66 | STAC_92HD73XX_MODELS | ||
67 | }; | ||
68 | |||
69 | enum { | ||
70 | STAC_92HD71BXX_REF, | ||
71 | STAC_92HD71BXX_MODELS | ||
72 | }; | ||
73 | |||
74 | enum { | ||
65 | STAC_925x_REF, | 75 | STAC_925x_REF, |
66 | STAC_M2_2, | 76 | STAC_M2_2, |
67 | STAC_MA6, | 77 | STAC_MA6, |
@@ -97,6 +107,7 @@ enum { | |||
97 | STAC_D965_3ST, | 107 | STAC_D965_3ST, |
98 | STAC_D965_5ST, | 108 | STAC_D965_5ST, |
99 | STAC_DELL_3ST, | 109 | STAC_DELL_3ST, |
110 | STAC_DELL_BIOS, | ||
100 | STAC_927X_MODELS | 111 | STAC_927X_MODELS |
101 | }; | 112 | }; |
102 | 113 | ||
@@ -110,12 +121,24 @@ struct sigmatel_spec { | |||
110 | unsigned int mic_switch: 1; | 121 | unsigned int mic_switch: 1; |
111 | unsigned int alt_switch: 1; | 122 | unsigned int alt_switch: 1; |
112 | unsigned int hp_detect: 1; | 123 | unsigned int hp_detect: 1; |
113 | unsigned int gpio_mute: 1; | ||
114 | unsigned int no_vol_knob :1; | ||
115 | 124 | ||
116 | unsigned int gpio_mask, gpio_data; | 125 | /* gpio lines */ |
126 | unsigned int gpio_mask; | ||
127 | unsigned int gpio_dir; | ||
128 | unsigned int gpio_data; | ||
129 | unsigned int gpio_mute; | ||
130 | |||
131 | /* analog loopback */ | ||
132 | unsigned char aloopback_mask; | ||
133 | unsigned char aloopback_shift; | ||
134 | |||
135 | /* power management */ | ||
136 | unsigned int num_pwrs; | ||
137 | hda_nid_t *pwr_nids; | ||
117 | 138 | ||
118 | /* playback */ | 139 | /* playback */ |
140 | struct hda_input_mux *mono_mux; | ||
141 | unsigned int cur_mmux; | ||
119 | struct hda_multi_out multiout; | 142 | struct hda_multi_out multiout; |
120 | hda_nid_t dac_nids[5]; | 143 | hda_nid_t dac_nids[5]; |
121 | 144 | ||
@@ -126,8 +149,10 @@ struct sigmatel_spec { | |||
126 | unsigned int num_muxes; | 149 | unsigned int num_muxes; |
127 | hda_nid_t *dmic_nids; | 150 | hda_nid_t *dmic_nids; |
128 | unsigned int num_dmics; | 151 | unsigned int num_dmics; |
129 | hda_nid_t dmux_nid; | 152 | hda_nid_t *dmux_nids; |
153 | unsigned int num_dmuxes; | ||
130 | hda_nid_t dig_in_nid; | 154 | hda_nid_t dig_in_nid; |
155 | hda_nid_t mono_nid; | ||
131 | 156 | ||
132 | /* pin widgets */ | 157 | /* pin widgets */ |
133 | hda_nid_t *pin_nids; | 158 | hda_nid_t *pin_nids; |
@@ -141,7 +166,7 @@ struct sigmatel_spec { | |||
141 | 166 | ||
142 | /* capture source */ | 167 | /* capture source */ |
143 | struct hda_input_mux *dinput_mux; | 168 | struct hda_input_mux *dinput_mux; |
144 | unsigned int cur_dmux; | 169 | unsigned int cur_dmux[2]; |
145 | struct hda_input_mux *input_mux; | 170 | struct hda_input_mux *input_mux; |
146 | unsigned int cur_mux[3]; | 171 | unsigned int cur_mux[3]; |
147 | 172 | ||
@@ -158,6 +183,10 @@ struct sigmatel_spec { | |||
158 | struct snd_kcontrol_new *kctl_alloc; | 183 | struct snd_kcontrol_new *kctl_alloc; |
159 | struct hda_input_mux private_dimux; | 184 | struct hda_input_mux private_dimux; |
160 | struct hda_input_mux private_imux; | 185 | struct hda_input_mux private_imux; |
186 | struct hda_input_mux private_mono_mux; | ||
187 | |||
188 | /* virtual master */ | ||
189 | unsigned int vmaster_tlv[4]; | ||
161 | }; | 190 | }; |
162 | 191 | ||
163 | static hda_nid_t stac9200_adc_nids[1] = { | 192 | static hda_nid_t stac9200_adc_nids[1] = { |
@@ -172,6 +201,58 @@ static hda_nid_t stac9200_dac_nids[1] = { | |||
172 | 0x02, | 201 | 0x02, |
173 | }; | 202 | }; |
174 | 203 | ||
204 | static hda_nid_t stac92hd73xx_pwr_nids[8] = { | ||
205 | 0x0a, 0x0b, 0x0c, 0xd, 0x0e, | ||
206 | 0x0f, 0x10, 0x11 | ||
207 | }; | ||
208 | |||
209 | static hda_nid_t stac92hd73xx_adc_nids[2] = { | ||
210 | 0x1a, 0x1b | ||
211 | }; | ||
212 | |||
213 | #define STAC92HD73XX_NUM_DMICS 2 | ||
214 | static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = { | ||
215 | 0x13, 0x14, 0 | ||
216 | }; | ||
217 | |||
218 | #define STAC92HD73_DAC_COUNT 5 | ||
219 | static hda_nid_t stac92hd73xx_dac_nids[STAC92HD73_DAC_COUNT] = { | ||
220 | 0x15, 0x16, 0x17, 0x18, 0x19, | ||
221 | }; | ||
222 | |||
223 | static hda_nid_t stac92hd73xx_mux_nids[4] = { | ||
224 | 0x28, 0x29, 0x2a, 0x2b, | ||
225 | }; | ||
226 | |||
227 | static hda_nid_t stac92hd73xx_dmux_nids[2] = { | ||
228 | 0x20, 0x21, | ||
229 | }; | ||
230 | |||
231 | static hda_nid_t stac92hd71bxx_pwr_nids[3] = { | ||
232 | 0x0a, 0x0d, 0x0f | ||
233 | }; | ||
234 | |||
235 | static hda_nid_t stac92hd71bxx_adc_nids[2] = { | ||
236 | 0x12, 0x13, | ||
237 | }; | ||
238 | |||
239 | static hda_nid_t stac92hd71bxx_mux_nids[2] = { | ||
240 | 0x1a, 0x1b | ||
241 | }; | ||
242 | |||
243 | static hda_nid_t stac92hd71bxx_dmux_nids[1] = { | ||
244 | 0x1c, | ||
245 | }; | ||
246 | |||
247 | static hda_nid_t stac92hd71bxx_dac_nids[2] = { | ||
248 | 0x10, /*0x11, */ | ||
249 | }; | ||
250 | |||
251 | #define STAC92HD71BXX_NUM_DMICS 2 | ||
252 | static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { | ||
253 | 0x18, 0x19, 0 | ||
254 | }; | ||
255 | |||
175 | static hda_nid_t stac925x_adc_nids[1] = { | 256 | static hda_nid_t stac925x_adc_nids[1] = { |
176 | 0x03, | 257 | 0x03, |
177 | }; | 258 | }; |
@@ -189,6 +270,10 @@ static hda_nid_t stac925x_dmic_nids[STAC925X_NUM_DMICS + 1] = { | |||
189 | 0x15, 0 | 270 | 0x15, 0 |
190 | }; | 271 | }; |
191 | 272 | ||
273 | static hda_nid_t stac925x_dmux_nids[1] = { | ||
274 | 0x14, | ||
275 | }; | ||
276 | |||
192 | static hda_nid_t stac922x_adc_nids[2] = { | 277 | static hda_nid_t stac922x_adc_nids[2] = { |
193 | 0x06, 0x07, | 278 | 0x06, 0x07, |
194 | }; | 279 | }; |
@@ -205,6 +290,15 @@ static hda_nid_t stac927x_mux_nids[3] = { | |||
205 | 0x15, 0x16, 0x17 | 290 | 0x15, 0x16, 0x17 |
206 | }; | 291 | }; |
207 | 292 | ||
293 | static hda_nid_t stac927x_dmux_nids[1] = { | ||
294 | 0x1b, | ||
295 | }; | ||
296 | |||
297 | #define STAC927X_NUM_DMICS 2 | ||
298 | static hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = { | ||
299 | 0x13, 0x14, 0 | ||
300 | }; | ||
301 | |||
208 | static hda_nid_t stac9205_adc_nids[2] = { | 302 | static hda_nid_t stac9205_adc_nids[2] = { |
209 | 0x12, 0x13 | 303 | 0x12, 0x13 |
210 | }; | 304 | }; |
@@ -213,6 +307,10 @@ static hda_nid_t stac9205_mux_nids[2] = { | |||
213 | 0x19, 0x1a | 307 | 0x19, 0x1a |
214 | }; | 308 | }; |
215 | 309 | ||
310 | static hda_nid_t stac9205_dmux_nids[1] = { | ||
311 | 0x1d, | ||
312 | }; | ||
313 | |||
216 | #define STAC9205_NUM_DMICS 2 | 314 | #define STAC9205_NUM_DMICS 2 |
217 | static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { | 315 | static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { |
218 | 0x17, 0x18, 0 | 316 | 0x17, 0x18, 0 |
@@ -233,6 +331,17 @@ static hda_nid_t stac922x_pin_nids[10] = { | |||
233 | 0x0f, 0x10, 0x11, 0x15, 0x1b, | 331 | 0x0f, 0x10, 0x11, 0x15, 0x1b, |
234 | }; | 332 | }; |
235 | 333 | ||
334 | static hda_nid_t stac92hd73xx_pin_nids[12] = { | ||
335 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
336 | 0x0f, 0x10, 0x11, 0x12, 0x13, | ||
337 | 0x14, 0x22 | ||
338 | }; | ||
339 | |||
340 | static hda_nid_t stac92hd71bxx_pin_nids[10] = { | ||
341 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
342 | 0x0f, 0x14, 0x18, 0x19, 0x1e, | ||
343 | }; | ||
344 | |||
236 | static hda_nid_t stac927x_pin_nids[14] = { | 345 | static hda_nid_t stac927x_pin_nids[14] = { |
237 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 346 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
238 | 0x0f, 0x10, 0x11, 0x12, 0x13, | 347 | 0x0f, 0x10, 0x11, 0x12, 0x13, |
@@ -258,8 +367,9 @@ static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol, | |||
258 | { | 367 | { |
259 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 368 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
260 | struct sigmatel_spec *spec = codec->spec; | 369 | struct sigmatel_spec *spec = codec->spec; |
370 | unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
261 | 371 | ||
262 | ucontrol->value.enumerated.item[0] = spec->cur_dmux; | 372 | ucontrol->value.enumerated.item[0] = spec->cur_dmux[dmux_idx]; |
263 | return 0; | 373 | return 0; |
264 | } | 374 | } |
265 | 375 | ||
@@ -268,9 +378,10 @@ static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol, | |||
268 | { | 378 | { |
269 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 379 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
270 | struct sigmatel_spec *spec = codec->spec; | 380 | struct sigmatel_spec *spec = codec->spec; |
381 | unsigned int dmux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
271 | 382 | ||
272 | return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol, | 383 | return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol, |
273 | spec->dmux_nid, &spec->cur_dmux); | 384 | spec->dmux_nids[dmux_idx], &spec->cur_dmux[dmux_idx]); |
274 | } | 385 | } |
275 | 386 | ||
276 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 387 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
@@ -300,15 +411,45 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
300 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | 411 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); |
301 | } | 412 | } |
302 | 413 | ||
414 | static int stac92xx_mono_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
415 | struct snd_ctl_elem_info *uinfo) | ||
416 | { | ||
417 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
418 | struct sigmatel_spec *spec = codec->spec; | ||
419 | return snd_hda_input_mux_info(spec->mono_mux, uinfo); | ||
420 | } | ||
421 | |||
422 | static int stac92xx_mono_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
423 | struct snd_ctl_elem_value *ucontrol) | ||
424 | { | ||
425 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
426 | struct sigmatel_spec *spec = codec->spec; | ||
427 | |||
428 | ucontrol->value.enumerated.item[0] = spec->cur_mmux; | ||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static int stac92xx_mono_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
433 | struct snd_ctl_elem_value *ucontrol) | ||
434 | { | ||
435 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
436 | struct sigmatel_spec *spec = codec->spec; | ||
437 | |||
438 | return snd_hda_input_mux_put(codec, spec->mono_mux, ucontrol, | ||
439 | spec->mono_nid, &spec->cur_mmux); | ||
440 | } | ||
441 | |||
303 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info | 442 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info |
304 | 443 | ||
305 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, | 444 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, |
306 | struct snd_ctl_elem_value *ucontrol) | 445 | struct snd_ctl_elem_value *ucontrol) |
307 | { | 446 | { |
308 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 447 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
448 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
309 | struct sigmatel_spec *spec = codec->spec; | 449 | struct sigmatel_spec *spec = codec->spec; |
310 | 450 | ||
311 | ucontrol->value.integer.value[0] = spec->aloopback; | 451 | ucontrol->value.integer.value[0] = !!(spec->aloopback & |
452 | (spec->aloopback_mask << idx)); | ||
312 | return 0; | 453 | return 0; |
313 | } | 454 | } |
314 | 455 | ||
@@ -317,23 +458,33 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, | |||
317 | { | 458 | { |
318 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 459 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
319 | struct sigmatel_spec *spec = codec->spec; | 460 | struct sigmatel_spec *spec = codec->spec; |
461 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
320 | unsigned int dac_mode; | 462 | unsigned int dac_mode; |
463 | unsigned int val, idx_val; | ||
321 | 464 | ||
322 | if (spec->aloopback == ucontrol->value.integer.value[0]) | 465 | idx_val = spec->aloopback_mask << idx; |
466 | if (ucontrol->value.integer.value[0]) | ||
467 | val = spec->aloopback | idx_val; | ||
468 | else | ||
469 | val = spec->aloopback & ~idx_val; | ||
470 | if (spec->aloopback == val) | ||
323 | return 0; | 471 | return 0; |
324 | 472 | ||
325 | spec->aloopback = ucontrol->value.integer.value[0]; | 473 | spec->aloopback = val; |
326 | |||
327 | 474 | ||
475 | /* Only return the bits defined by the shift value of the | ||
476 | * first two bytes of the mask | ||
477 | */ | ||
328 | dac_mode = snd_hda_codec_read(codec, codec->afg, 0, | 478 | dac_mode = snd_hda_codec_read(codec, codec->afg, 0, |
329 | kcontrol->private_value & 0xFFFF, 0x0); | 479 | kcontrol->private_value & 0xFFFF, 0x0); |
480 | dac_mode >>= spec->aloopback_shift; | ||
330 | 481 | ||
331 | if (spec->aloopback) { | 482 | if (spec->aloopback & idx_val) { |
332 | snd_hda_power_up(codec); | 483 | snd_hda_power_up(codec); |
333 | dac_mode |= 0x40; | 484 | dac_mode |= idx_val; |
334 | } else { | 485 | } else { |
335 | snd_hda_power_down(codec); | 486 | snd_hda_power_down(codec); |
336 | dac_mode &= ~0x40; | 487 | dac_mode &= ~idx_val; |
337 | } | 488 | } |
338 | 489 | ||
339 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 490 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
@@ -342,42 +493,6 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, | |||
342 | return 1; | 493 | return 1; |
343 | } | 494 | } |
344 | 495 | ||
345 | static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol, | ||
346 | struct snd_ctl_elem_info *uinfo) | ||
347 | { | ||
348 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
349 | uinfo->count = 1; | ||
350 | uinfo->value.integer.min = 0; | ||
351 | uinfo->value.integer.max = 127; | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol, | ||
356 | struct snd_ctl_elem_value *ucontrol) | ||
357 | { | ||
358 | ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol, | ||
363 | struct snd_ctl_elem_value *ucontrol) | ||
364 | { | ||
365 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
366 | unsigned int val = kcontrol->private_value & 0xff; | ||
367 | |||
368 | if (val == ucontrol->value.integer.value[0]) | ||
369 | return 0; | ||
370 | |||
371 | val = ucontrol->value.integer.value[0]; | ||
372 | kcontrol->private_value &= ~0xff; | ||
373 | kcontrol->private_value |= val; | ||
374 | |||
375 | snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0, | ||
376 | AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80); | ||
377 | return 1; | ||
378 | } | ||
379 | |||
380 | |||
381 | static struct hda_verb stac9200_core_init[] = { | 496 | static struct hda_verb stac9200_core_init[] = { |
382 | /* set dac0mux for dac converter */ | 497 | /* set dac0mux for dac converter */ |
383 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | 498 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -391,6 +506,107 @@ static struct hda_verb stac9200_eapd_init[] = { | |||
391 | {} | 506 | {} |
392 | }; | 507 | }; |
393 | 508 | ||
509 | static struct hda_verb stac92hd73xx_6ch_core_init[] = { | ||
510 | /* set master volume and direct control */ | ||
511 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | ||
512 | /* setup audio connections */ | ||
513 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
514 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
515 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
516 | /* setup adcs to point to mixer */ | ||
517 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | ||
518 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | ||
519 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
520 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
521 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
522 | /* setup import muxs */ | ||
523 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
524 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
525 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
526 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
527 | {} | ||
528 | }; | ||
529 | |||
530 | static struct hda_verb stac92hd73xx_8ch_core_init[] = { | ||
531 | /* set master volume and direct control */ | ||
532 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | ||
533 | /* setup audio connections */ | ||
534 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
535 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
536 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
537 | /* connect hp ports to dac3 */ | ||
538 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
539 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
540 | /* setup adcs to point to mixer */ | ||
541 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | ||
542 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | ||
543 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
544 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
545 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
546 | /* setup import muxs */ | ||
547 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
548 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
549 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
550 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
551 | {} | ||
552 | }; | ||
553 | |||
554 | static struct hda_verb stac92hd73xx_10ch_core_init[] = { | ||
555 | /* set master volume and direct control */ | ||
556 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | ||
557 | /* setup audio connections */ | ||
558 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
559 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
560 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
561 | /* dac3 is connected to import3 mux */ | ||
562 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f}, | ||
563 | /* connect hp ports to dac4 */ | ||
564 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x04}, | ||
565 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x04}, | ||
566 | /* setup adcs to point to mixer */ | ||
567 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | ||
568 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | ||
569 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
570 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
571 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
572 | /* setup import muxs */ | ||
573 | { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
574 | { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
575 | { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
576 | { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
577 | {} | ||
578 | }; | ||
579 | |||
580 | static struct hda_verb stac92hd71bxx_core_init[] = { | ||
581 | /* set master volume and direct control */ | ||
582 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | ||
583 | /* connect headphone jack to dac1 */ | ||
584 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
585 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */ | ||
586 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ | ||
587 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
588 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
589 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
590 | }; | ||
591 | |||
592 | static struct hda_verb stac92hd71bxx_analog_core_init[] = { | ||
593 | /* set master volume and direct control */ | ||
594 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | ||
595 | /* connect headphone jack to dac1 */ | ||
596 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
597 | /* connect ports 0d and 0f to audio mixer */ | ||
598 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
599 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
600 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */ | ||
601 | /* unmute dac0 input in audio mixer */ | ||
602 | { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f}, | ||
603 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ | ||
604 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
605 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
606 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
607 | {} | ||
608 | }; | ||
609 | |||
394 | static struct hda_verb stac925x_core_init[] = { | 610 | static struct hda_verb stac925x_core_init[] = { |
395 | /* set dac0mux for dac converter */ | 611 | /* set dac0mux for dac converter */ |
396 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, | 612 | { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00}, |
@@ -425,6 +641,16 @@ static struct hda_verb stac9205_core_init[] = { | |||
425 | {} | 641 | {} |
426 | }; | 642 | }; |
427 | 643 | ||
644 | #define STAC_MONO_MUX \ | ||
645 | { \ | ||
646 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
647 | .name = "Mono Mux", \ | ||
648 | .count = 1, \ | ||
649 | .info = stac92xx_mono_mux_enum_info, \ | ||
650 | .get = stac92xx_mono_mux_enum_get, \ | ||
651 | .put = stac92xx_mono_mux_enum_put, \ | ||
652 | } | ||
653 | |||
428 | #define STAC_INPUT_SOURCE(cnt) \ | 654 | #define STAC_INPUT_SOURCE(cnt) \ |
429 | { \ | 655 | { \ |
430 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 656 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
@@ -435,29 +661,17 @@ static struct hda_verb stac9205_core_init[] = { | |||
435 | .put = stac92xx_mux_enum_put, \ | 661 | .put = stac92xx_mux_enum_put, \ |
436 | } | 662 | } |
437 | 663 | ||
438 | #define STAC_ANALOG_LOOPBACK(verb_read,verb_write) \ | 664 | #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ |
439 | { \ | 665 | { \ |
440 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 666 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
441 | .name = "Analog Loopback", \ | 667 | .name = "Analog Loopback", \ |
442 | .count = 1, \ | 668 | .count = cnt, \ |
443 | .info = stac92xx_aloopback_info, \ | 669 | .info = stac92xx_aloopback_info, \ |
444 | .get = stac92xx_aloopback_get, \ | 670 | .get = stac92xx_aloopback_get, \ |
445 | .put = stac92xx_aloopback_put, \ | 671 | .put = stac92xx_aloopback_put, \ |
446 | .private_value = verb_read | (verb_write << 16), \ | 672 | .private_value = verb_read | (verb_write << 16), \ |
447 | } | 673 | } |
448 | 674 | ||
449 | #define STAC_VOLKNOB(knob_nid) \ | ||
450 | { \ | ||
451 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
452 | .name = "Master Playback Volume", \ | ||
453 | .count = 1, \ | ||
454 | .info = stac92xx_volknob_info, \ | ||
455 | .get = stac92xx_volknob_get, \ | ||
456 | .put = stac92xx_volknob_put, \ | ||
457 | .private_value = 127 | (knob_nid << 16), \ | ||
458 | } | ||
459 | |||
460 | |||
461 | static struct snd_kcontrol_new stac9200_mixer[] = { | 675 | static struct snd_kcontrol_new stac9200_mixer[] = { |
462 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 676 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
463 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 677 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
@@ -468,6 +682,114 @@ static struct snd_kcontrol_new stac9200_mixer[] = { | |||
468 | { } /* end */ | 682 | { } /* end */ |
469 | }; | 683 | }; |
470 | 684 | ||
685 | static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { | ||
686 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), | ||
687 | |||
688 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | ||
689 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | ||
690 | |||
691 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), | ||
692 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), | ||
693 | |||
694 | HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), | ||
695 | HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), | ||
696 | |||
697 | HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), | ||
698 | HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), | ||
699 | |||
700 | HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), | ||
701 | HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), | ||
702 | |||
703 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | ||
704 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | ||
705 | |||
706 | HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), | ||
707 | HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), | ||
708 | { } /* end */ | ||
709 | }; | ||
710 | |||
711 | static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { | ||
712 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 4), | ||
713 | |||
714 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | ||
715 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | ||
716 | |||
717 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), | ||
718 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), | ||
719 | |||
720 | HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), | ||
721 | HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), | ||
722 | |||
723 | HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), | ||
724 | HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), | ||
725 | |||
726 | HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), | ||
727 | HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), | ||
728 | |||
729 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | ||
730 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | ||
731 | |||
732 | HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), | ||
733 | HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), | ||
734 | { } /* end */ | ||
735 | }; | ||
736 | |||
737 | static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { | ||
738 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 5), | ||
739 | |||
740 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), | ||
741 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), | ||
742 | |||
743 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), | ||
744 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), | ||
745 | |||
746 | HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), | ||
747 | HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), | ||
748 | |||
749 | HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), | ||
750 | HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), | ||
751 | |||
752 | HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), | ||
753 | HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), | ||
754 | |||
755 | HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), | ||
756 | HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), | ||
757 | |||
758 | HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), | ||
759 | HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), | ||
760 | { } /* end */ | ||
761 | }; | ||
762 | |||
763 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | ||
764 | STAC_INPUT_SOURCE(2), | ||
765 | |||
766 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | ||
767 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | ||
768 | HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x0, 0x1a, 0x0, HDA_OUTPUT), | ||
769 | |||
770 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), | ||
771 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), | ||
772 | HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT), | ||
773 | |||
774 | HDA_CODEC_MUTE("Analog Loopback 1", 0x17, 0x3, HDA_INPUT), | ||
775 | HDA_CODEC_MUTE("Analog Loopback 2", 0x17, 0x4, HDA_INPUT), | ||
776 | { } /* end */ | ||
777 | }; | ||
778 | |||
779 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | ||
780 | STAC_INPUT_SOURCE(2), | ||
781 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | ||
782 | |||
783 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | ||
784 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | ||
785 | HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x0, 0x1a, 0x0, HDA_OUTPUT), | ||
786 | |||
787 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), | ||
788 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), | ||
789 | HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT), | ||
790 | { } /* end */ | ||
791 | }; | ||
792 | |||
471 | static struct snd_kcontrol_new stac925x_mixer[] = { | 793 | static struct snd_kcontrol_new stac925x_mixer[] = { |
472 | STAC_INPUT_SOURCE(1), | 794 | STAC_INPUT_SOURCE(1), |
473 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), | 795 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), |
@@ -477,17 +799,8 @@ static struct snd_kcontrol_new stac925x_mixer[] = { | |||
477 | }; | 799 | }; |
478 | 800 | ||
479 | static struct snd_kcontrol_new stac9205_mixer[] = { | 801 | static struct snd_kcontrol_new stac9205_mixer[] = { |
480 | { | ||
481 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
482 | .name = "Digital Input Source", | ||
483 | .count = 1, | ||
484 | .info = stac92xx_dmux_enum_info, | ||
485 | .get = stac92xx_dmux_enum_get, | ||
486 | .put = stac92xx_dmux_enum_put, | ||
487 | }, | ||
488 | STAC_INPUT_SOURCE(2), | 802 | STAC_INPUT_SOURCE(2), |
489 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), | 803 | STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0, 1), |
490 | STAC_VOLKNOB(0x24), | ||
491 | 804 | ||
492 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), | 805 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), |
493 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), | 806 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), |
@@ -503,7 +816,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = { | |||
503 | /* This needs to be generated dynamically based on sequence */ | 816 | /* This needs to be generated dynamically based on sequence */ |
504 | static struct snd_kcontrol_new stac922x_mixer[] = { | 817 | static struct snd_kcontrol_new stac922x_mixer[] = { |
505 | STAC_INPUT_SOURCE(2), | 818 | STAC_INPUT_SOURCE(2), |
506 | STAC_VOLKNOB(0x16), | ||
507 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), | 819 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), |
508 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), | 820 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), |
509 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), | 821 | HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), |
@@ -517,8 +829,7 @@ static struct snd_kcontrol_new stac922x_mixer[] = { | |||
517 | 829 | ||
518 | static struct snd_kcontrol_new stac927x_mixer[] = { | 830 | static struct snd_kcontrol_new stac927x_mixer[] = { |
519 | STAC_INPUT_SOURCE(3), | 831 | STAC_INPUT_SOURCE(3), |
520 | STAC_VOLKNOB(0x24), | 832 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), |
521 | STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), | ||
522 | 833 | ||
523 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), | 834 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), |
524 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), | 835 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), |
@@ -534,6 +845,44 @@ static struct snd_kcontrol_new stac927x_mixer[] = { | |||
534 | { } /* end */ | 845 | { } /* end */ |
535 | }; | 846 | }; |
536 | 847 | ||
848 | static struct snd_kcontrol_new stac_dmux_mixer = { | ||
849 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
850 | .name = "Digital Input Source", | ||
851 | /* count set later */ | ||
852 | .info = stac92xx_dmux_enum_info, | ||
853 | .get = stac92xx_dmux_enum_get, | ||
854 | .put = stac92xx_dmux_enum_put, | ||
855 | }; | ||
856 | |||
857 | static const char *slave_vols[] = { | ||
858 | "Front Playback Volume", | ||
859 | "Surround Playback Volume", | ||
860 | "Center Playback Volume", | ||
861 | "LFE Playback Volume", | ||
862 | "Side Playback Volume", | ||
863 | "Headphone Playback Volume", | ||
864 | "Headphone Playback Volume", | ||
865 | "Speaker Playback Volume", | ||
866 | "External Speaker Playback Volume", | ||
867 | "Speaker2 Playback Volume", | ||
868 | NULL | ||
869 | }; | ||
870 | |||
871 | static const char *slave_sws[] = { | ||
872 | "Front Playback Switch", | ||
873 | "Surround Playback Switch", | ||
874 | "Center Playback Switch", | ||
875 | "LFE Playback Switch", | ||
876 | "Side Playback Switch", | ||
877 | "Headphone Playback Switch", | ||
878 | "Headphone Playback Switch", | ||
879 | "Speaker Playback Switch", | ||
880 | "External Speaker Playback Switch", | ||
881 | "Speaker2 Playback Switch", | ||
882 | "IEC958 Playback Switch", | ||
883 | NULL | ||
884 | }; | ||
885 | |||
537 | static int stac92xx_build_controls(struct hda_codec *codec) | 886 | static int stac92xx_build_controls(struct hda_codec *codec) |
538 | { | 887 | { |
539 | struct sigmatel_spec *spec = codec->spec; | 888 | struct sigmatel_spec *spec = codec->spec; |
@@ -549,6 +898,13 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
549 | if (err < 0) | 898 | if (err < 0) |
550 | return err; | 899 | return err; |
551 | } | 900 | } |
901 | if (spec->num_dmuxes > 0) { | ||
902 | stac_dmux_mixer.count = spec->num_dmuxes; | ||
903 | err = snd_ctl_add(codec->bus->card, | ||
904 | snd_ctl_new1(&stac_dmux_mixer, codec)); | ||
905 | if (err < 0) | ||
906 | return err; | ||
907 | } | ||
552 | 908 | ||
553 | if (spec->multiout.dig_out_nid) { | 909 | if (spec->multiout.dig_out_nid) { |
554 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 910 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); |
@@ -560,6 +916,23 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
560 | if (err < 0) | 916 | if (err < 0) |
561 | return err; | 917 | return err; |
562 | } | 918 | } |
919 | |||
920 | /* if we have no master control, let's create it */ | ||
921 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | ||
922 | snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0], | ||
923 | HDA_OUTPUT, spec->vmaster_tlv); | ||
924 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | ||
925 | spec->vmaster_tlv, slave_vols); | ||
926 | if (err < 0) | ||
927 | return err; | ||
928 | } | ||
929 | if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | ||
930 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | ||
931 | NULL, slave_sws); | ||
932 | if (err < 0) | ||
933 | return err; | ||
934 | } | ||
935 | |||
563 | return 0; | 936 | return 0; |
564 | } | 937 | } |
565 | 938 | ||
@@ -785,7 +1158,7 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { | |||
785 | 1158 | ||
786 | static unsigned int ref925x_pin_configs[8] = { | 1159 | static unsigned int ref925x_pin_configs[8] = { |
787 | 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021, | 1160 | 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021, |
788 | 0x90a70320, 0x02214210, 0x400003f1, 0x9033032e, | 1161 | 0x90a70320, 0x02214210, 0x01019020, 0x9033032e, |
789 | }; | 1162 | }; |
790 | 1163 | ||
791 | static unsigned int stac925x_MA6_pin_configs[8] = { | 1164 | static unsigned int stac925x_MA6_pin_configs[8] = { |
@@ -829,6 +1202,48 @@ static struct snd_pci_quirk stac925x_cfg_tbl[] = { | |||
829 | {} /* terminator */ | 1202 | {} /* terminator */ |
830 | }; | 1203 | }; |
831 | 1204 | ||
1205 | static unsigned int ref92hd73xx_pin_configs[12] = { | ||
1206 | 0x02214030, 0x02a19040, 0x01a19020, 0x02214030, | ||
1207 | 0x0181302e, 0x01014010, 0x01014020, 0x01014030, | ||
1208 | 0x02319040, 0x90a000f0, 0x90a000f0, 0x01452050, | ||
1209 | }; | ||
1210 | |||
1211 | static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | ||
1212 | [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, | ||
1213 | }; | ||
1214 | |||
1215 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { | ||
1216 | [STAC_92HD73XX_REF] = "ref", | ||
1217 | }; | ||
1218 | |||
1219 | static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | ||
1220 | /* SigmaTel reference board */ | ||
1221 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | ||
1222 | "DFI LanParty", STAC_92HD73XX_REF), | ||
1223 | {} /* terminator */ | ||
1224 | }; | ||
1225 | |||
1226 | static unsigned int ref92hd71bxx_pin_configs[10] = { | ||
1227 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, | ||
1228 | 0x0181302e, 0x01114010, 0x01019020, 0x90a000f0, | ||
1229 | 0x90a000f0, 0x01452050, | ||
1230 | }; | ||
1231 | |||
1232 | static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { | ||
1233 | [STAC_92HD71BXX_REF] = ref92hd71bxx_pin_configs, | ||
1234 | }; | ||
1235 | |||
1236 | static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { | ||
1237 | [STAC_92HD71BXX_REF] = "ref", | ||
1238 | }; | ||
1239 | |||
1240 | static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { | ||
1241 | /* SigmaTel reference board */ | ||
1242 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | ||
1243 | "DFI LanParty", STAC_92HD71BXX_REF), | ||
1244 | {} /* terminator */ | ||
1245 | }; | ||
1246 | |||
832 | static unsigned int ref922x_pin_configs[10] = { | 1247 | static unsigned int ref922x_pin_configs[10] = { |
833 | 0x01014010, 0x01016011, 0x01012012, 0x0221401f, | 1248 | 0x01014010, 0x01016011, 0x01012012, 0x0221401f, |
834 | 0x01813122, 0x01011014, 0x01441030, 0x01c41030, | 1249 | 0x01813122, 0x01011014, 0x01441030, 0x01c41030, |
@@ -875,8 +1290,8 @@ static unsigned int dell_922x_m81_pin_configs[10] = { | |||
875 | 102801D7 (Dell XPS M1210) | 1290 | 102801D7 (Dell XPS M1210) |
876 | */ | 1291 | */ |
877 | static unsigned int dell_922x_m82_pin_configs[10] = { | 1292 | static unsigned int dell_922x_m82_pin_configs[10] = { |
878 | 0x0221121f, 0x408103ff, 0x02111212, 0x90100310, | 1293 | 0x02211211, 0x408103ff, 0x02a1123e, 0x90100310, |
879 | 0x408003f1, 0x02111211, 0x03451340, 0x40c003f2, | 1294 | 0x408003f1, 0x0221121f, 0x03451340, 0x40c003f2, |
880 | 0x508003f3, 0x405003f4, | 1295 | 0x508003f3, 0x405003f4, |
881 | }; | 1296 | }; |
882 | 1297 | ||
@@ -1074,22 +1489,24 @@ static unsigned int d965_5st_pin_configs[14] = { | |||
1074 | static unsigned int dell_3st_pin_configs[14] = { | 1489 | static unsigned int dell_3st_pin_configs[14] = { |
1075 | 0x02211230, 0x02a11220, 0x01a19040, 0x01114210, | 1490 | 0x02211230, 0x02a11220, 0x01a19040, 0x01114210, |
1076 | 0x01111212, 0x01116211, 0x01813050, 0x01112214, | 1491 | 0x01111212, 0x01116211, 0x01813050, 0x01112214, |
1077 | 0x403003fa, 0x40000100, 0x40000100, 0x404003fb, | 1492 | 0x403003fa, 0x90a60040, 0x90a60040, 0x404003fb, |
1078 | 0x40c003fc, 0x40000100 | 1493 | 0x40c003fc, 0x40000100 |
1079 | }; | 1494 | }; |
1080 | 1495 | ||
1081 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | 1496 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { |
1082 | [STAC_D965_REF] = ref927x_pin_configs, | 1497 | [STAC_D965_REF] = ref927x_pin_configs, |
1083 | [STAC_D965_3ST] = d965_3st_pin_configs, | 1498 | [STAC_D965_3ST] = d965_3st_pin_configs, |
1084 | [STAC_D965_5ST] = d965_5st_pin_configs, | 1499 | [STAC_D965_5ST] = d965_5st_pin_configs, |
1085 | [STAC_DELL_3ST] = dell_3st_pin_configs, | 1500 | [STAC_DELL_3ST] = dell_3st_pin_configs, |
1501 | [STAC_DELL_BIOS] = NULL, | ||
1086 | }; | 1502 | }; |
1087 | 1503 | ||
1088 | static const char *stac927x_models[STAC_927X_MODELS] = { | 1504 | static const char *stac927x_models[STAC_927X_MODELS] = { |
1089 | [STAC_D965_REF] = "ref", | 1505 | [STAC_D965_REF] = "ref", |
1090 | [STAC_D965_3ST] = "3stack", | 1506 | [STAC_D965_3ST] = "3stack", |
1091 | [STAC_D965_5ST] = "5stack", | 1507 | [STAC_D965_5ST] = "5stack", |
1092 | [STAC_DELL_3ST] = "dell-3stack", | 1508 | [STAC_DELL_3ST] = "dell-3stack", |
1509 | [STAC_DELL_BIOS] = "dell-bios", | ||
1093 | }; | 1510 | }; |
1094 | 1511 | ||
1095 | static struct snd_pci_quirk stac927x_cfg_tbl[] = { | 1512 | static struct snd_pci_quirk stac927x_cfg_tbl[] = { |
@@ -1116,13 +1533,21 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
1116 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), | 1533 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST), |
1117 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), | 1534 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST), |
1118 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), | 1535 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST), |
1119 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_D965_3ST), | ||
1120 | /* Dell 3 stack systems */ | 1536 | /* Dell 3 stack systems */ |
1537 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f7, "Dell XPS M1730", STAC_DELL_3ST), | ||
1121 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), | 1538 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01dd, "Dell Dimension E520", STAC_DELL_3ST), |
1122 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST), | 1539 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ed, "Dell ", STAC_DELL_3ST), |
1123 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST), | 1540 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f4, "Dell ", STAC_DELL_3ST), |
1541 | /* Dell 3 stack systems with verb table in BIOS */ | ||
1542 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS), | ||
1543 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS), | ||
1544 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell ", STAC_DELL_BIOS), | ||
1545 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS), | ||
1546 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS), | ||
1547 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS), | ||
1548 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), | ||
1549 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_DELL_BIOS), | ||
1124 | /* 965 based 5 stack systems */ | 1550 | /* 965 based 5 stack systems */ |
1125 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0209, "Dell XPS 1330", STAC_D965_5ST), | ||
1126 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), | 1551 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST), |
1127 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), | 1552 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST), |
1128 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), | 1553 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST), |
@@ -1137,7 +1562,7 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { | |||
1137 | 1562 | ||
1138 | static unsigned int ref9205_pin_configs[12] = { | 1563 | static unsigned int ref9205_pin_configs[12] = { |
1139 | 0x40000100, 0x40000100, 0x01016011, 0x01014010, | 1564 | 0x40000100, 0x40000100, 0x01016011, 0x01014010, |
1140 | 0x01813122, 0x01a19021, 0x40000100, 0x40000100, | 1565 | 0x01813122, 0x01a19021, 0x01019020, 0x40000100, |
1141 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 | 1566 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 |
1142 | }; | 1567 | }; |
1143 | 1568 | ||
@@ -1149,6 +1574,7 @@ static unsigned int ref9205_pin_configs[12] = { | |||
1149 | 102801FD | 1574 | 102801FD |
1150 | 10280204 | 1575 | 10280204 |
1151 | 1028021F | 1576 | 1028021F |
1577 | 10280228 (Dell Vostro 1500) | ||
1152 | */ | 1578 | */ |
1153 | static unsigned int dell_9205_m42_pin_configs[12] = { | 1579 | static unsigned int dell_9205_m42_pin_configs[12] = { |
1154 | 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310, | 1580 | 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310, |
@@ -1232,6 +1658,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { | |||
1232 | "unknown Dell", STAC_9205_DELL_M42), | 1658 | "unknown Dell", STAC_9205_DELL_M42), |
1233 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, | 1659 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f, |
1234 | "Dell Inspiron", STAC_9205_DELL_M44), | 1660 | "Dell Inspiron", STAC_9205_DELL_M44), |
1661 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, | ||
1662 | "Dell Vostro 1500", STAC_9205_DELL_M42), | ||
1235 | {} /* terminator */ | 1663 | {} /* terminator */ |
1236 | }; | 1664 | }; |
1237 | 1665 | ||
@@ -1297,22 +1725,6 @@ static void stac92xx_set_config_regs(struct hda_codec *codec) | |||
1297 | spec->pin_configs[i]); | 1725 | spec->pin_configs[i]); |
1298 | } | 1726 | } |
1299 | 1727 | ||
1300 | static void stac92xx_enable_gpio_mask(struct hda_codec *codec) | ||
1301 | { | ||
1302 | struct sigmatel_spec *spec = codec->spec; | ||
1303 | /* Configure GPIOx as output */ | ||
1304 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
1305 | AC_VERB_SET_GPIO_DIRECTION, spec->gpio_mask); | ||
1306 | /* Configure GPIOx as CMOS */ | ||
1307 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7e7, 0x00000000); | ||
1308 | /* Assert GPIOx */ | ||
1309 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
1310 | AC_VERB_SET_GPIO_DATA, spec->gpio_data); | ||
1311 | /* Enable GPIOx */ | ||
1312 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
1313 | AC_VERB_SET_GPIO_MASK, spec->gpio_mask); | ||
1314 | } | ||
1315 | |||
1316 | /* | 1728 | /* |
1317 | * Analog playback callbacks | 1729 | * Analog playback callbacks |
1318 | */ | 1730 | */ |
@@ -1531,7 +1943,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1531 | struct sigmatel_spec *spec = codec->spec; | 1943 | struct sigmatel_spec *spec = codec->spec; |
1532 | hda_nid_t nid = kcontrol->private_value >> 8; | 1944 | hda_nid_t nid = kcontrol->private_value >> 8; |
1533 | int io_idx = kcontrol-> private_value & 0xff; | 1945 | int io_idx = kcontrol-> private_value & 0xff; |
1534 | unsigned short val = ucontrol->value.integer.value[0]; | 1946 | unsigned short val = !!ucontrol->value.integer.value[0]; |
1535 | 1947 | ||
1536 | spec->io_switch[io_idx] = val; | 1948 | spec->io_switch[io_idx] = val; |
1537 | 1949 | ||
@@ -1543,6 +1955,13 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
1543 | pinctl |= stac92xx_get_vref(codec, nid); | 1955 | pinctl |= stac92xx_get_vref(codec, nid); |
1544 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 1956 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
1545 | } | 1957 | } |
1958 | |||
1959 | /* check the auto-mute again: we need to mute/unmute the speaker | ||
1960 | * appropriately according to the pin direction | ||
1961 | */ | ||
1962 | if (spec->hp_detect) | ||
1963 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | ||
1964 | |||
1546 | return 1; | 1965 | return 1; |
1547 | } | 1966 | } |
1548 | 1967 | ||
@@ -1564,11 +1983,12 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, | |||
1564 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1983 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1565 | struct sigmatel_spec *spec = codec->spec; | 1984 | struct sigmatel_spec *spec = codec->spec; |
1566 | hda_nid_t nid = kcontrol->private_value & 0xff; | 1985 | hda_nid_t nid = kcontrol->private_value & 0xff; |
1986 | unsigned int val = !!ucontrol->value.integer.value[0]; | ||
1567 | 1987 | ||
1568 | if (spec->clfe_swap == ucontrol->value.integer.value[0]) | 1988 | if (spec->clfe_swap == val) |
1569 | return 0; | 1989 | return 0; |
1570 | 1990 | ||
1571 | spec->clfe_swap = ucontrol->value.integer.value[0]; | 1991 | spec->clfe_swap = val; |
1572 | 1992 | ||
1573 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, | 1993 | snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, |
1574 | spec->clfe_swap ? 0x4 : 0x0); | 1994 | spec->clfe_swap ? 0x4 : 0x0); |
@@ -1599,6 +2019,7 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, | |||
1599 | enum { | 2019 | enum { |
1600 | STAC_CTL_WIDGET_VOL, | 2020 | STAC_CTL_WIDGET_VOL, |
1601 | STAC_CTL_WIDGET_MUTE, | 2021 | STAC_CTL_WIDGET_MUTE, |
2022 | STAC_CTL_WIDGET_MONO_MUX, | ||
1602 | STAC_CTL_WIDGET_IO_SWITCH, | 2023 | STAC_CTL_WIDGET_IO_SWITCH, |
1603 | STAC_CTL_WIDGET_CLFE_SWITCH | 2024 | STAC_CTL_WIDGET_CLFE_SWITCH |
1604 | }; | 2025 | }; |
@@ -1606,6 +2027,7 @@ enum { | |||
1606 | static struct snd_kcontrol_new stac92xx_control_templates[] = { | 2027 | static struct snd_kcontrol_new stac92xx_control_templates[] = { |
1607 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 2028 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), |
1608 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 2029 | HDA_CODEC_MUTE(NULL, 0, 0, 0), |
2030 | STAC_MONO_MUX, | ||
1609 | STAC_CODEC_IO_SWITCH(NULL, 0), | 2031 | STAC_CODEC_IO_SWITCH(NULL, 0), |
1610 | STAC_CODEC_CLFE_SWITCH(NULL, 0), | 2032 | STAC_CODEC_CLFE_SWITCH(NULL, 0), |
1611 | }; | 2033 | }; |
@@ -1650,6 +2072,7 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
1650 | for (i = 0; i < codec->num_nodes; i++) { | 2072 | for (i = 0; i < codec->num_nodes; i++) { |
1651 | wcaps = codec->wcaps[i]; | 2073 | wcaps = codec->wcaps[i]; |
1652 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 2074 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
2075 | |||
1653 | if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) | 2076 | if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) |
1654 | num_dacs++; | 2077 | num_dacs++; |
1655 | } | 2078 | } |
@@ -1737,7 +2160,6 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
1737 | wcaps = snd_hda_param_read(codec, conn[j], | 2160 | wcaps = snd_hda_param_read(codec, conn[j], |
1738 | AC_PAR_AUDIO_WIDGET_CAP); | 2161 | AC_PAR_AUDIO_WIDGET_CAP); |
1739 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 2162 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
1740 | |||
1741 | if (wtype != AC_WID_AUD_OUT || | 2163 | if (wtype != AC_WID_AUD_OUT || |
1742 | (wcaps & AC_WCAP_DIGITAL)) | 2164 | (wcaps & AC_WCAP_DIGITAL)) |
1743 | continue; | 2165 | continue; |
@@ -1811,7 +2233,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
1811 | int i, err; | 2233 | int i, err; |
1812 | 2234 | ||
1813 | struct sigmatel_spec *spec = codec->spec; | 2235 | struct sigmatel_spec *spec = codec->spec; |
1814 | unsigned int wid_caps; | 2236 | unsigned int wid_caps, pincap; |
1815 | 2237 | ||
1816 | 2238 | ||
1817 | for (i = 0; i < cfg->line_outs; i++) { | 2239 | for (i = 0; i < cfg->line_outs; i++) { |
@@ -1847,13 +2269,39 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
1847 | } | 2269 | } |
1848 | } | 2270 | } |
1849 | 2271 | ||
1850 | if (spec->line_switch) | 2272 | if (spec->line_switch) { |
1851 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, "Line In as Output Switch", cfg->input_pins[AUTO_PIN_LINE] << 8)) < 0) | 2273 | nid = cfg->input_pins[AUTO_PIN_LINE]; |
1852 | return err; | 2274 | pincap = snd_hda_param_read(codec, nid, |
2275 | AC_PAR_PIN_CAP); | ||
2276 | if (pincap & AC_PINCAP_OUT) { | ||
2277 | err = stac92xx_add_control(spec, | ||
2278 | STAC_CTL_WIDGET_IO_SWITCH, | ||
2279 | "Line In as Output Switch", nid << 8); | ||
2280 | if (err < 0) | ||
2281 | return err; | ||
2282 | } | ||
2283 | } | ||
1853 | 2284 | ||
1854 | if (spec->mic_switch) | 2285 | if (spec->mic_switch) { |
1855 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, "Mic as Output Switch", (cfg->input_pins[AUTO_PIN_MIC] << 8) | 1)) < 0) | 2286 | unsigned int def_conf; |
1856 | return err; | 2287 | nid = cfg->input_pins[AUTO_PIN_MIC]; |
2288 | def_conf = snd_hda_codec_read(codec, nid, 0, | ||
2289 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
2290 | |||
2291 | /* some laptops have an internal analog microphone | ||
2292 | * which can't be used as a output */ | ||
2293 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | ||
2294 | pincap = snd_hda_param_read(codec, nid, | ||
2295 | AC_PAR_PIN_CAP); | ||
2296 | if (pincap & AC_PINCAP_OUT) { | ||
2297 | err = stac92xx_add_control(spec, | ||
2298 | STAC_CTL_WIDGET_IO_SWITCH, | ||
2299 | "Mic as Output Switch", (nid << 8) | 1); | ||
2300 | if (err < 0) | ||
2301 | return err; | ||
2302 | } | ||
2303 | } | ||
2304 | } | ||
1857 | 2305 | ||
1858 | return 0; | 2306 | return 0; |
1859 | } | 2307 | } |
@@ -1931,8 +2379,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
1931 | } | 2379 | } |
1932 | if (spec->multiout.hp_nid) { | 2380 | if (spec->multiout.hp_nid) { |
1933 | const char *pfx; | 2381 | const char *pfx; |
1934 | if (old_num_dacs == spec->multiout.num_dacs && | 2382 | if (old_num_dacs == spec->multiout.num_dacs) |
1935 | spec->no_vol_knob) | ||
1936 | pfx = "Master"; | 2383 | pfx = "Master"; |
1937 | else | 2384 | else |
1938 | pfx = "Headphone"; | 2385 | pfx = "Headphone"; |
@@ -1944,6 +2391,37 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
1944 | return 0; | 2391 | return 0; |
1945 | } | 2392 | } |
1946 | 2393 | ||
2394 | /* labels for mono mux outputs */ | ||
2395 | static const char *stac92xx_mono_labels[3] = { | ||
2396 | "DAC0", "DAC1", "Mixer" | ||
2397 | }; | ||
2398 | |||
2399 | /* create mono mux for mono out on capable codecs */ | ||
2400 | static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) | ||
2401 | { | ||
2402 | struct sigmatel_spec *spec = codec->spec; | ||
2403 | struct hda_input_mux *mono_mux = &spec->private_mono_mux; | ||
2404 | int i, num_cons; | ||
2405 | hda_nid_t con_lst[ARRAY_SIZE(stac92xx_mono_labels)]; | ||
2406 | |||
2407 | num_cons = snd_hda_get_connections(codec, | ||
2408 | spec->mono_nid, | ||
2409 | con_lst, | ||
2410 | HDA_MAX_NUM_INPUTS); | ||
2411 | if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) | ||
2412 | return -EINVAL; | ||
2413 | |||
2414 | for (i = 0; i < num_cons; i++) { | ||
2415 | mono_mux->items[mono_mux->num_items].label = | ||
2416 | stac92xx_mono_labels[i]; | ||
2417 | mono_mux->items[mono_mux->num_items].index = i; | ||
2418 | mono_mux->num_items++; | ||
2419 | } | ||
2420 | |||
2421 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, | ||
2422 | "Mono Mux", spec->mono_nid); | ||
2423 | } | ||
2424 | |||
1947 | /* labels for dmic mux inputs */ | 2425 | /* labels for dmic mux inputs */ |
1948 | static const char *stac92xx_dmic_labels[5] = { | 2426 | static const char *stac92xx_dmic_labels[5] = { |
1949 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", | 2427 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", |
@@ -1957,15 +2435,18 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
1957 | struct sigmatel_spec *spec = codec->spec; | 2435 | struct sigmatel_spec *spec = codec->spec; |
1958 | struct hda_input_mux *dimux = &spec->private_dimux; | 2436 | struct hda_input_mux *dimux = &spec->private_dimux; |
1959 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | 2437 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; |
1960 | int i, j; | 2438 | int err, i, j; |
2439 | char name[32]; | ||
1961 | 2440 | ||
1962 | dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; | 2441 | dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; |
1963 | dimux->items[dimux->num_items].index = 0; | 2442 | dimux->items[dimux->num_items].index = 0; |
1964 | dimux->num_items++; | 2443 | dimux->num_items++; |
1965 | 2444 | ||
1966 | for (i = 0; i < spec->num_dmics; i++) { | 2445 | for (i = 0; i < spec->num_dmics; i++) { |
2446 | hda_nid_t nid; | ||
1967 | int index; | 2447 | int index; |
1968 | int num_cons; | 2448 | int num_cons; |
2449 | unsigned int wcaps; | ||
1969 | unsigned int def_conf; | 2450 | unsigned int def_conf; |
1970 | 2451 | ||
1971 | def_conf = snd_hda_codec_read(codec, | 2452 | def_conf = snd_hda_codec_read(codec, |
@@ -1976,17 +2457,32 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
1976 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | 2457 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) |
1977 | continue; | 2458 | continue; |
1978 | 2459 | ||
2460 | nid = spec->dmic_nids[i]; | ||
1979 | num_cons = snd_hda_get_connections(codec, | 2461 | num_cons = snd_hda_get_connections(codec, |
1980 | spec->dmux_nid, | 2462 | spec->dmux_nids[0], |
1981 | con_lst, | 2463 | con_lst, |
1982 | HDA_MAX_NUM_INPUTS); | 2464 | HDA_MAX_NUM_INPUTS); |
1983 | for (j = 0; j < num_cons; j++) | 2465 | for (j = 0; j < num_cons; j++) |
1984 | if (con_lst[j] == spec->dmic_nids[i]) { | 2466 | if (con_lst[j] == nid) { |
1985 | index = j; | 2467 | index = j; |
1986 | goto found; | 2468 | goto found; |
1987 | } | 2469 | } |
1988 | continue; | 2470 | continue; |
1989 | found: | 2471 | found: |
2472 | wcaps = get_wcaps(codec, nid); | ||
2473 | |||
2474 | if (wcaps & AC_WCAP_OUT_AMP) { | ||
2475 | sprintf(name, "%s Capture Volume", | ||
2476 | stac92xx_dmic_labels[dimux->num_items]); | ||
2477 | |||
2478 | err = stac92xx_add_control(spec, | ||
2479 | STAC_CTL_WIDGET_VOL, | ||
2480 | name, | ||
2481 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | ||
2482 | if (err < 0) | ||
2483 | return err; | ||
2484 | } | ||
2485 | |||
1990 | dimux->items[dimux->num_items].label = | 2486 | dimux->items[dimux->num_items].label = |
1991 | stac92xx_dmic_labels[dimux->num_items]; | 2487 | stac92xx_dmic_labels[dimux->num_items]; |
1992 | dimux->items[dimux->num_items].index = index; | 2488 | dimux->items[dimux->num_items].index = index; |
@@ -2079,6 +2575,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
2079 | { | 2575 | { |
2080 | struct sigmatel_spec *spec = codec->spec; | 2576 | struct sigmatel_spec *spec = codec->spec; |
2081 | int err; | 2577 | int err; |
2578 | int hp_speaker_swap = 0; | ||
2082 | 2579 | ||
2083 | if ((err = snd_hda_parse_pin_def_config(codec, | 2580 | if ((err = snd_hda_parse_pin_def_config(codec, |
2084 | &spec->autocfg, | 2581 | &spec->autocfg, |
@@ -2087,6 +2584,68 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
2087 | if (! spec->autocfg.line_outs) | 2584 | if (! spec->autocfg.line_outs) |
2088 | return 0; /* can't find valid pin config */ | 2585 | return 0; /* can't find valid pin config */ |
2089 | 2586 | ||
2587 | /* If we have no real line-out pin and multiple hp-outs, HPs should | ||
2588 | * be set up as multi-channel outputs. | ||
2589 | */ | ||
2590 | if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && | ||
2591 | spec->autocfg.hp_outs > 1) { | ||
2592 | /* Copy hp_outs to line_outs, backup line_outs in | ||
2593 | * speaker_outs so that the following routines can handle | ||
2594 | * HP pins as primary outputs. | ||
2595 | */ | ||
2596 | memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins, | ||
2597 | sizeof(spec->autocfg.line_out_pins)); | ||
2598 | spec->autocfg.speaker_outs = spec->autocfg.line_outs; | ||
2599 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins, | ||
2600 | sizeof(spec->autocfg.hp_pins)); | ||
2601 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | ||
2602 | hp_speaker_swap = 1; | ||
2603 | } | ||
2604 | if (spec->autocfg.mono_out_pin) { | ||
2605 | int dir = (get_wcaps(codec, spec->autocfg.mono_out_pin) | ||
2606 | & AC_WCAP_OUT_AMP) ? HDA_OUTPUT : HDA_INPUT; | ||
2607 | u32 caps = query_amp_caps(codec, | ||
2608 | spec->autocfg.mono_out_pin, dir); | ||
2609 | hda_nid_t conn_list[1]; | ||
2610 | |||
2611 | /* get the mixer node and then the mono mux if it exists */ | ||
2612 | if (snd_hda_get_connections(codec, | ||
2613 | spec->autocfg.mono_out_pin, conn_list, 1) && | ||
2614 | snd_hda_get_connections(codec, conn_list[0], | ||
2615 | conn_list, 1)) { | ||
2616 | |||
2617 | int wcaps = get_wcaps(codec, conn_list[0]); | ||
2618 | int wid_type = (wcaps & AC_WCAP_TYPE) | ||
2619 | >> AC_WCAP_TYPE_SHIFT; | ||
2620 | /* LR swap check, some stac925x have a mux that | ||
2621 | * changes the DACs output path instead of the | ||
2622 | * mono-mux path. | ||
2623 | */ | ||
2624 | if (wid_type == AC_WID_AUD_SEL && | ||
2625 | !(wcaps & AC_WCAP_LR_SWAP)) | ||
2626 | spec->mono_nid = conn_list[0]; | ||
2627 | } | ||
2628 | /* all mono outs have a least a mute/unmute switch */ | ||
2629 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, | ||
2630 | "Mono Playback Switch", | ||
2631 | HDA_COMPOSE_AMP_VAL(spec->autocfg.mono_out_pin, | ||
2632 | 1, 0, dir)); | ||
2633 | if (err < 0) | ||
2634 | return err; | ||
2635 | /* check to see if there is volume support for the amp */ | ||
2636 | if ((caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT) { | ||
2637 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, | ||
2638 | "Mono Playback Volume", | ||
2639 | HDA_COMPOSE_AMP_VAL(spec->autocfg.mono_out_pin, | ||
2640 | 1, 0, dir)); | ||
2641 | if (err < 0) | ||
2642 | return err; | ||
2643 | } | ||
2644 | |||
2645 | stac92xx_auto_set_pinctl(codec, spec->autocfg.mono_out_pin, | ||
2646 | AC_PINCTL_OUT_EN); | ||
2647 | } | ||
2648 | |||
2090 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) | 2649 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) |
2091 | return err; | 2650 | return err; |
2092 | if (spec->multiout.num_dacs == 0) | 2651 | if (spec->multiout.num_dacs == 0) |
@@ -2098,6 +2657,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
2098 | if (err < 0) | 2657 | if (err < 0) |
2099 | return err; | 2658 | return err; |
2100 | 2659 | ||
2660 | if (hp_speaker_swap == 1) { | ||
2661 | /* Restore the hp_outs and line_outs */ | ||
2662 | memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | ||
2663 | sizeof(spec->autocfg.line_out_pins)); | ||
2664 | spec->autocfg.hp_outs = spec->autocfg.line_outs; | ||
2665 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.speaker_pins, | ||
2666 | sizeof(spec->autocfg.speaker_pins)); | ||
2667 | spec->autocfg.line_outs = spec->autocfg.speaker_outs; | ||
2668 | memset(spec->autocfg.speaker_pins, 0, | ||
2669 | sizeof(spec->autocfg.speaker_pins)); | ||
2670 | spec->autocfg.speaker_outs = 0; | ||
2671 | } | ||
2672 | |||
2101 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | 2673 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); |
2102 | 2674 | ||
2103 | if (err < 0) | 2675 | if (err < 0) |
@@ -2108,6 +2680,12 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
2108 | if (err < 0) | 2680 | if (err < 0) |
2109 | return err; | 2681 | return err; |
2110 | 2682 | ||
2683 | if (spec->mono_nid > 0) { | ||
2684 | err = stac92xx_auto_create_mono_output_ctls(codec); | ||
2685 | if (err < 0) | ||
2686 | return err; | ||
2687 | } | ||
2688 | |||
2111 | if (spec->num_dmics > 0) | 2689 | if (spec->num_dmics > 0) |
2112 | if ((err = stac92xx_auto_create_dmic_input_ctls(codec, | 2690 | if ((err = stac92xx_auto_create_dmic_input_ctls(codec, |
2113 | &spec->autocfg)) < 0) | 2691 | &spec->autocfg)) < 0) |
@@ -2126,7 +2704,9 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
2126 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 2704 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
2127 | 2705 | ||
2128 | spec->input_mux = &spec->private_imux; | 2706 | spec->input_mux = &spec->private_imux; |
2129 | spec->dinput_mux = &spec->private_dimux; | 2707 | if (!spec->dinput_mux) |
2708 | spec->dinput_mux = &spec->private_dimux; | ||
2709 | spec->mono_mux = &spec->private_mono_mux; | ||
2130 | 2710 | ||
2131 | return 1; | 2711 | return 1; |
2132 | } | 2712 | } |
@@ -2236,38 +2816,35 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
2236 | * funky external mute control using GPIO pins. | 2816 | * funky external mute control using GPIO pins. |
2237 | */ | 2817 | */ |
2238 | 2818 | ||
2239 | static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) | 2819 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, |
2820 | unsigned int dir_mask, unsigned int data) | ||
2240 | { | 2821 | { |
2241 | unsigned int gpiostate, gpiomask, gpiodir; | 2822 | unsigned int gpiostate, gpiomask, gpiodir; |
2242 | 2823 | ||
2243 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, | 2824 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, |
2244 | AC_VERB_GET_GPIO_DATA, 0); | 2825 | AC_VERB_GET_GPIO_DATA, 0); |
2245 | 2826 | gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); | |
2246 | if (!muted) | ||
2247 | gpiostate |= (1 << pin); | ||
2248 | else | ||
2249 | gpiostate &= ~(1 << pin); | ||
2250 | 2827 | ||
2251 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, | 2828 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, |
2252 | AC_VERB_GET_GPIO_MASK, 0); | 2829 | AC_VERB_GET_GPIO_MASK, 0); |
2253 | gpiomask |= (1 << pin); | 2830 | gpiomask |= mask; |
2254 | 2831 | ||
2255 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, | 2832 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, |
2256 | AC_VERB_GET_GPIO_DIRECTION, 0); | 2833 | AC_VERB_GET_GPIO_DIRECTION, 0); |
2257 | gpiodir |= (1 << pin); | 2834 | gpiodir |= dir_mask; |
2258 | 2835 | ||
2259 | /* AppleHDA seems to do this -- WTF is this verb?? */ | 2836 | /* Configure GPIOx as CMOS */ |
2260 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); | 2837 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); |
2261 | 2838 | ||
2262 | snd_hda_codec_write(codec, codec->afg, 0, | 2839 | snd_hda_codec_write(codec, codec->afg, 0, |
2263 | AC_VERB_SET_GPIO_MASK, gpiomask); | 2840 | AC_VERB_SET_GPIO_MASK, gpiomask); |
2264 | snd_hda_codec_write(codec, codec->afg, 0, | 2841 | snd_hda_codec_read(codec, codec->afg, 0, |
2265 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); | 2842 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */ |
2266 | 2843 | ||
2267 | msleep(1); | 2844 | msleep(1); |
2268 | 2845 | ||
2269 | snd_hda_codec_write(codec, codec->afg, 0, | 2846 | snd_hda_codec_read(codec, codec->afg, 0, |
2270 | AC_VERB_SET_GPIO_DATA, gpiostate); | 2847 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
2271 | } | 2848 | } |
2272 | 2849 | ||
2273 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 2850 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, |
@@ -2279,6 +2856,16 @@ static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | |||
2279 | (AC_USRSP_EN | event)); | 2856 | (AC_USRSP_EN | event)); |
2280 | } | 2857 | } |
2281 | 2858 | ||
2859 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | ||
2860 | { | ||
2861 | int i; | ||
2862 | for (i = 0; i < cfg->hp_outs; i++) | ||
2863 | if (cfg->hp_pins[i] == nid) | ||
2864 | return 1; /* nid is a HP-Out */ | ||
2865 | |||
2866 | return 0; /* nid is not a HP-Out */ | ||
2867 | }; | ||
2868 | |||
2282 | static int stac92xx_init(struct hda_codec *codec) | 2869 | static int stac92xx_init(struct hda_codec *codec) |
2283 | { | 2870 | { |
2284 | struct sigmatel_spec *spec = codec->spec; | 2871 | struct sigmatel_spec *spec = codec->spec; |
@@ -2314,10 +2901,23 @@ static int stac92xx_init(struct hda_codec *codec) | |||
2314 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 2901 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
2315 | } | 2902 | } |
2316 | } | 2903 | } |
2317 | if (spec->num_dmics > 0) | 2904 | for (i = 0; i < spec->num_dmics; i++) |
2318 | for (i = 0; i < spec->num_dmics; i++) | 2905 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], |
2319 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | 2906 | AC_PINCTL_IN_EN); |
2320 | AC_PINCTL_IN_EN); | 2907 | for (i = 0; i < spec->num_pwrs; i++) { |
2908 | int event = is_nid_hp_pin(cfg, spec->pwr_nids[i]) | ||
2909 | ? STAC_HP_EVENT : STAC_PWR_EVENT; | ||
2910 | int pinctl = snd_hda_codec_read(codec, spec->pwr_nids[i], | ||
2911 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
2912 | /* outputs are only ports capable of power management | ||
2913 | * any attempts on powering down a input port cause the | ||
2914 | * referenced VREF to act quirky. | ||
2915 | */ | ||
2916 | if (pinctl & AC_PINCTL_IN_EN) | ||
2917 | continue; | ||
2918 | enable_pin_detect(codec, spec->pwr_nids[i], event | i); | ||
2919 | codec->patch_ops.unsol_event(codec, (event | i) << 26); | ||
2920 | } | ||
2321 | 2921 | ||
2322 | if (cfg->dig_out_pin) | 2922 | if (cfg->dig_out_pin) |
2323 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | 2923 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, |
@@ -2326,10 +2926,8 @@ static int stac92xx_init(struct hda_codec *codec) | |||
2326 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | 2926 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, |
2327 | AC_PINCTL_IN_EN); | 2927 | AC_PINCTL_IN_EN); |
2328 | 2928 | ||
2329 | if (spec->gpio_mute) { | 2929 | stac_gpio_set(codec, spec->gpio_mask, |
2330 | stac922x_gpio_mute(codec, 0, 0); | 2930 | spec->gpio_dir, spec->gpio_data); |
2331 | stac922x_gpio_mute(codec, 1, 0); | ||
2332 | } | ||
2333 | 2931 | ||
2334 | return 0; | 2932 | return 0; |
2335 | } | 2933 | } |
@@ -2395,13 +2993,20 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
2395 | pin_ctl & ~flag); | 2993 | pin_ctl & ~flag); |
2396 | } | 2994 | } |
2397 | 2995 | ||
2398 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) | 2996 | static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid) |
2399 | { | 2997 | { |
2400 | if (!nid) | 2998 | if (!nid) |
2401 | return 0; | 2999 | return 0; |
2402 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) | 3000 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) |
2403 | & (1 << 31)) | 3001 | & (1 << 31)) { |
2404 | return 1; | 3002 | unsigned int pinctl; |
3003 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
3004 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
3005 | if (pinctl & AC_PINCTL_IN_EN) | ||
3006 | return 0; /* mic- or line-input */ | ||
3007 | else | ||
3008 | return 1; /* HP-output */ | ||
3009 | } | ||
2405 | return 0; | 3010 | return 0; |
2406 | } | 3011 | } |
2407 | 3012 | ||
@@ -2412,10 +3017,14 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | |||
2412 | int i, presence; | 3017 | int i, presence; |
2413 | 3018 | ||
2414 | presence = 0; | 3019 | presence = 0; |
3020 | if (spec->gpio_mute) | ||
3021 | presence = !(snd_hda_codec_read(codec, codec->afg, 0, | ||
3022 | AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute); | ||
3023 | |||
2415 | for (i = 0; i < cfg->hp_outs; i++) { | 3024 | for (i = 0; i < cfg->hp_outs; i++) { |
2416 | presence = get_pin_presence(codec, cfg->hp_pins[i]); | ||
2417 | if (presence) | 3025 | if (presence) |
2418 | break; | 3026 | break; |
3027 | presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); | ||
2419 | } | 3028 | } |
2420 | 3029 | ||
2421 | if (presence) { | 3030 | if (presence) { |
@@ -2437,12 +3046,37 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | |||
2437 | } | 3046 | } |
2438 | } | 3047 | } |
2439 | 3048 | ||
3049 | static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | ||
3050 | { | ||
3051 | struct sigmatel_spec *spec = codec->spec; | ||
3052 | hda_nid_t nid = spec->pwr_nids[idx]; | ||
3053 | int presence, val; | ||
3054 | val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) | ||
3055 | & 0x000000ff; | ||
3056 | presence = get_hp_pin_presence(codec, nid); | ||
3057 | idx = 1 << idx; | ||
3058 | |||
3059 | if (presence) | ||
3060 | val &= ~idx; | ||
3061 | else | ||
3062 | val |= idx; | ||
3063 | |||
3064 | /* power down unused output ports */ | ||
3065 | snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, val); | ||
3066 | }; | ||
3067 | |||
2440 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 3068 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) |
2441 | { | 3069 | { |
2442 | switch (res >> 26) { | 3070 | struct sigmatel_spec *spec = codec->spec; |
3071 | int idx = res >> 26 & 0x0f; | ||
3072 | |||
3073 | switch ((res >> 26) & 0x30) { | ||
2443 | case STAC_HP_EVENT: | 3074 | case STAC_HP_EVENT: |
2444 | stac92xx_hp_detect(codec, res); | 3075 | stac92xx_hp_detect(codec, res); |
2445 | break; | 3076 | /* fallthru */ |
3077 | case STAC_PWR_EVENT: | ||
3078 | if (spec->num_pwrs > 0) | ||
3079 | stac92xx_pin_sense(codec, idx); | ||
2446 | } | 3080 | } |
2447 | } | 3081 | } |
2448 | 3082 | ||
@@ -2453,10 +3087,8 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
2453 | 3087 | ||
2454 | stac92xx_set_config_regs(codec); | 3088 | stac92xx_set_config_regs(codec); |
2455 | snd_hda_sequence_write(codec, spec->init); | 3089 | snd_hda_sequence_write(codec, spec->init); |
2456 | if (spec->gpio_mute) { | 3090 | stac_gpio_set(codec, spec->gpio_mask, |
2457 | stac922x_gpio_mute(codec, 0, 0); | 3091 | spec->gpio_dir, spec->gpio_data); |
2458 | stac922x_gpio_mute(codec, 1, 0); | ||
2459 | } | ||
2460 | snd_hda_codec_resume_amp(codec); | 3092 | snd_hda_codec_resume_amp(codec); |
2461 | snd_hda_codec_resume_cache(codec); | 3093 | snd_hda_codec_resume_cache(codec); |
2462 | /* invoke unsolicited event to reset the HP state */ | 3094 | /* invoke unsolicited event to reset the HP state */ |
@@ -2489,7 +3121,6 @@ static int patch_stac9200(struct hda_codec *codec) | |||
2489 | codec->spec = spec; | 3121 | codec->spec = spec; |
2490 | spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); | 3122 | spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); |
2491 | spec->pin_nids = stac9200_pin_nids; | 3123 | spec->pin_nids = stac9200_pin_nids; |
2492 | spec->no_vol_knob = 1; | ||
2493 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, | 3124 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, |
2494 | stac9200_models, | 3125 | stac9200_models, |
2495 | stac9200_cfg_tbl); | 3126 | stac9200_cfg_tbl); |
@@ -2514,6 +3145,7 @@ static int patch_stac9200(struct hda_codec *codec) | |||
2514 | spec->num_muxes = 1; | 3145 | spec->num_muxes = 1; |
2515 | spec->num_dmics = 0; | 3146 | spec->num_dmics = 0; |
2516 | spec->num_adcs = 1; | 3147 | spec->num_adcs = 1; |
3148 | spec->num_pwrs = 0; | ||
2517 | 3149 | ||
2518 | if (spec->board_config == STAC_9200_GATEWAY) | 3150 | if (spec->board_config == STAC_9200_GATEWAY) |
2519 | spec->init = stac9200_eapd_init; | 3151 | spec->init = stac9200_eapd_init; |
@@ -2544,7 +3176,6 @@ static int patch_stac925x(struct hda_codec *codec) | |||
2544 | codec->spec = spec; | 3176 | codec->spec = spec; |
2545 | spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); | 3177 | spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); |
2546 | spec->pin_nids = stac925x_pin_nids; | 3178 | spec->pin_nids = stac925x_pin_nids; |
2547 | spec->no_vol_knob = 1; | ||
2548 | spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, | 3179 | spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, |
2549 | stac925x_models, | 3180 | stac925x_models, |
2550 | stac925x_cfg_tbl); | 3181 | stac925x_cfg_tbl); |
@@ -2570,6 +3201,7 @@ static int patch_stac925x(struct hda_codec *codec) | |||
2570 | spec->mux_nids = stac925x_mux_nids; | 3201 | spec->mux_nids = stac925x_mux_nids; |
2571 | spec->num_muxes = 1; | 3202 | spec->num_muxes = 1; |
2572 | spec->num_adcs = 1; | 3203 | spec->num_adcs = 1; |
3204 | spec->num_pwrs = 0; | ||
2573 | switch (codec->vendor_id) { | 3205 | switch (codec->vendor_id) { |
2574 | case 0x83847632: /* STAC9202 */ | 3206 | case 0x83847632: /* STAC9202 */ |
2575 | case 0x83847633: /* STAC9202D */ | 3207 | case 0x83847633: /* STAC9202D */ |
@@ -2577,6 +3209,8 @@ static int patch_stac925x(struct hda_codec *codec) | |||
2577 | case 0x83847637: /* STAC9251D */ | 3209 | case 0x83847637: /* STAC9251D */ |
2578 | spec->num_dmics = STAC925X_NUM_DMICS; | 3210 | spec->num_dmics = STAC925X_NUM_DMICS; |
2579 | spec->dmic_nids = stac925x_dmic_nids; | 3211 | spec->dmic_nids = stac925x_dmic_nids; |
3212 | spec->num_dmuxes = ARRAY_SIZE(stac925x_dmux_nids); | ||
3213 | spec->dmux_nids = stac925x_dmux_nids; | ||
2580 | break; | 3214 | break; |
2581 | default: | 3215 | default: |
2582 | spec->num_dmics = 0; | 3216 | spec->num_dmics = 0; |
@@ -2606,6 +3240,204 @@ static int patch_stac925x(struct hda_codec *codec) | |||
2606 | return 0; | 3240 | return 0; |
2607 | } | 3241 | } |
2608 | 3242 | ||
3243 | static struct hda_input_mux stac92hd73xx_dmux = { | ||
3244 | .num_items = 4, | ||
3245 | .items = { | ||
3246 | { "Analog Inputs", 0x0b }, | ||
3247 | { "CD", 0x08 }, | ||
3248 | { "Digital Mic 1", 0x09 }, | ||
3249 | { "Digital Mic 2", 0x0a }, | ||
3250 | } | ||
3251 | }; | ||
3252 | |||
3253 | static int patch_stac92hd73xx(struct hda_codec *codec) | ||
3254 | { | ||
3255 | struct sigmatel_spec *spec; | ||
3256 | hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; | ||
3257 | int err = 0; | ||
3258 | |||
3259 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
3260 | if (spec == NULL) | ||
3261 | return -ENOMEM; | ||
3262 | |||
3263 | codec->spec = spec; | ||
3264 | spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); | ||
3265 | spec->pin_nids = stac92hd73xx_pin_nids; | ||
3266 | spec->board_config = snd_hda_check_board_config(codec, | ||
3267 | STAC_92HD73XX_MODELS, | ||
3268 | stac92hd73xx_models, | ||
3269 | stac92hd73xx_cfg_tbl); | ||
3270 | again: | ||
3271 | if (spec->board_config < 0) { | ||
3272 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | ||
3273 | " STAC92HD73XX, using BIOS defaults\n"); | ||
3274 | err = stac92xx_save_bios_config_regs(codec); | ||
3275 | if (err < 0) { | ||
3276 | stac92xx_free(codec); | ||
3277 | return err; | ||
3278 | } | ||
3279 | spec->pin_configs = spec->bios_pin_configs; | ||
3280 | } else { | ||
3281 | spec->pin_configs = stac92hd73xx_brd_tbl[spec->board_config]; | ||
3282 | stac92xx_set_config_regs(codec); | ||
3283 | } | ||
3284 | |||
3285 | spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a, | ||
3286 | conn, STAC92HD73_DAC_COUNT + 2) - 1; | ||
3287 | |||
3288 | if (spec->multiout.num_dacs < 0) { | ||
3289 | printk(KERN_WARNING "hda_codec: Could not determine " | ||
3290 | "number of channels defaulting to DAC count\n"); | ||
3291 | spec->multiout.num_dacs = STAC92HD73_DAC_COUNT; | ||
3292 | } | ||
3293 | |||
3294 | switch (spec->multiout.num_dacs) { | ||
3295 | case 0x3: /* 6 Channel */ | ||
3296 | spec->mixer = stac92hd73xx_6ch_mixer; | ||
3297 | spec->init = stac92hd73xx_6ch_core_init; | ||
3298 | break; | ||
3299 | case 0x4: /* 8 Channel */ | ||
3300 | spec->multiout.hp_nid = 0x18; | ||
3301 | spec->mixer = stac92hd73xx_8ch_mixer; | ||
3302 | spec->init = stac92hd73xx_8ch_core_init; | ||
3303 | break; | ||
3304 | case 0x5: /* 10 Channel */ | ||
3305 | spec->multiout.hp_nid = 0x19; | ||
3306 | spec->mixer = stac92hd73xx_10ch_mixer; | ||
3307 | spec->init = stac92hd73xx_10ch_core_init; | ||
3308 | }; | ||
3309 | |||
3310 | spec->multiout.dac_nids = stac92hd73xx_dac_nids; | ||
3311 | spec->aloopback_mask = 0x01; | ||
3312 | spec->aloopback_shift = 8; | ||
3313 | |||
3314 | spec->mux_nids = stac92hd73xx_mux_nids; | ||
3315 | spec->adc_nids = stac92hd73xx_adc_nids; | ||
3316 | spec->dmic_nids = stac92hd73xx_dmic_nids; | ||
3317 | spec->dmux_nids = stac92hd73xx_dmux_nids; | ||
3318 | |||
3319 | spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids); | ||
3320 | spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids); | ||
3321 | spec->num_dmics = STAC92HD73XX_NUM_DMICS; | ||
3322 | spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids); | ||
3323 | spec->dinput_mux = &stac92hd73xx_dmux; | ||
3324 | /* GPIO0 High = Enable EAPD */ | ||
3325 | spec->gpio_mask = spec->gpio_dir = 0x1; | ||
3326 | spec->gpio_data = 0x01; | ||
3327 | |||
3328 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); | ||
3329 | spec->pwr_nids = stac92hd73xx_pwr_nids; | ||
3330 | |||
3331 | err = stac92xx_parse_auto_config(codec, 0x22, 0x24); | ||
3332 | |||
3333 | if (!err) { | ||
3334 | if (spec->board_config < 0) { | ||
3335 | printk(KERN_WARNING "hda_codec: No auto-config is " | ||
3336 | "available, default to model=ref\n"); | ||
3337 | spec->board_config = STAC_92HD73XX_REF; | ||
3338 | goto again; | ||
3339 | } | ||
3340 | err = -EINVAL; | ||
3341 | } | ||
3342 | |||
3343 | if (err < 0) { | ||
3344 | stac92xx_free(codec); | ||
3345 | return err; | ||
3346 | } | ||
3347 | |||
3348 | codec->patch_ops = stac92xx_patch_ops; | ||
3349 | |||
3350 | return 0; | ||
3351 | } | ||
3352 | |||
3353 | static int patch_stac92hd71bxx(struct hda_codec *codec) | ||
3354 | { | ||
3355 | struct sigmatel_spec *spec; | ||
3356 | int err = 0; | ||
3357 | |||
3358 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
3359 | if (spec == NULL) | ||
3360 | return -ENOMEM; | ||
3361 | |||
3362 | codec->spec = spec; | ||
3363 | spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids); | ||
3364 | spec->pin_nids = stac92hd71bxx_pin_nids; | ||
3365 | spec->board_config = snd_hda_check_board_config(codec, | ||
3366 | STAC_92HD71BXX_MODELS, | ||
3367 | stac92hd71bxx_models, | ||
3368 | stac92hd71bxx_cfg_tbl); | ||
3369 | again: | ||
3370 | if (spec->board_config < 0) { | ||
3371 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | ||
3372 | " STAC92HD71BXX, using BIOS defaults\n"); | ||
3373 | err = stac92xx_save_bios_config_regs(codec); | ||
3374 | if (err < 0) { | ||
3375 | stac92xx_free(codec); | ||
3376 | return err; | ||
3377 | } | ||
3378 | spec->pin_configs = spec->bios_pin_configs; | ||
3379 | } else { | ||
3380 | spec->pin_configs = stac92hd71bxx_brd_tbl[spec->board_config]; | ||
3381 | stac92xx_set_config_regs(codec); | ||
3382 | } | ||
3383 | |||
3384 | switch (codec->vendor_id) { | ||
3385 | case 0x111d76b6: /* 4 Port without Analog Mixer */ | ||
3386 | case 0x111d76b7: | ||
3387 | case 0x111d76b4: /* 6 Port without Analog Mixer */ | ||
3388 | case 0x111d76b5: | ||
3389 | spec->mixer = stac92hd71bxx_mixer; | ||
3390 | spec->init = stac92hd71bxx_core_init; | ||
3391 | break; | ||
3392 | default: | ||
3393 | spec->mixer = stac92hd71bxx_analog_mixer; | ||
3394 | spec->init = stac92hd71bxx_analog_core_init; | ||
3395 | } | ||
3396 | |||
3397 | spec->aloopback_mask = 0x20; | ||
3398 | spec->aloopback_shift = 0; | ||
3399 | |||
3400 | /* GPIO0 High = EAPD */ | ||
3401 | spec->gpio_mask = spec->gpio_dir = spec->gpio_data = 0x1; | ||
3402 | |||
3403 | spec->mux_nids = stac92hd71bxx_mux_nids; | ||
3404 | spec->adc_nids = stac92hd71bxx_adc_nids; | ||
3405 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | ||
3406 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | ||
3407 | |||
3408 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); | ||
3409 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); | ||
3410 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; | ||
3411 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | ||
3412 | |||
3413 | spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids); | ||
3414 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | ||
3415 | |||
3416 | spec->multiout.num_dacs = 2; | ||
3417 | spec->multiout.hp_nid = 0x11; | ||
3418 | spec->multiout.dac_nids = stac92hd71bxx_dac_nids; | ||
3419 | |||
3420 | err = stac92xx_parse_auto_config(codec, 0x21, 0x23); | ||
3421 | if (!err) { | ||
3422 | if (spec->board_config < 0) { | ||
3423 | printk(KERN_WARNING "hda_codec: No auto-config is " | ||
3424 | "available, default to model=ref\n"); | ||
3425 | spec->board_config = STAC_92HD71BXX_REF; | ||
3426 | goto again; | ||
3427 | } | ||
3428 | err = -EINVAL; | ||
3429 | } | ||
3430 | |||
3431 | if (err < 0) { | ||
3432 | stac92xx_free(codec); | ||
3433 | return err; | ||
3434 | } | ||
3435 | |||
3436 | codec->patch_ops = stac92xx_patch_ops; | ||
3437 | |||
3438 | return 0; | ||
3439 | }; | ||
3440 | |||
2609 | static int patch_stac922x(struct hda_codec *codec) | 3441 | static int patch_stac922x(struct hda_codec *codec) |
2610 | { | 3442 | { |
2611 | struct sigmatel_spec *spec; | 3443 | struct sigmatel_spec *spec; |
@@ -2622,7 +3454,8 @@ static int patch_stac922x(struct hda_codec *codec) | |||
2622 | stac922x_models, | 3454 | stac922x_models, |
2623 | stac922x_cfg_tbl); | 3455 | stac922x_cfg_tbl); |
2624 | if (spec->board_config == STAC_INTEL_MAC_V3) { | 3456 | if (spec->board_config == STAC_INTEL_MAC_V3) { |
2625 | spec->gpio_mute = 1; | 3457 | spec->gpio_mask = spec->gpio_dir = 0x03; |
3458 | spec->gpio_data = 0x03; | ||
2626 | /* Intel Macs have all same PCI SSID, so we need to check | 3459 | /* Intel Macs have all same PCI SSID, so we need to check |
2627 | * codec SSID to distinguish the exact models | 3460 | * codec SSID to distinguish the exact models |
2628 | */ | 3461 | */ |
@@ -2675,6 +3508,7 @@ static int patch_stac922x(struct hda_codec *codec) | |||
2675 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); | 3508 | spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids); |
2676 | spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); | 3509 | spec->num_adcs = ARRAY_SIZE(stac922x_adc_nids); |
2677 | spec->num_dmics = 0; | 3510 | spec->num_dmics = 0; |
3511 | spec->num_pwrs = 0; | ||
2678 | 3512 | ||
2679 | spec->init = stac922x_core_init; | 3513 | spec->init = stac922x_core_init; |
2680 | spec->mixer = stac922x_mixer; | 3514 | spec->mixer = stac922x_mixer; |
@@ -2724,53 +3558,70 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2724 | stac927x_models, | 3558 | stac927x_models, |
2725 | stac927x_cfg_tbl); | 3559 | stac927x_cfg_tbl); |
2726 | again: | 3560 | again: |
2727 | if (spec->board_config < 0) { | 3561 | if (spec->board_config < 0 || !stac927x_brd_tbl[spec->board_config]) { |
2728 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); | 3562 | if (spec->board_config < 0) |
3563 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | ||
3564 | "STAC927x, using BIOS defaults\n"); | ||
2729 | err = stac92xx_save_bios_config_regs(codec); | 3565 | err = stac92xx_save_bios_config_regs(codec); |
2730 | if (err < 0) { | 3566 | if (err < 0) { |
2731 | stac92xx_free(codec); | 3567 | stac92xx_free(codec); |
2732 | return err; | 3568 | return err; |
2733 | } | 3569 | } |
2734 | spec->pin_configs = spec->bios_pin_configs; | 3570 | spec->pin_configs = spec->bios_pin_configs; |
2735 | } else if (stac927x_brd_tbl[spec->board_config] != NULL) { | 3571 | } else { |
2736 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; | 3572 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; |
2737 | stac92xx_set_config_regs(codec); | 3573 | stac92xx_set_config_regs(codec); |
2738 | } | 3574 | } |
2739 | 3575 | ||
3576 | spec->adc_nids = stac927x_adc_nids; | ||
3577 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
3578 | spec->mux_nids = stac927x_mux_nids; | ||
3579 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | ||
3580 | spec->multiout.dac_nids = spec->dac_nids; | ||
3581 | |||
2740 | switch (spec->board_config) { | 3582 | switch (spec->board_config) { |
2741 | case STAC_D965_3ST: | 3583 | case STAC_D965_3ST: |
2742 | spec->adc_nids = stac927x_adc_nids; | 3584 | case STAC_D965_5ST: |
2743 | spec->mux_nids = stac927x_mux_nids; | 3585 | /* GPIO0 High = Enable EAPD */ |
2744 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 3586 | spec->gpio_mask = spec->gpio_dir = 0x01; |
2745 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | 3587 | spec->gpio_data = 0x01; |
2746 | spec->num_dmics = 0; | 3588 | spec->num_dmics = 0; |
3589 | |||
2747 | spec->init = d965_core_init; | 3590 | spec->init = d965_core_init; |
2748 | spec->mixer = stac927x_mixer; | 3591 | spec->mixer = stac927x_mixer; |
2749 | break; | 3592 | break; |
2750 | case STAC_D965_5ST: | 3593 | case STAC_DELL_BIOS: |
2751 | spec->adc_nids = stac927x_adc_nids; | 3594 | /* correct the front output jack as a hp out */ |
2752 | spec->mux_nids = stac927x_mux_nids; | 3595 | stac92xx_set_config_reg(codec, 0x0f, 0x02270110); |
2753 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 3596 | /* correct the front input jack as a mic */ |
2754 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | 3597 | stac92xx_set_config_reg(codec, 0x0e, 0x02a79130); |
2755 | spec->num_dmics = 0; | 3598 | /* fallthru */ |
3599 | case STAC_DELL_3ST: | ||
3600 | /* GPIO2 High = Enable EAPD */ | ||
3601 | spec->gpio_mask = spec->gpio_dir = 0x04; | ||
3602 | spec->gpio_data = 0x04; | ||
3603 | spec->dmic_nids = stac927x_dmic_nids; | ||
3604 | spec->num_dmics = STAC927X_NUM_DMICS; | ||
3605 | |||
2756 | spec->init = d965_core_init; | 3606 | spec->init = d965_core_init; |
2757 | spec->mixer = stac927x_mixer; | 3607 | spec->mixer = stac927x_mixer; |
3608 | spec->dmux_nids = stac927x_dmux_nids; | ||
3609 | spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids); | ||
2758 | break; | 3610 | break; |
2759 | default: | 3611 | default: |
2760 | spec->adc_nids = stac927x_adc_nids; | 3612 | /* GPIO0 High = Enable EAPD */ |
2761 | spec->mux_nids = stac927x_mux_nids; | 3613 | spec->gpio_mask = spec->gpio_dir = 0x1; |
2762 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 3614 | spec->gpio_data = 0x01; |
2763 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | ||
2764 | spec->num_dmics = 0; | 3615 | spec->num_dmics = 0; |
3616 | |||
2765 | spec->init = stac927x_core_init; | 3617 | spec->init = stac927x_core_init; |
2766 | spec->mixer = stac927x_mixer; | 3618 | spec->mixer = stac927x_mixer; |
2767 | } | 3619 | } |
2768 | 3620 | ||
2769 | spec->multiout.dac_nids = spec->dac_nids; | 3621 | spec->num_pwrs = 0; |
2770 | /* GPIO0 High = Enable EAPD */ | 3622 | spec->aloopback_mask = 0x40; |
2771 | spec->gpio_mask = spec->gpio_data = 0x00000001; | 3623 | spec->aloopback_shift = 0; |
2772 | stac92xx_enable_gpio_mask(codec); | 3624 | |
2773 | |||
2774 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | 3625 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); |
2775 | if (!err) { | 3626 | if (!err) { |
2776 | if (spec->board_config < 0) { | 3627 | if (spec->board_config < 0) { |
@@ -2788,6 +3639,18 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2788 | 3639 | ||
2789 | codec->patch_ops = stac92xx_patch_ops; | 3640 | codec->patch_ops = stac92xx_patch_ops; |
2790 | 3641 | ||
3642 | /* | ||
3643 | * !!FIXME!! | ||
3644 | * The STAC927x seem to require fairly long delays for certain | ||
3645 | * command sequences. With too short delays (even if the answer | ||
3646 | * is set to RIRB properly), it results in the silence output | ||
3647 | * on some hardwares like Dell. | ||
3648 | * | ||
3649 | * The below flag enables the longer delay (see get_response | ||
3650 | * in hda_intel.c). | ||
3651 | */ | ||
3652 | codec->bus->needs_damn_long_delay = 1; | ||
3653 | |||
2791 | return 0; | 3654 | return 0; |
2792 | } | 3655 | } |
2793 | 3656 | ||
@@ -2826,11 +3689,15 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2826 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); | 3689 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); |
2827 | spec->dmic_nids = stac9205_dmic_nids; | 3690 | spec->dmic_nids = stac9205_dmic_nids; |
2828 | spec->num_dmics = STAC9205_NUM_DMICS; | 3691 | spec->num_dmics = STAC9205_NUM_DMICS; |
2829 | spec->dmux_nid = 0x1d; | 3692 | spec->dmux_nids = stac9205_dmux_nids; |
3693 | spec->num_dmuxes = ARRAY_SIZE(stac9205_dmux_nids); | ||
3694 | spec->num_pwrs = 0; | ||
2830 | 3695 | ||
2831 | spec->init = stac9205_core_init; | 3696 | spec->init = stac9205_core_init; |
2832 | spec->mixer = stac9205_mixer; | 3697 | spec->mixer = stac9205_mixer; |
2833 | 3698 | ||
3699 | spec->aloopback_mask = 0x40; | ||
3700 | spec->aloopback_shift = 0; | ||
2834 | spec->multiout.dac_nids = spec->dac_nids; | 3701 | spec->multiout.dac_nids = spec->dac_nids; |
2835 | 3702 | ||
2836 | switch (spec->board_config){ | 3703 | switch (spec->board_config){ |
@@ -2839,19 +3706,28 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2839 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); | 3706 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); |
2840 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | 3707 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); |
2841 | 3708 | ||
2842 | spec->gpio_mask = 0x00000007; /* GPIO0-2 */ | 3709 | /* Enable unsol response for GPIO4/Dock HP connection */ |
2843 | /* GPIO0 High = EAPD, GPIO1 Low = DRM, | 3710 | snd_hda_codec_write(codec, codec->afg, 0, |
2844 | * GPIO2 High = Headphone Mute | 3711 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
3712 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
3713 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
3714 | (AC_USRSP_EN | STAC_HP_EVENT)); | ||
3715 | |||
3716 | spec->gpio_dir = 0x0b; | ||
3717 | spec->gpio_mask = 0x1b; | ||
3718 | spec->gpio_mute = 0x10; | ||
3719 | /* GPIO0 High = EAPD, GPIO1 Low = Headphone Mute, | ||
3720 | * GPIO3 Low = DRM | ||
2845 | */ | 3721 | */ |
2846 | spec->gpio_data = 0x00000005; | 3722 | spec->gpio_data = 0x01; |
2847 | break; | 3723 | break; |
2848 | default: | 3724 | default: |
2849 | /* GPIO0 High = EAPD */ | 3725 | /* GPIO0 High = EAPD */ |
2850 | spec->gpio_mask = spec->gpio_data = 0x00000001; | 3726 | spec->gpio_mask = spec->gpio_dir = 0x1; |
3727 | spec->gpio_data = 0x01; | ||
2851 | break; | 3728 | break; |
2852 | } | 3729 | } |
2853 | 3730 | ||
2854 | stac92xx_enable_gpio_mask(codec); | ||
2855 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); | 3731 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); |
2856 | if (!err) { | 3732 | if (!err) { |
2857 | if (spec->board_config < 0) { | 3733 | if (spec->board_config < 0) { |
@@ -3005,7 +3881,7 @@ static int stac9872_vaio_init(struct hda_codec *codec) | |||
3005 | 3881 | ||
3006 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | 3882 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) |
3007 | { | 3883 | { |
3008 | if (get_pin_presence(codec, 0x0a)) { | 3884 | if (get_hp_pin_presence(codec, 0x0a)) { |
3009 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | 3885 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); |
3010 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | 3886 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); |
3011 | } else { | 3887 | } else { |
@@ -3087,6 +3963,7 @@ static int patch_stac9872(struct hda_codec *codec) | |||
3087 | spec->multiout.hp_nid = VAIO_HP_DAC; | 3963 | spec->multiout.hp_nid = VAIO_HP_DAC; |
3088 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | 3964 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); |
3089 | spec->adc_nids = vaio_adcs; | 3965 | spec->adc_nids = vaio_adcs; |
3966 | spec->num_pwrs = 0; | ||
3090 | spec->input_mux = &vaio_mux; | 3967 | spec->input_mux = &vaio_mux; |
3091 | spec->mux_nids = vaio_mux_nids; | 3968 | spec->mux_nids = vaio_mux_nids; |
3092 | codec->patch_ops = stac9872_vaio_patch_ops; | 3969 | codec->patch_ops = stac9872_vaio_patch_ops; |
@@ -3100,6 +3977,7 @@ static int patch_stac9872(struct hda_codec *codec) | |||
3100 | spec->multiout.dac_nids = vaio_dacs; | 3977 | spec->multiout.dac_nids = vaio_dacs; |
3101 | spec->multiout.hp_nid = VAIO_HP_DAC; | 3978 | spec->multiout.hp_nid = VAIO_HP_DAC; |
3102 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); | 3979 | spec->num_adcs = ARRAY_SIZE(vaio_adcs); |
3980 | spec->num_pwrs = 0; | ||
3103 | spec->adc_nids = vaio_adcs; | 3981 | spec->adc_nids = vaio_adcs; |
3104 | spec->input_mux = &vaio_mux; | 3982 | spec->input_mux = &vaio_mux; |
3105 | spec->mux_nids = vaio_mux_nids; | 3983 | spec->mux_nids = vaio_mux_nids; |
@@ -3159,5 +4037,17 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
3159 | { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, | 4037 | { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, |
3160 | { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, | 4038 | { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, |
3161 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, | 4039 | { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, |
4040 | { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, | ||
4041 | { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, | ||
4042 | { .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx }, | ||
4043 | { .id = 0x111d7608, .name = "92HD71BXX", .patch = patch_stac92hd71bxx }, | ||
4044 | { .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, | ||
4045 | { .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx }, | ||
4046 | { .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, | ||
4047 | { .id = 0x111d76b3, .name = "92HD71B7X", .patch = patch_stac92hd71bxx }, | ||
4048 | { .id = 0x111d76b4, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, | ||
4049 | { .id = 0x111d76b5, .name = "92HD71B6X", .patch = patch_stac92hd71bxx }, | ||
4050 | { .id = 0x111d76b6, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, | ||
4051 | { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, | ||
3162 | {} /* terminator */ | 4052 | {} /* terminator */ |
3163 | }; | 4053 | }; |