diff options
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r-- | sound/pci/hda/patch_via.c | 2230 |
1 files changed, 1110 insertions, 1120 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index ae3acb2b42d1..f43bb0eaed8b 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -98,24 +98,30 @@ enum VIA_HDA_CODEC { | |||
98 | VT1716S, | 98 | VT1716S, |
99 | VT2002P, | 99 | VT2002P, |
100 | VT1812, | 100 | VT1812, |
101 | VT1802, | ||
101 | CODEC_TYPES, | 102 | CODEC_TYPES, |
102 | }; | 103 | }; |
103 | 104 | ||
105 | #define VT2002P_COMPATIBLE(spec) \ | ||
106 | ((spec)->codec_type == VT2002P ||\ | ||
107 | (spec)->codec_type == VT1812 ||\ | ||
108 | (spec)->codec_type == VT1802) | ||
109 | |||
104 | struct via_spec { | 110 | struct via_spec { |
105 | /* codec parameterization */ | 111 | /* codec parameterization */ |
106 | struct snd_kcontrol_new *mixers[6]; | 112 | const struct snd_kcontrol_new *mixers[6]; |
107 | unsigned int num_mixers; | 113 | unsigned int num_mixers; |
108 | 114 | ||
109 | struct hda_verb *init_verbs[5]; | 115 | const struct hda_verb *init_verbs[5]; |
110 | unsigned int num_iverbs; | 116 | unsigned int num_iverbs; |
111 | 117 | ||
112 | char *stream_name_analog; | 118 | char *stream_name_analog; |
113 | struct hda_pcm_stream *stream_analog_playback; | 119 | const struct hda_pcm_stream *stream_analog_playback; |
114 | struct hda_pcm_stream *stream_analog_capture; | 120 | const struct hda_pcm_stream *stream_analog_capture; |
115 | 121 | ||
116 | char *stream_name_digital; | 122 | char *stream_name_digital; |
117 | struct hda_pcm_stream *stream_digital_playback; | 123 | const struct hda_pcm_stream *stream_digital_playback; |
118 | struct hda_pcm_stream *stream_digital_capture; | 124 | const struct hda_pcm_stream *stream_digital_capture; |
119 | 125 | ||
120 | /* playback */ | 126 | /* playback */ |
121 | struct hda_multi_out multiout; | 127 | struct hda_multi_out multiout; |
@@ -123,7 +129,7 @@ struct via_spec { | |||
123 | 129 | ||
124 | /* capture */ | 130 | /* capture */ |
125 | unsigned int num_adc_nids; | 131 | unsigned int num_adc_nids; |
126 | hda_nid_t *adc_nids; | 132 | const hda_nid_t *adc_nids; |
127 | hda_nid_t mux_nids[3]; | 133 | hda_nid_t mux_nids[3]; |
128 | hda_nid_t dig_in_nid; | 134 | hda_nid_t dig_in_nid; |
129 | hda_nid_t dig_in_pin; | 135 | hda_nid_t dig_in_pin; |
@@ -154,11 +160,15 @@ struct via_spec { | |||
154 | struct delayed_work vt1708_hp_work; | 160 | struct delayed_work vt1708_hp_work; |
155 | int vt1708_jack_detectect; | 161 | int vt1708_jack_detectect; |
156 | int vt1708_hp_present; | 162 | int vt1708_hp_present; |
163 | |||
164 | void (*set_widgets_power_state)(struct hda_codec *codec); | ||
165 | |||
157 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 166 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
158 | struct hda_loopback_check loopback; | 167 | struct hda_loopback_check loopback; |
159 | #endif | 168 | #endif |
160 | }; | 169 | }; |
161 | 170 | ||
171 | static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec); | ||
162 | static struct via_spec * via_new_spec(struct hda_codec *codec) | 172 | static struct via_spec * via_new_spec(struct hda_codec *codec) |
163 | { | 173 | { |
164 | struct via_spec *spec; | 174 | struct via_spec *spec; |
@@ -169,6 +179,10 @@ static struct via_spec * via_new_spec(struct hda_codec *codec) | |||
169 | 179 | ||
170 | codec->spec = spec; | 180 | codec->spec = spec; |
171 | spec->codec = codec; | 181 | spec->codec = codec; |
182 | spec->codec_type = get_codec_type(codec); | ||
183 | /* VT1708BCE & VT1708S are almost same */ | ||
184 | if (spec->codec_type == VT1708BCE) | ||
185 | spec->codec_type = VT1708S; | ||
172 | return spec; | 186 | return spec; |
173 | } | 187 | } |
174 | 188 | ||
@@ -213,17 +227,19 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec) | |||
213 | codec_type = VT1812; | 227 | codec_type = VT1812; |
214 | else if (dev_id == 0x0440) | 228 | else if (dev_id == 0x0440) |
215 | codec_type = VT1708S; | 229 | codec_type = VT1708S; |
230 | else if ((dev_id & 0xfff) == 0x446) | ||
231 | codec_type = VT1802; | ||
216 | else | 232 | else |
217 | codec_type = UNKNOWN; | 233 | codec_type = UNKNOWN; |
218 | return codec_type; | 234 | return codec_type; |
219 | }; | 235 | }; |
220 | 236 | ||
237 | #define VIA_JACK_EVENT 0x20 | ||
221 | #define VIA_HP_EVENT 0x01 | 238 | #define VIA_HP_EVENT 0x01 |
222 | #define VIA_GPIO_EVENT 0x02 | 239 | #define VIA_GPIO_EVENT 0x02 |
223 | #define VIA_JACK_EVENT 0x04 | 240 | #define VIA_MONO_EVENT 0x03 |
224 | #define VIA_MONO_EVENT 0x08 | 241 | #define VIA_SPEAKER_EVENT 0x04 |
225 | #define VIA_SPEAKER_EVENT 0x10 | 242 | #define VIA_BIND_HP_EVENT 0x05 |
226 | #define VIA_BIND_HP_EVENT 0x20 | ||
227 | 243 | ||
228 | enum { | 244 | enum { |
229 | VIA_CTL_WIDGET_VOL, | 245 | VIA_CTL_WIDGET_VOL, |
@@ -240,7 +256,6 @@ enum { | |||
240 | }; | 256 | }; |
241 | 257 | ||
242 | static void analog_low_current_mode(struct hda_codec *codec, int stream_idle); | 258 | static void analog_low_current_mode(struct hda_codec *codec, int stream_idle); |
243 | static void set_jack_power_state(struct hda_codec *codec); | ||
244 | static int is_aa_path_mute(struct hda_codec *codec); | 259 | static int is_aa_path_mute(struct hda_codec *codec); |
245 | 260 | ||
246 | static void vt1708_start_hp_work(struct via_spec *spec) | 261 | static void vt1708_start_hp_work(struct via_spec *spec) |
@@ -263,10 +278,15 @@ static void vt1708_stop_hp_work(struct via_spec *spec) | |||
263 | return; | 278 | return; |
264 | snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, | 279 | snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, |
265 | !spec->vt1708_jack_detectect); | 280 | !spec->vt1708_jack_detectect); |
266 | cancel_delayed_work(&spec->vt1708_hp_work); | 281 | cancel_delayed_work_sync(&spec->vt1708_hp_work); |
267 | flush_scheduled_work(); | ||
268 | } | 282 | } |
269 | 283 | ||
284 | static void set_widgets_power_state(struct hda_codec *codec) | ||
285 | { | ||
286 | struct via_spec *spec = codec->spec; | ||
287 | if (spec->set_widgets_power_state) | ||
288 | spec->set_widgets_power_state(codec); | ||
289 | } | ||
270 | 290 | ||
271 | static int analog_input_switch_put(struct snd_kcontrol *kcontrol, | 291 | static int analog_input_switch_put(struct snd_kcontrol *kcontrol, |
272 | struct snd_ctl_elem_value *ucontrol) | 292 | struct snd_ctl_elem_value *ucontrol) |
@@ -274,7 +294,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol, | |||
274 | int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 294 | int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); |
275 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 295 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
276 | 296 | ||
277 | set_jack_power_state(codec); | 297 | set_widgets_power_state(codec); |
278 | analog_low_current_mode(snd_kcontrol_chip(kcontrol), -1); | 298 | analog_low_current_mode(snd_kcontrol_chip(kcontrol), -1); |
279 | if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) { | 299 | if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) { |
280 | if (is_aa_path_mute(codec)) | 300 | if (is_aa_path_mute(codec)) |
@@ -390,62 +410,62 @@ static int bind_pin_switch_put(struct snd_kcontrol *kcontrol, | |||
390 | .put = bind_pin_switch_put, \ | 410 | .put = bind_pin_switch_put, \ |
391 | .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) } | 411 | .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0) } |
392 | 412 | ||
393 | static struct snd_kcontrol_new via_control_templates[] = { | 413 | static const struct snd_kcontrol_new via_control_templates[] = { |
394 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | 414 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), |
395 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | 415 | HDA_CODEC_MUTE(NULL, 0, 0, 0), |
396 | ANALOG_INPUT_MUTE, | 416 | ANALOG_INPUT_MUTE, |
397 | BIND_PIN_MUTE, | 417 | BIND_PIN_MUTE, |
398 | }; | 418 | }; |
399 | 419 | ||
400 | static hda_nid_t vt1708_adc_nids[2] = { | 420 | static const hda_nid_t vt1708_adc_nids[2] = { |
401 | /* ADC1-2 */ | 421 | /* ADC1-2 */ |
402 | 0x15, 0x27 | 422 | 0x15, 0x27 |
403 | }; | 423 | }; |
404 | 424 | ||
405 | static hda_nid_t vt1709_adc_nids[3] = { | 425 | static const hda_nid_t vt1709_adc_nids[3] = { |
406 | /* ADC1-2 */ | 426 | /* ADC1-2 */ |
407 | 0x14, 0x15, 0x16 | 427 | 0x14, 0x15, 0x16 |
408 | }; | 428 | }; |
409 | 429 | ||
410 | static hda_nid_t vt1708B_adc_nids[2] = { | 430 | static const hda_nid_t vt1708B_adc_nids[2] = { |
411 | /* ADC1-2 */ | 431 | /* ADC1-2 */ |
412 | 0x13, 0x14 | 432 | 0x13, 0x14 |
413 | }; | 433 | }; |
414 | 434 | ||
415 | static hda_nid_t vt1708S_adc_nids[2] = { | 435 | static const hda_nid_t vt1708S_adc_nids[2] = { |
416 | /* ADC1-2 */ | 436 | /* ADC1-2 */ |
417 | 0x13, 0x14 | 437 | 0x13, 0x14 |
418 | }; | 438 | }; |
419 | 439 | ||
420 | static hda_nid_t vt1702_adc_nids[3] = { | 440 | static const hda_nid_t vt1702_adc_nids[3] = { |
421 | /* ADC1-2 */ | 441 | /* ADC1-2 */ |
422 | 0x12, 0x20, 0x1F | 442 | 0x12, 0x20, 0x1F |
423 | }; | 443 | }; |
424 | 444 | ||
425 | static hda_nid_t vt1718S_adc_nids[2] = { | 445 | static const hda_nid_t vt1718S_adc_nids[2] = { |
426 | /* ADC1-2 */ | 446 | /* ADC1-2 */ |
427 | 0x10, 0x11 | 447 | 0x10, 0x11 |
428 | }; | 448 | }; |
429 | 449 | ||
430 | static hda_nid_t vt1716S_adc_nids[2] = { | 450 | static const hda_nid_t vt1716S_adc_nids[2] = { |
431 | /* ADC1-2 */ | 451 | /* ADC1-2 */ |
432 | 0x13, 0x14 | 452 | 0x13, 0x14 |
433 | }; | 453 | }; |
434 | 454 | ||
435 | static hda_nid_t vt2002P_adc_nids[2] = { | 455 | static const hda_nid_t vt2002P_adc_nids[2] = { |
436 | /* ADC1-2 */ | 456 | /* ADC1-2 */ |
437 | 0x10, 0x11 | 457 | 0x10, 0x11 |
438 | }; | 458 | }; |
439 | 459 | ||
440 | static hda_nid_t vt1812_adc_nids[2] = { | 460 | static const hda_nid_t vt1812_adc_nids[2] = { |
441 | /* ADC1-2 */ | 461 | /* ADC1-2 */ |
442 | 0x10, 0x11 | 462 | 0x10, 0x11 |
443 | }; | 463 | }; |
444 | 464 | ||
445 | 465 | ||
446 | /* add dynamic controls */ | 466 | /* add dynamic controls */ |
447 | static int via_add_control(struct via_spec *spec, int type, const char *name, | 467 | static int __via_add_control(struct via_spec *spec, int type, const char *name, |
448 | unsigned long val) | 468 | int idx, unsigned long val) |
449 | { | 469 | { |
450 | struct snd_kcontrol_new *knew; | 470 | struct snd_kcontrol_new *knew; |
451 | 471 | ||
@@ -463,8 +483,11 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, | |||
463 | return 0; | 483 | return 0; |
464 | } | 484 | } |
465 | 485 | ||
486 | #define via_add_control(spec, type, name, val) \ | ||
487 | __via_add_control(spec, type, name, 0, val) | ||
488 | |||
466 | static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, | 489 | static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, |
467 | struct snd_kcontrol_new *tmpl) | 490 | const struct snd_kcontrol_new *tmpl) |
468 | { | 491 | { |
469 | struct snd_kcontrol_new *knew; | 492 | struct snd_kcontrol_new *knew; |
470 | 493 | ||
@@ -494,18 +517,18 @@ static void via_free_kctls(struct hda_codec *codec) | |||
494 | 517 | ||
495 | /* create input playback/capture controls for the given pin */ | 518 | /* create input playback/capture controls for the given pin */ |
496 | static int via_new_analog_input(struct via_spec *spec, const char *ctlname, | 519 | static int via_new_analog_input(struct via_spec *spec, const char *ctlname, |
497 | int idx, int mix_nid) | 520 | int type_idx, int idx, int mix_nid) |
498 | { | 521 | { |
499 | char name[32]; | 522 | char name[32]; |
500 | int err; | 523 | int err; |
501 | 524 | ||
502 | sprintf(name, "%s Playback Volume", ctlname); | 525 | sprintf(name, "%s Playback Volume", ctlname); |
503 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 526 | err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, |
504 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 527 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
505 | if (err < 0) | 528 | if (err < 0) |
506 | return err; | 529 | return err; |
507 | sprintf(name, "%s Playback Switch", ctlname); | 530 | sprintf(name, "%s Playback Switch", ctlname); |
508 | err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, | 531 | err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx, |
509 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 532 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
510 | if (err < 0) | 533 | if (err < 0) |
511 | return err; | 534 | return err; |
@@ -557,17 +580,15 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin); | |||
557 | static void via_auto_init_analog_input(struct hda_codec *codec) | 580 | static void via_auto_init_analog_input(struct hda_codec *codec) |
558 | { | 581 | { |
559 | struct via_spec *spec = codec->spec; | 582 | struct via_spec *spec = codec->spec; |
583 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
560 | unsigned int ctl; | 584 | unsigned int ctl; |
561 | int i; | 585 | int i; |
562 | 586 | ||
563 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 587 | for (i = 0; i < cfg->num_inputs; i++) { |
564 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 588 | hda_nid_t nid = cfg->inputs[i].pin; |
565 | if (!nid) | ||
566 | continue; | ||
567 | |||
568 | if (spec->smart51_enabled && is_smart51_pins(spec, nid)) | 589 | if (spec->smart51_enabled && is_smart51_pins(spec, nid)) |
569 | ctl = PIN_OUT; | 590 | ctl = PIN_OUT; |
570 | else if (i <= AUTO_PIN_FRONT_MIC) | 591 | else if (cfg->inputs[i].type == AUTO_PIN_MIC) |
571 | ctl = PIN_VREF50; | 592 | ctl = PIN_VREF50; |
572 | else | 593 | else |
573 | ctl = PIN_IN; | 594 | ctl = PIN_IN; |
@@ -597,482 +618,6 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, | |||
597 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); | 618 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); |
598 | } | 619 | } |
599 | 620 | ||
600 | static void set_jack_power_state(struct hda_codec *codec) | ||
601 | { | ||
602 | struct via_spec *spec = codec->spec; | ||
603 | int imux_is_smixer; | ||
604 | unsigned int parm; | ||
605 | |||
606 | if (spec->codec_type == VT1702) { | ||
607 | imux_is_smixer = snd_hda_codec_read( | ||
608 | codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3; | ||
609 | /* inputs */ | ||
610 | /* PW 1/2/5 (14h/15h/18h) */ | ||
611 | parm = AC_PWRST_D3; | ||
612 | set_pin_power_state(codec, 0x14, &parm); | ||
613 | set_pin_power_state(codec, 0x15, &parm); | ||
614 | set_pin_power_state(codec, 0x18, &parm); | ||
615 | if (imux_is_smixer) | ||
616 | parm = AC_PWRST_D0; /* SW0 = stereo mixer (idx 3) */ | ||
617 | /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */ | ||
618 | snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, | ||
619 | parm); | ||
620 | snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, | ||
621 | parm); | ||
622 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, | ||
623 | parm); | ||
624 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, | ||
625 | parm); | ||
626 | |||
627 | /* outputs */ | ||
628 | /* PW 3/4 (16h/17h) */ | ||
629 | parm = AC_PWRST_D3; | ||
630 | set_pin_power_state(codec, 0x16, &parm); | ||
631 | set_pin_power_state(codec, 0x17, &parm); | ||
632 | /* MW0 (1ah), AOW 0/1 (10h/1dh) */ | ||
633 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, | ||
634 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
635 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, | ||
636 | parm); | ||
637 | snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, | ||
638 | parm); | ||
639 | } else if (spec->codec_type == VT1708B_8CH | ||
640 | || spec->codec_type == VT1708B_4CH | ||
641 | || spec->codec_type == VT1708S) { | ||
642 | /* SW0 (17h) = stereo mixer */ | ||
643 | int is_8ch = spec->codec_type != VT1708B_4CH; | ||
644 | imux_is_smixer = snd_hda_codec_read( | ||
645 | codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) | ||
646 | == ((spec->codec_type == VT1708S) ? 5 : 0); | ||
647 | /* inputs */ | ||
648 | /* PW 1/2/5 (1ah/1bh/1eh) */ | ||
649 | parm = AC_PWRST_D3; | ||
650 | set_pin_power_state(codec, 0x1a, &parm); | ||
651 | set_pin_power_state(codec, 0x1b, &parm); | ||
652 | set_pin_power_state(codec, 0x1e, &parm); | ||
653 | if (imux_is_smixer) | ||
654 | parm = AC_PWRST_D0; | ||
655 | /* SW0 (17h), AIW 0/1 (13h/14h) */ | ||
656 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, | ||
657 | parm); | ||
658 | snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, | ||
659 | parm); | ||
660 | snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, | ||
661 | parm); | ||
662 | |||
663 | /* outputs */ | ||
664 | /* PW0 (19h), SW1 (18h), AOW1 (11h) */ | ||
665 | parm = AC_PWRST_D3; | ||
666 | set_pin_power_state(codec, 0x19, &parm); | ||
667 | if (spec->smart51_enabled) | ||
668 | parm = AC_PWRST_D0; | ||
669 | snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, | ||
670 | parm); | ||
671 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, | ||
672 | parm); | ||
673 | |||
674 | /* PW6 (22h), SW2 (26h), AOW2 (24h) */ | ||
675 | if (is_8ch) { | ||
676 | parm = AC_PWRST_D3; | ||
677 | set_pin_power_state(codec, 0x22, &parm); | ||
678 | if (spec->smart51_enabled) | ||
679 | parm = AC_PWRST_D0; | ||
680 | snd_hda_codec_write(codec, 0x26, 0, | ||
681 | AC_VERB_SET_POWER_STATE, parm); | ||
682 | snd_hda_codec_write(codec, 0x24, 0, | ||
683 | AC_VERB_SET_POWER_STATE, parm); | ||
684 | } | ||
685 | |||
686 | /* PW 3/4/7 (1ch/1dh/23h) */ | ||
687 | parm = AC_PWRST_D3; | ||
688 | /* force to D0 for internal Speaker */ | ||
689 | set_pin_power_state(codec, 0x1c, &parm); | ||
690 | set_pin_power_state(codec, 0x1d, &parm); | ||
691 | if (is_8ch) | ||
692 | set_pin_power_state(codec, 0x23, &parm); | ||
693 | /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */ | ||
694 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, | ||
695 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
696 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, | ||
697 | parm); | ||
698 | if (is_8ch) { | ||
699 | snd_hda_codec_write(codec, 0x25, 0, | ||
700 | AC_VERB_SET_POWER_STATE, parm); | ||
701 | snd_hda_codec_write(codec, 0x27, 0, | ||
702 | AC_VERB_SET_POWER_STATE, parm); | ||
703 | } | ||
704 | } else if (spec->codec_type == VT1718S) { | ||
705 | /* MUX6 (1eh) = stereo mixer */ | ||
706 | imux_is_smixer = snd_hda_codec_read( | ||
707 | codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; | ||
708 | /* inputs */ | ||
709 | /* PW 5/6/7 (29h/2ah/2bh) */ | ||
710 | parm = AC_PWRST_D3; | ||
711 | set_pin_power_state(codec, 0x29, &parm); | ||
712 | set_pin_power_state(codec, 0x2a, &parm); | ||
713 | set_pin_power_state(codec, 0x2b, &parm); | ||
714 | if (imux_is_smixer) | ||
715 | parm = AC_PWRST_D0; | ||
716 | /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */ | ||
717 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, | ||
718 | parm); | ||
719 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, | ||
720 | parm); | ||
721 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, | ||
722 | parm); | ||
723 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, | ||
724 | parm); | ||
725 | |||
726 | /* outputs */ | ||
727 | /* PW3 (27h), MW2 (1ah), AOW3 (bh) */ | ||
728 | parm = AC_PWRST_D3; | ||
729 | set_pin_power_state(codec, 0x27, &parm); | ||
730 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, | ||
731 | parm); | ||
732 | snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, | ||
733 | parm); | ||
734 | |||
735 | /* PW2 (26h), AOW2 (ah) */ | ||
736 | parm = AC_PWRST_D3; | ||
737 | set_pin_power_state(codec, 0x26, &parm); | ||
738 | snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, | ||
739 | parm); | ||
740 | |||
741 | /* PW0/1 (24h/25h) */ | ||
742 | parm = AC_PWRST_D3; | ||
743 | set_pin_power_state(codec, 0x24, &parm); | ||
744 | set_pin_power_state(codec, 0x25, &parm); | ||
745 | if (!spec->hp_independent_mode) /* check for redirected HP */ | ||
746 | set_pin_power_state(codec, 0x28, &parm); | ||
747 | snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, | ||
748 | parm); | ||
749 | snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, | ||
750 | parm); | ||
751 | /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ | ||
752 | snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE, | ||
753 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
754 | if (spec->hp_independent_mode) { | ||
755 | /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */ | ||
756 | parm = AC_PWRST_D3; | ||
757 | set_pin_power_state(codec, 0x28, &parm); | ||
758 | snd_hda_codec_write(codec, 0x1b, 0, | ||
759 | AC_VERB_SET_POWER_STATE, parm); | ||
760 | snd_hda_codec_write(codec, 0x34, 0, | ||
761 | AC_VERB_SET_POWER_STATE, parm); | ||
762 | snd_hda_codec_write(codec, 0xc, 0, | ||
763 | AC_VERB_SET_POWER_STATE, parm); | ||
764 | } | ||
765 | } else if (spec->codec_type == VT1716S) { | ||
766 | unsigned int mono_out, present; | ||
767 | /* SW0 (17h) = stereo mixer */ | ||
768 | imux_is_smixer = snd_hda_codec_read( | ||
769 | codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; | ||
770 | /* inputs */ | ||
771 | /* PW 1/2/5 (1ah/1bh/1eh) */ | ||
772 | parm = AC_PWRST_D3; | ||
773 | set_pin_power_state(codec, 0x1a, &parm); | ||
774 | set_pin_power_state(codec, 0x1b, &parm); | ||
775 | set_pin_power_state(codec, 0x1e, &parm); | ||
776 | if (imux_is_smixer) | ||
777 | parm = AC_PWRST_D0; | ||
778 | /* SW0 (17h), AIW0(13h) */ | ||
779 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, | ||
780 | parm); | ||
781 | snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, | ||
782 | parm); | ||
783 | |||
784 | parm = AC_PWRST_D3; | ||
785 | set_pin_power_state(codec, 0x1e, &parm); | ||
786 | /* PW11 (22h) */ | ||
787 | if (spec->dmic_enabled) | ||
788 | set_pin_power_state(codec, 0x22, &parm); | ||
789 | else | ||
790 | snd_hda_codec_write( | ||
791 | codec, 0x22, 0, | ||
792 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
793 | |||
794 | /* SW2(26h), AIW1(14h) */ | ||
795 | snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, | ||
796 | parm); | ||
797 | snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, | ||
798 | parm); | ||
799 | |||
800 | /* outputs */ | ||
801 | /* PW0 (19h), SW1 (18h), AOW1 (11h) */ | ||
802 | parm = AC_PWRST_D3; | ||
803 | set_pin_power_state(codec, 0x19, &parm); | ||
804 | /* Smart 5.1 PW2(1bh) */ | ||
805 | if (spec->smart51_enabled) | ||
806 | set_pin_power_state(codec, 0x1b, &parm); | ||
807 | snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, | ||
808 | parm); | ||
809 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, | ||
810 | parm); | ||
811 | |||
812 | /* PW7 (23h), SW3 (27h), AOW3 (25h) */ | ||
813 | parm = AC_PWRST_D3; | ||
814 | set_pin_power_state(codec, 0x23, &parm); | ||
815 | /* Smart 5.1 PW1(1ah) */ | ||
816 | if (spec->smart51_enabled) | ||
817 | set_pin_power_state(codec, 0x1a, &parm); | ||
818 | snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, | ||
819 | parm); | ||
820 | |||
821 | /* Smart 5.1 PW5(1eh) */ | ||
822 | if (spec->smart51_enabled) | ||
823 | set_pin_power_state(codec, 0x1e, &parm); | ||
824 | snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, | ||
825 | parm); | ||
826 | |||
827 | /* Mono out */ | ||
828 | /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/ | ||
829 | present = snd_hda_jack_detect(codec, 0x1c); | ||
830 | if (present) | ||
831 | mono_out = 0; | ||
832 | else { | ||
833 | present = snd_hda_jack_detect(codec, 0x1d); | ||
834 | if (!spec->hp_independent_mode && present) | ||
835 | mono_out = 0; | ||
836 | else | ||
837 | mono_out = 1; | ||
838 | } | ||
839 | parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3; | ||
840 | snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, | ||
841 | parm); | ||
842 | snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, | ||
843 | parm); | ||
844 | snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, | ||
845 | parm); | ||
846 | |||
847 | /* PW 3/4 (1ch/1dh) */ | ||
848 | parm = AC_PWRST_D3; | ||
849 | set_pin_power_state(codec, 0x1c, &parm); | ||
850 | set_pin_power_state(codec, 0x1d, &parm); | ||
851 | /* HP Independent Mode, power on AOW3 */ | ||
852 | if (spec->hp_independent_mode) | ||
853 | snd_hda_codec_write(codec, 0x25, 0, | ||
854 | AC_VERB_SET_POWER_STATE, parm); | ||
855 | |||
856 | /* force to D0 for internal Speaker */ | ||
857 | /* MW0 (16h), AOW0 (10h) */ | ||
858 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, | ||
859 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
860 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, | ||
861 | mono_out ? AC_PWRST_D0 : parm); | ||
862 | } else if (spec->codec_type == VT2002P) { | ||
863 | unsigned int present; | ||
864 | /* MUX9 (1eh) = stereo mixer */ | ||
865 | imux_is_smixer = snd_hda_codec_read( | ||
866 | codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3; | ||
867 | /* inputs */ | ||
868 | /* PW 5/6/7 (29h/2ah/2bh) */ | ||
869 | parm = AC_PWRST_D3; | ||
870 | set_pin_power_state(codec, 0x29, &parm); | ||
871 | set_pin_power_state(codec, 0x2a, &parm); | ||
872 | set_pin_power_state(codec, 0x2b, &parm); | ||
873 | if (imux_is_smixer) | ||
874 | parm = AC_PWRST_D0; | ||
875 | /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */ | ||
876 | snd_hda_codec_write(codec, 0x1e, 0, | ||
877 | AC_VERB_SET_POWER_STATE, parm); | ||
878 | snd_hda_codec_write(codec, 0x1f, 0, | ||
879 | AC_VERB_SET_POWER_STATE, parm); | ||
880 | snd_hda_codec_write(codec, 0x10, 0, | ||
881 | AC_VERB_SET_POWER_STATE, parm); | ||
882 | snd_hda_codec_write(codec, 0x11, 0, | ||
883 | AC_VERB_SET_POWER_STATE, parm); | ||
884 | |||
885 | /* outputs */ | ||
886 | /* AOW0 (8h)*/ | ||
887 | snd_hda_codec_write(codec, 0x8, 0, | ||
888 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
889 | |||
890 | /* PW4 (26h), MW4 (1ch), MUX4(37h) */ | ||
891 | parm = AC_PWRST_D3; | ||
892 | set_pin_power_state(codec, 0x26, &parm); | ||
893 | snd_hda_codec_write(codec, 0x1c, 0, | ||
894 | AC_VERB_SET_POWER_STATE, parm); | ||
895 | snd_hda_codec_write(codec, 0x37, | ||
896 | 0, AC_VERB_SET_POWER_STATE, parm); | ||
897 | |||
898 | /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */ | ||
899 | parm = AC_PWRST_D3; | ||
900 | set_pin_power_state(codec, 0x25, &parm); | ||
901 | snd_hda_codec_write(codec, 0x19, 0, | ||
902 | AC_VERB_SET_POWER_STATE, parm); | ||
903 | snd_hda_codec_write(codec, 0x35, 0, | ||
904 | AC_VERB_SET_POWER_STATE, parm); | ||
905 | if (spec->hp_independent_mode) { | ||
906 | snd_hda_codec_write(codec, 0x9, 0, | ||
907 | AC_VERB_SET_POWER_STATE, parm); | ||
908 | } | ||
909 | |||
910 | /* Class-D */ | ||
911 | /* PW0 (24h), MW0(18h), MUX0(34h) */ | ||
912 | present = snd_hda_jack_detect(codec, 0x25); | ||
913 | parm = AC_PWRST_D3; | ||
914 | set_pin_power_state(codec, 0x24, &parm); | ||
915 | if (present) { | ||
916 | snd_hda_codec_write( | ||
917 | codec, 0x18, 0, | ||
918 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
919 | snd_hda_codec_write( | ||
920 | codec, 0x34, 0, | ||
921 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
922 | } else { | ||
923 | snd_hda_codec_write( | ||
924 | codec, 0x18, 0, | ||
925 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
926 | snd_hda_codec_write( | ||
927 | codec, 0x34, 0, | ||
928 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
929 | } | ||
930 | |||
931 | /* Mono Out */ | ||
932 | /* PW15 (31h), MW8(17h), MUX8(3bh) */ | ||
933 | present = snd_hda_jack_detect(codec, 0x26); | ||
934 | parm = AC_PWRST_D3; | ||
935 | set_pin_power_state(codec, 0x31, &parm); | ||
936 | if (present) { | ||
937 | snd_hda_codec_write( | ||
938 | codec, 0x17, 0, | ||
939 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
940 | snd_hda_codec_write( | ||
941 | codec, 0x3b, 0, | ||
942 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
943 | } else { | ||
944 | snd_hda_codec_write( | ||
945 | codec, 0x17, 0, | ||
946 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
947 | snd_hda_codec_write( | ||
948 | codec, 0x3b, 0, | ||
949 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
950 | } | ||
951 | |||
952 | /* MW9 (21h) */ | ||
953 | if (imux_is_smixer || !is_aa_path_mute(codec)) | ||
954 | snd_hda_codec_write( | ||
955 | codec, 0x21, 0, | ||
956 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
957 | else | ||
958 | snd_hda_codec_write( | ||
959 | codec, 0x21, 0, | ||
960 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
961 | } else if (spec->codec_type == VT1812) { | ||
962 | unsigned int present; | ||
963 | /* MUX10 (1eh) = stereo mixer */ | ||
964 | imux_is_smixer = snd_hda_codec_read( | ||
965 | codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; | ||
966 | /* inputs */ | ||
967 | /* PW 5/6/7 (29h/2ah/2bh) */ | ||
968 | parm = AC_PWRST_D3; | ||
969 | set_pin_power_state(codec, 0x29, &parm); | ||
970 | set_pin_power_state(codec, 0x2a, &parm); | ||
971 | set_pin_power_state(codec, 0x2b, &parm); | ||
972 | if (imux_is_smixer) | ||
973 | parm = AC_PWRST_D0; | ||
974 | /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */ | ||
975 | snd_hda_codec_write(codec, 0x1e, 0, | ||
976 | AC_VERB_SET_POWER_STATE, parm); | ||
977 | snd_hda_codec_write(codec, 0x1f, 0, | ||
978 | AC_VERB_SET_POWER_STATE, parm); | ||
979 | snd_hda_codec_write(codec, 0x10, 0, | ||
980 | AC_VERB_SET_POWER_STATE, parm); | ||
981 | snd_hda_codec_write(codec, 0x11, 0, | ||
982 | AC_VERB_SET_POWER_STATE, parm); | ||
983 | |||
984 | /* outputs */ | ||
985 | /* AOW0 (8h)*/ | ||
986 | snd_hda_codec_write(codec, 0x8, 0, | ||
987 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
988 | |||
989 | /* PW4 (28h), MW4 (18h), MUX4(38h) */ | ||
990 | parm = AC_PWRST_D3; | ||
991 | set_pin_power_state(codec, 0x28, &parm); | ||
992 | snd_hda_codec_write(codec, 0x18, 0, | ||
993 | AC_VERB_SET_POWER_STATE, parm); | ||
994 | snd_hda_codec_write(codec, 0x38, 0, | ||
995 | AC_VERB_SET_POWER_STATE, parm); | ||
996 | |||
997 | /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ | ||
998 | parm = AC_PWRST_D3; | ||
999 | set_pin_power_state(codec, 0x25, &parm); | ||
1000 | snd_hda_codec_write(codec, 0x15, 0, | ||
1001 | AC_VERB_SET_POWER_STATE, parm); | ||
1002 | snd_hda_codec_write(codec, 0x35, 0, | ||
1003 | AC_VERB_SET_POWER_STATE, parm); | ||
1004 | if (spec->hp_independent_mode) { | ||
1005 | snd_hda_codec_write(codec, 0x9, 0, | ||
1006 | AC_VERB_SET_POWER_STATE, parm); | ||
1007 | } | ||
1008 | |||
1009 | /* Internal Speaker */ | ||
1010 | /* PW0 (24h), MW0(14h), MUX0(34h) */ | ||
1011 | present = snd_hda_jack_detect(codec, 0x25); | ||
1012 | parm = AC_PWRST_D3; | ||
1013 | set_pin_power_state(codec, 0x24, &parm); | ||
1014 | if (present) { | ||
1015 | snd_hda_codec_write(codec, 0x14, 0, | ||
1016 | AC_VERB_SET_POWER_STATE, | ||
1017 | AC_PWRST_D3); | ||
1018 | snd_hda_codec_write(codec, 0x34, 0, | ||
1019 | AC_VERB_SET_POWER_STATE, | ||
1020 | AC_PWRST_D3); | ||
1021 | } else { | ||
1022 | snd_hda_codec_write(codec, 0x14, 0, | ||
1023 | AC_VERB_SET_POWER_STATE, | ||
1024 | AC_PWRST_D0); | ||
1025 | snd_hda_codec_write(codec, 0x34, 0, | ||
1026 | AC_VERB_SET_POWER_STATE, | ||
1027 | AC_PWRST_D0); | ||
1028 | } | ||
1029 | /* Mono Out */ | ||
1030 | /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */ | ||
1031 | present = snd_hda_jack_detect(codec, 0x28); | ||
1032 | parm = AC_PWRST_D3; | ||
1033 | set_pin_power_state(codec, 0x31, &parm); | ||
1034 | if (present) { | ||
1035 | snd_hda_codec_write(codec, 0x1c, 0, | ||
1036 | AC_VERB_SET_POWER_STATE, | ||
1037 | AC_PWRST_D3); | ||
1038 | snd_hda_codec_write(codec, 0x3c, 0, | ||
1039 | AC_VERB_SET_POWER_STATE, | ||
1040 | AC_PWRST_D3); | ||
1041 | snd_hda_codec_write(codec, 0x3e, 0, | ||
1042 | AC_VERB_SET_POWER_STATE, | ||
1043 | AC_PWRST_D3); | ||
1044 | } else { | ||
1045 | snd_hda_codec_write(codec, 0x1c, 0, | ||
1046 | AC_VERB_SET_POWER_STATE, | ||
1047 | AC_PWRST_D0); | ||
1048 | snd_hda_codec_write(codec, 0x3c, 0, | ||
1049 | AC_VERB_SET_POWER_STATE, | ||
1050 | AC_PWRST_D0); | ||
1051 | snd_hda_codec_write(codec, 0x3e, 0, | ||
1052 | AC_VERB_SET_POWER_STATE, | ||
1053 | AC_PWRST_D0); | ||
1054 | } | ||
1055 | |||
1056 | /* PW15 (33h), MW15 (1dh), MUX15(3dh) */ | ||
1057 | parm = AC_PWRST_D3; | ||
1058 | set_pin_power_state(codec, 0x33, &parm); | ||
1059 | snd_hda_codec_write(codec, 0x1d, 0, | ||
1060 | AC_VERB_SET_POWER_STATE, parm); | ||
1061 | snd_hda_codec_write(codec, 0x3d, 0, | ||
1062 | AC_VERB_SET_POWER_STATE, parm); | ||
1063 | |||
1064 | /* MW9 (21h) */ | ||
1065 | if (imux_is_smixer || !is_aa_path_mute(codec)) | ||
1066 | snd_hda_codec_write( | ||
1067 | codec, 0x21, 0, | ||
1068 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
1069 | else | ||
1070 | snd_hda_codec_write( | ||
1071 | codec, 0x21, 0, | ||
1072 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | /* | 621 | /* |
1077 | * input MUX handling | 622 | * input MUX handling |
1078 | */ | 623 | */ |
@@ -1101,6 +646,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
1101 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 646 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1102 | struct via_spec *spec = codec->spec; | 647 | struct via_spec *spec = codec->spec; |
1103 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 648 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
649 | int ret; | ||
1104 | 650 | ||
1105 | if (!spec->mux_nids[adc_idx]) | 651 | if (!spec->mux_nids[adc_idx]) |
1106 | return -EINVAL; | 652 | return -EINVAL; |
@@ -1109,12 +655,14 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
1109 | AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0) | 655 | AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0) |
1110 | snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, | 656 | snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, |
1111 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | 657 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); |
1112 | /* update jack power state */ | ||
1113 | set_jack_power_state(codec); | ||
1114 | 658 | ||
1115 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | 659 | ret = snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, |
1116 | spec->mux_nids[adc_idx], | 660 | spec->mux_nids[adc_idx], |
1117 | &spec->cur_mux[adc_idx]); | 661 | &spec->cur_mux[adc_idx]); |
662 | /* update jack power state */ | ||
663 | set_widgets_power_state(codec); | ||
664 | |||
665 | return ret; | ||
1118 | } | 666 | } |
1119 | 667 | ||
1120 | static int via_independent_hp_info(struct snd_kcontrol *kcontrol, | 668 | static int via_independent_hp_info(struct snd_kcontrol *kcontrol, |
@@ -1160,6 +708,9 @@ static hda_nid_t side_mute_channel(struct via_spec *spec) | |||
1160 | case VT1709_10CH: return 0x29; | 708 | case VT1709_10CH: return 0x29; |
1161 | case VT1708B_8CH: /* fall thru */ | 709 | case VT1708B_8CH: /* fall thru */ |
1162 | case VT1708S: return 0x27; | 710 | case VT1708S: return 0x27; |
711 | case VT2002P: return 0x19; | ||
712 | case VT1802: return 0x15; | ||
713 | case VT1812: return 0x15; | ||
1163 | default: return 0; | 714 | default: return 0; |
1164 | } | 715 | } |
1165 | } | 716 | } |
@@ -1168,13 +719,22 @@ static int update_side_mute_status(struct hda_codec *codec) | |||
1168 | { | 719 | { |
1169 | /* mute side channel */ | 720 | /* mute side channel */ |
1170 | struct via_spec *spec = codec->spec; | 721 | struct via_spec *spec = codec->spec; |
1171 | unsigned int parm = spec->hp_independent_mode | 722 | unsigned int parm; |
1172 | ? AMP_OUT_MUTE : AMP_OUT_UNMUTE; | ||
1173 | hda_nid_t sw3 = side_mute_channel(spec); | 723 | hda_nid_t sw3 = side_mute_channel(spec); |
1174 | 724 | ||
1175 | if (sw3) | 725 | if (sw3) { |
1176 | snd_hda_codec_write(codec, sw3, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 726 | if (VT2002P_COMPATIBLE(spec)) |
1177 | parm); | 727 | parm = spec->hp_independent_mode ? |
728 | AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1); | ||
729 | else | ||
730 | parm = spec->hp_independent_mode ? | ||
731 | AMP_OUT_MUTE : AMP_OUT_UNMUTE; | ||
732 | snd_hda_codec_write(codec, sw3, 0, | ||
733 | AC_VERB_SET_AMP_GAIN_MUTE, parm); | ||
734 | if (spec->codec_type == VT1812) | ||
735 | snd_hda_codec_write(codec, 0x1d, 0, | ||
736 | AC_VERB_SET_AMP_GAIN_MUTE, parm); | ||
737 | } | ||
1178 | return 0; | 738 | return 0; |
1179 | } | 739 | } |
1180 | 740 | ||
@@ -1185,11 +745,30 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol, | |||
1185 | struct via_spec *spec = codec->spec; | 745 | struct via_spec *spec = codec->spec; |
1186 | hda_nid_t nid = kcontrol->private_value; | 746 | hda_nid_t nid = kcontrol->private_value; |
1187 | unsigned int pinsel = ucontrol->value.enumerated.item[0]; | 747 | unsigned int pinsel = ucontrol->value.enumerated.item[0]; |
748 | unsigned int parm0, parm1; | ||
1188 | /* Get Independent Mode index of headphone pin widget */ | 749 | /* Get Independent Mode index of headphone pin widget */ |
1189 | spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel | 750 | spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel |
1190 | ? 1 : 0; | 751 | ? 1 : 0; |
1191 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel); | 752 | if (spec->codec_type == VT1718S) { |
753 | snd_hda_codec_write(codec, nid, 0, | ||
754 | AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0); | ||
755 | /* Set correct mute switch for MW3 */ | ||
756 | parm0 = spec->hp_independent_mode ? | ||
757 | AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0); | ||
758 | parm1 = spec->hp_independent_mode ? | ||
759 | AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1); | ||
760 | snd_hda_codec_write(codec, 0x1b, 0, | ||
761 | AC_VERB_SET_AMP_GAIN_MUTE, parm0); | ||
762 | snd_hda_codec_write(codec, 0x1b, 0, | ||
763 | AC_VERB_SET_AMP_GAIN_MUTE, parm1); | ||
764 | } | ||
765 | else | ||
766 | snd_hda_codec_write(codec, nid, 0, | ||
767 | AC_VERB_SET_CONNECT_SEL, pinsel); | ||
1192 | 768 | ||
769 | if (spec->codec_type == VT1812) | ||
770 | snd_hda_codec_write(codec, 0x35, 0, | ||
771 | AC_VERB_SET_CONNECT_SEL, pinsel); | ||
1193 | if (spec->multiout.hp_nid && spec->multiout.hp_nid | 772 | if (spec->multiout.hp_nid && spec->multiout.hp_nid |
1194 | != spec->multiout.dac_nids[HDA_FRONT]) | 773 | != spec->multiout.dac_nids[HDA_FRONT]) |
1195 | snd_hda_codec_setup_stream(codec, spec->multiout.hp_nid, | 774 | snd_hda_codec_setup_stream(codec, spec->multiout.hp_nid, |
@@ -1201,17 +780,18 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol, | |||
1201 | || spec->codec_type == VT1702 | 780 | || spec->codec_type == VT1702 |
1202 | || spec->codec_type == VT1718S | 781 | || spec->codec_type == VT1718S |
1203 | || spec->codec_type == VT1716S | 782 | || spec->codec_type == VT1716S |
1204 | || spec->codec_type == VT2002P | 783 | || VT2002P_COMPATIBLE(spec)) { |
1205 | || spec->codec_type == VT1812) { | ||
1206 | activate_ctl(codec, "Headphone Playback Volume", | 784 | activate_ctl(codec, "Headphone Playback Volume", |
1207 | spec->hp_independent_mode); | 785 | spec->hp_independent_mode); |
1208 | activate_ctl(codec, "Headphone Playback Switch", | 786 | activate_ctl(codec, "Headphone Playback Switch", |
1209 | spec->hp_independent_mode); | 787 | spec->hp_independent_mode); |
1210 | } | 788 | } |
789 | /* update jack power state */ | ||
790 | set_widgets_power_state(codec); | ||
1211 | return 0; | 791 | return 0; |
1212 | } | 792 | } |
1213 | 793 | ||
1214 | static struct snd_kcontrol_new via_hp_mixer[2] = { | 794 | static const struct snd_kcontrol_new via_hp_mixer[2] = { |
1215 | { | 795 | { |
1216 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 796 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1217 | .name = "Independent HP", | 797 | .name = "Independent HP", |
@@ -1238,6 +818,7 @@ static int via_hp_build(struct hda_codec *codec) | |||
1238 | nid = 0x34; | 818 | nid = 0x34; |
1239 | break; | 819 | break; |
1240 | case VT2002P: | 820 | case VT2002P: |
821 | case VT1802: | ||
1241 | nid = 0x35; | 822 | nid = 0x35; |
1242 | break; | 823 | break; |
1243 | case VT1812: | 824 | case VT1812: |
@@ -1248,9 +829,12 @@ static int via_hp_build(struct hda_codec *codec) | |||
1248 | break; | 829 | break; |
1249 | } | 830 | } |
1250 | 831 | ||
1251 | nums = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS); | 832 | if (spec->codec_type != VT1708) { |
1252 | if (nums <= 1) | 833 | nums = snd_hda_get_connections(codec, nid, |
1253 | return 0; | 834 | conn, HDA_MAX_CONNECTIONS); |
835 | if (nums <= 1) | ||
836 | return 0; | ||
837 | } | ||
1254 | 838 | ||
1255 | knew = via_clone_control(spec, &via_hp_mixer[0]); | 839 | knew = via_clone_control(spec, &via_hp_mixer[0]); |
1256 | if (knew == NULL) | 840 | if (knew == NULL) |
@@ -1259,10 +843,13 @@ static int via_hp_build(struct hda_codec *codec) | |||
1259 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | 843 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; |
1260 | knew->private_value = nid; | 844 | knew->private_value = nid; |
1261 | 845 | ||
1262 | knew = via_clone_control(spec, &via_hp_mixer[1]); | 846 | nid = side_mute_channel(spec); |
1263 | if (knew == NULL) | 847 | if (nid) { |
1264 | return -ENOMEM; | 848 | knew = via_clone_control(spec, &via_hp_mixer[1]); |
1265 | knew->subdevice = side_mute_channel(spec); | 849 | if (knew == NULL) |
850 | return -ENOMEM; | ||
851 | knew->subdevice = nid; | ||
852 | } | ||
1266 | 853 | ||
1267 | return 0; | 854 | return 0; |
1268 | } | 855 | } |
@@ -1271,14 +858,18 @@ static void notify_aa_path_ctls(struct hda_codec *codec) | |||
1271 | { | 858 | { |
1272 | int i; | 859 | int i; |
1273 | struct snd_ctl_elem_id id; | 860 | struct snd_ctl_elem_id id; |
1274 | const char *labels[] = {"Mic", "Front Mic", "Line"}; | 861 | const char *labels[] = {"Mic", "Front Mic", "Line", "Rear Mic"}; |
862 | struct snd_kcontrol *ctl; | ||
1275 | 863 | ||
1276 | memset(&id, 0, sizeof(id)); | 864 | memset(&id, 0, sizeof(id)); |
1277 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 865 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
1278 | for (i = 0; i < ARRAY_SIZE(labels); i++) { | 866 | for (i = 0; i < ARRAY_SIZE(labels); i++) { |
1279 | sprintf(id.name, "%s Playback Volume", labels[i]); | 867 | sprintf(id.name, "%s Playback Volume", labels[i]); |
1280 | snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE, | 868 | ctl = snd_hda_find_mixer_ctl(codec, id.name); |
1281 | &id); | 869 | if (ctl) |
870 | snd_ctl_notify(codec->bus->card, | ||
871 | SNDRV_CTL_EVENT_MASK_VALUE, | ||
872 | &ctl->id); | ||
1282 | } | 873 | } |
1283 | } | 874 | } |
1284 | 875 | ||
@@ -1310,6 +901,11 @@ static void mute_aa_path(struct hda_codec *codec, int mute) | |||
1310 | start_idx = 2; | 901 | start_idx = 2; |
1311 | end_idx = 4; | 902 | end_idx = 4; |
1312 | break; | 903 | break; |
904 | case VT1718S: | ||
905 | nid_mixer = 0x21; | ||
906 | start_idx = 1; | ||
907 | end_idx = 3; | ||
908 | break; | ||
1313 | default: | 909 | default: |
1314 | return; | 910 | return; |
1315 | } | 911 | } |
@@ -1322,15 +918,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute) | |||
1322 | } | 918 | } |
1323 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) | 919 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) |
1324 | { | 920 | { |
1325 | int res = 0; | 921 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
1326 | int index; | 922 | int i; |
1327 | for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) { | 923 | |
1328 | if (pin == spec->autocfg.input_pins[index]) { | 924 | for (i = 0; i < cfg->num_inputs; i++) { |
1329 | res = 1; | 925 | if (pin == cfg->inputs[i].pin) |
1330 | break; | 926 | return cfg->inputs[i].type <= AUTO_PIN_LINE_IN; |
1331 | } | ||
1332 | } | 927 | } |
1333 | return res; | 928 | return 0; |
1334 | } | 929 | } |
1335 | 930 | ||
1336 | static int via_smart51_info(struct snd_kcontrol *kcontrol, | 931 | static int via_smart51_info(struct snd_kcontrol *kcontrol, |
@@ -1348,25 +943,21 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol, | |||
1348 | { | 943 | { |
1349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 944 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1350 | struct via_spec *spec = codec->spec; | 945 | struct via_spec *spec = codec->spec; |
1351 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | 946 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
1352 | int on = 1; | 947 | int on = 1; |
1353 | int i; | 948 | int i; |
1354 | 949 | ||
1355 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 950 | for (i = 0; i < cfg->num_inputs; i++) { |
1356 | hda_nid_t nid = spec->autocfg.input_pins[index[i]]; | 951 | hda_nid_t nid = cfg->inputs[i].pin; |
1357 | if (nid) { | 952 | int ctl = snd_hda_codec_read(codec, nid, 0, |
1358 | int ctl = | 953 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1359 | snd_hda_codec_read(codec, nid, 0, | 954 | if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) |
1360 | AC_VERB_GET_PIN_WIDGET_CONTROL, | 955 | continue; |
1361 | 0); | 956 | if (cfg->inputs[i].type == AUTO_PIN_MIC && |
1362 | if (i == AUTO_PIN_FRONT_MIC | 957 | spec->hp_independent_mode && spec->codec_type != VT1718S) |
1363 | && spec->hp_independent_mode | 958 | continue; /* ignore FMic for independent HP */ |
1364 | && spec->codec_type != VT1718S) | 959 | if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN)) |
1365 | continue; /* ignore FMic for independent HP */ | 960 | on = 0; |
1366 | if (ctl & AC_PINCTL_IN_EN | ||
1367 | && !(ctl & AC_PINCTL_OUT_EN)) | ||
1368 | on = 0; | ||
1369 | } | ||
1370 | } | 961 | } |
1371 | *ucontrol->value.integer.value = on; | 962 | *ucontrol->value.integer.value = on; |
1372 | return 0; | 963 | return 0; |
@@ -1377,36 +968,38 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, | |||
1377 | { | 968 | { |
1378 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 969 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1379 | struct via_spec *spec = codec->spec; | 970 | struct via_spec *spec = codec->spec; |
971 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1380 | int out_in = *ucontrol->value.integer.value | 972 | int out_in = *ucontrol->value.integer.value |
1381 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; | 973 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; |
1382 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | ||
1383 | int i; | 974 | int i; |
1384 | 975 | ||
1385 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 976 | for (i = 0; i < cfg->num_inputs; i++) { |
1386 | hda_nid_t nid = spec->autocfg.input_pins[index[i]]; | 977 | hda_nid_t nid = cfg->inputs[i].pin; |
1387 | if (i == AUTO_PIN_FRONT_MIC | 978 | unsigned int parm; |
1388 | && spec->hp_independent_mode | 979 | |
1389 | && spec->codec_type != VT1718S) | 980 | if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) |
981 | continue; | ||
982 | if (cfg->inputs[i].type == AUTO_PIN_MIC && | ||
983 | spec->hp_independent_mode && spec->codec_type != VT1718S) | ||
1390 | continue; /* don't retask FMic for independent HP */ | 984 | continue; /* don't retask FMic for independent HP */ |
1391 | if (nid) { | 985 | |
1392 | unsigned int parm = snd_hda_codec_read( | 986 | parm = snd_hda_codec_read(codec, nid, 0, |
1393 | codec, nid, 0, | 987 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1394 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 988 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
1395 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 989 | parm |= out_in; |
1396 | parm |= out_in; | 990 | snd_hda_codec_write(codec, nid, 0, |
1397 | snd_hda_codec_write(codec, nid, 0, | 991 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1398 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 992 | parm); |
1399 | parm); | 993 | if (out_in == AC_PINCTL_OUT_EN) { |
1400 | if (out_in == AC_PINCTL_OUT_EN) { | 994 | mute_aa_path(codec, 1); |
1401 | mute_aa_path(codec, 1); | 995 | notify_aa_path_ctls(codec); |
1402 | notify_aa_path_ctls(codec); | 996 | } |
1403 | } | 997 | if (spec->codec_type == VT1718S) { |
1404 | if (spec->codec_type == VT1718S) | 998 | snd_hda_codec_amp_stereo( |
1405 | snd_hda_codec_amp_stereo( | ||
1406 | codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, | 999 | codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, |
1407 | HDA_AMP_UNMUTE); | 1000 | HDA_AMP_UNMUTE); |
1408 | } | 1001 | } |
1409 | if (i == AUTO_PIN_FRONT_MIC) { | 1002 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { |
1410 | if (spec->codec_type == VT1708S | 1003 | if (spec->codec_type == VT1708S |
1411 | || spec->codec_type == VT1716S) { | 1004 | || spec->codec_type == VT1716S) { |
1412 | /* input = index 1 (AOW3) */ | 1005 | /* input = index 1 (AOW3) */ |
@@ -1420,11 +1013,11 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, | |||
1420 | } | 1013 | } |
1421 | } | 1014 | } |
1422 | spec->smart51_enabled = *ucontrol->value.integer.value; | 1015 | spec->smart51_enabled = *ucontrol->value.integer.value; |
1423 | set_jack_power_state(codec); | 1016 | set_widgets_power_state(codec); |
1424 | return 1; | 1017 | return 1; |
1425 | } | 1018 | } |
1426 | 1019 | ||
1427 | static struct snd_kcontrol_new via_smart51_mixer[2] = { | 1020 | static const struct snd_kcontrol_new via_smart51_mixer[2] = { |
1428 | { | 1021 | { |
1429 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1022 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1430 | .name = "Smart 5.1", | 1023 | .name = "Smart 5.1", |
@@ -1442,21 +1035,27 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = { | |||
1442 | static int via_smart51_build(struct via_spec *spec) | 1035 | static int via_smart51_build(struct via_spec *spec) |
1443 | { | 1036 | { |
1444 | struct snd_kcontrol_new *knew; | 1037 | struct snd_kcontrol_new *knew; |
1445 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | 1038 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
1446 | hda_nid_t nid; | 1039 | hda_nid_t nid; |
1447 | int i; | 1040 | int i; |
1448 | 1041 | ||
1042 | if (!cfg) | ||
1043 | return 0; | ||
1044 | if (cfg->line_outs > 2) | ||
1045 | return 0; | ||
1046 | |||
1449 | knew = via_clone_control(spec, &via_smart51_mixer[0]); | 1047 | knew = via_clone_control(spec, &via_smart51_mixer[0]); |
1450 | if (knew == NULL) | 1048 | if (knew == NULL) |
1451 | return -ENOMEM; | 1049 | return -ENOMEM; |
1452 | 1050 | ||
1453 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 1051 | for (i = 0; i < cfg->num_inputs; i++) { |
1454 | nid = spec->autocfg.input_pins[index[i]]; | 1052 | nid = cfg->inputs[i].pin; |
1455 | if (nid) { | 1053 | if (cfg->inputs[i].type <= AUTO_PIN_LINE_IN) { |
1456 | knew = via_clone_control(spec, &via_smart51_mixer[1]); | 1054 | knew = via_clone_control(spec, &via_smart51_mixer[1]); |
1457 | if (knew == NULL) | 1055 | if (knew == NULL) |
1458 | return -ENOMEM; | 1056 | return -ENOMEM; |
1459 | knew->subdevice = nid; | 1057 | knew->subdevice = nid; |
1058 | break; | ||
1460 | } | 1059 | } |
1461 | } | 1060 | } |
1462 | 1061 | ||
@@ -1464,7 +1063,7 @@ static int via_smart51_build(struct via_spec *spec) | |||
1464 | } | 1063 | } |
1465 | 1064 | ||
1466 | /* capture mixer elements */ | 1065 | /* capture mixer elements */ |
1467 | static struct snd_kcontrol_new vt1708_capture_mixer[] = { | 1066 | static const struct snd_kcontrol_new vt1708_capture_mixer[] = { |
1468 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT), | 1067 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT), |
1469 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT), | 1068 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT), |
1470 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT), | 1069 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT), |
@@ -1515,6 +1114,7 @@ static int is_aa_path_mute(struct hda_codec *codec) | |||
1515 | break; | 1114 | break; |
1516 | case VT2002P: | 1115 | case VT2002P: |
1517 | case VT1812: | 1116 | case VT1812: |
1117 | case VT1802: | ||
1518 | nid_mixer = 0x21; | 1118 | nid_mixer = 0x21; |
1519 | start_idx = 0; | 1119 | start_idx = 0; |
1520 | end_idx = 2; | 1120 | end_idx = 2; |
@@ -1579,6 +1179,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle) | |||
1579 | break; | 1179 | break; |
1580 | case VT2002P: | 1180 | case VT2002P: |
1581 | case VT1812: | 1181 | case VT1812: |
1182 | case VT1802: | ||
1582 | verb = 0xf93; | 1183 | verb = 0xf93; |
1583 | parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */ | 1184 | parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */ |
1584 | break; | 1185 | break; |
@@ -1592,7 +1193,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle) | |||
1592 | /* | 1193 | /* |
1593 | * generic initialization of ADC, input mixers and output mixers | 1194 | * generic initialization of ADC, input mixers and output mixers |
1594 | */ | 1195 | */ |
1595 | static struct hda_verb vt1708_volume_init_verbs[] = { | 1196 | static const struct hda_verb vt1708_volume_init_verbs[] = { |
1596 | /* | 1197 | /* |
1597 | * Unmute ADC0-1 and set the default input to mic-in | 1198 | * Unmute ADC0-1 and set the default input to mic-in |
1598 | */ | 1199 | */ |
@@ -1622,6 +1223,8 @@ static struct hda_verb vt1708_volume_init_verbs[] = { | |||
1622 | {0x20, AC_VERB_SET_CONNECT_SEL, 0}, | 1223 | {0x20, AC_VERB_SET_CONNECT_SEL, 0}, |
1623 | /* PW9 Output enable */ | 1224 | /* PW9 Output enable */ |
1624 | {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 1225 | {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, |
1226 | /* power down jack detect function */ | ||
1227 | {0x1, 0xf81, 0x1}, | ||
1625 | { } | 1228 | { } |
1626 | }; | 1229 | }; |
1627 | 1230 | ||
@@ -1644,7 +1247,7 @@ static void playback_multi_pcm_prep_0(struct hda_codec *codec, | |||
1644 | { | 1247 | { |
1645 | struct via_spec *spec = codec->spec; | 1248 | struct via_spec *spec = codec->spec; |
1646 | struct hda_multi_out *mout = &spec->multiout; | 1249 | struct hda_multi_out *mout = &spec->multiout; |
1647 | hda_nid_t *nids = mout->dac_nids; | 1250 | const hda_nid_t *nids = mout->dac_nids; |
1648 | int chs = substream->runtime->channels; | 1251 | int chs = substream->runtime->channels; |
1649 | int i; | 1252 | int i; |
1650 | 1253 | ||
@@ -1713,7 +1316,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1713 | { | 1316 | { |
1714 | struct via_spec *spec = codec->spec; | 1317 | struct via_spec *spec = codec->spec; |
1715 | struct hda_multi_out *mout = &spec->multiout; | 1318 | struct hda_multi_out *mout = &spec->multiout; |
1716 | hda_nid_t *nids = mout->dac_nids; | 1319 | const hda_nid_t *nids = mout->dac_nids; |
1717 | 1320 | ||
1718 | if (substream->number == 0) | 1321 | if (substream->number == 0) |
1719 | playback_multi_pcm_prep_0(codec, stream_tag, format, | 1322 | playback_multi_pcm_prep_0(codec, stream_tag, format, |
@@ -1734,7 +1337,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
1734 | { | 1337 | { |
1735 | struct via_spec *spec = codec->spec; | 1338 | struct via_spec *spec = codec->spec; |
1736 | struct hda_multi_out *mout = &spec->multiout; | 1339 | struct hda_multi_out *mout = &spec->multiout; |
1737 | hda_nid_t *nids = mout->dac_nids; | 1340 | const hda_nid_t *nids = mout->dac_nids; |
1738 | int i; | 1341 | int i; |
1739 | 1342 | ||
1740 | if (substream->number == 0) { | 1343 | if (substream->number == 0) { |
@@ -1832,7 +1435,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
1832 | return 0; | 1435 | return 0; |
1833 | } | 1436 | } |
1834 | 1437 | ||
1835 | static struct hda_pcm_stream vt1708_pcm_analog_playback = { | 1438 | static const struct hda_pcm_stream vt1708_pcm_analog_playback = { |
1836 | .substreams = 2, | 1439 | .substreams = 2, |
1837 | .channels_min = 2, | 1440 | .channels_min = 2, |
1838 | .channels_max = 8, | 1441 | .channels_max = 8, |
@@ -1844,7 +1447,7 @@ static struct hda_pcm_stream vt1708_pcm_analog_playback = { | |||
1844 | }, | 1447 | }, |
1845 | }; | 1448 | }; |
1846 | 1449 | ||
1847 | static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { | 1450 | static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { |
1848 | .substreams = 2, | 1451 | .substreams = 2, |
1849 | .channels_min = 2, | 1452 | .channels_min = 2, |
1850 | .channels_max = 8, | 1453 | .channels_max = 8, |
@@ -1861,7 +1464,7 @@ static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { | |||
1861 | }, | 1464 | }, |
1862 | }; | 1465 | }; |
1863 | 1466 | ||
1864 | static struct hda_pcm_stream vt1708_pcm_analog_capture = { | 1467 | static const struct hda_pcm_stream vt1708_pcm_analog_capture = { |
1865 | .substreams = 2, | 1468 | .substreams = 2, |
1866 | .channels_min = 2, | 1469 | .channels_min = 2, |
1867 | .channels_max = 2, | 1470 | .channels_max = 2, |
@@ -1872,7 +1475,7 @@ static struct hda_pcm_stream vt1708_pcm_analog_capture = { | |||
1872 | }, | 1475 | }, |
1873 | }; | 1476 | }; |
1874 | 1477 | ||
1875 | static struct hda_pcm_stream vt1708_pcm_digital_playback = { | 1478 | static const struct hda_pcm_stream vt1708_pcm_digital_playback = { |
1876 | .substreams = 1, | 1479 | .substreams = 1, |
1877 | .channels_min = 2, | 1480 | .channels_min = 2, |
1878 | .channels_max = 2, | 1481 | .channels_max = 2, |
@@ -1885,7 +1488,7 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = { | |||
1885 | }, | 1488 | }, |
1886 | }; | 1489 | }; |
1887 | 1490 | ||
1888 | static struct hda_pcm_stream vt1708_pcm_digital_capture = { | 1491 | static const struct hda_pcm_stream vt1708_pcm_digital_capture = { |
1889 | .substreams = 1, | 1492 | .substreams = 1, |
1890 | .channels_min = 2, | 1493 | .channels_min = 2, |
1891 | .channels_max = 2, | 1494 | .channels_max = 2, |
@@ -1895,7 +1498,7 @@ static int via_build_controls(struct hda_codec *codec) | |||
1895 | { | 1498 | { |
1896 | struct via_spec *spec = codec->spec; | 1499 | struct via_spec *spec = codec->spec; |
1897 | struct snd_kcontrol *kctl; | 1500 | struct snd_kcontrol *kctl; |
1898 | struct snd_kcontrol_new *knew; | 1501 | const struct snd_kcontrol_new *knew; |
1899 | int err, i; | 1502 | int err, i; |
1900 | 1503 | ||
1901 | for (i = 0; i < spec->num_mixers; i++) { | 1504 | for (i = 0; i < spec->num_mixers; i++) { |
@@ -1943,7 +1546,7 @@ static int via_build_controls(struct hda_codec *codec) | |||
1943 | } | 1546 | } |
1944 | 1547 | ||
1945 | /* init power states */ | 1548 | /* init power states */ |
1946 | set_jack_power_state(codec); | 1549 | set_widgets_power_state(codec); |
1947 | analog_low_current_mode(codec, 1); | 1550 | analog_low_current_mode(codec, 1); |
1948 | 1551 | ||
1949 | via_free_kctls(codec); /* no longer needed */ | 1552 | via_free_kctls(codec); /* no longer needed */ |
@@ -2107,7 +1710,7 @@ static void via_speaker_automute(struct hda_codec *codec) | |||
2107 | unsigned int hp_present; | 1710 | unsigned int hp_present; |
2108 | struct via_spec *spec = codec->spec; | 1711 | struct via_spec *spec = codec->spec; |
2109 | 1712 | ||
2110 | if (spec->codec_type != VT2002P && spec->codec_type != VT1812) | 1713 | if (!VT2002P_COMPATIBLE(spec)) |
2111 | return; | 1714 | return; |
2112 | 1715 | ||
2113 | hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); | 1716 | hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); |
@@ -2166,17 +1769,21 @@ static void via_unsol_event(struct hda_codec *codec, | |||
2166 | unsigned int res) | 1769 | unsigned int res) |
2167 | { | 1770 | { |
2168 | res >>= 26; | 1771 | res >>= 26; |
2169 | if (res & VIA_HP_EVENT) | 1772 | |
1773 | if (res & VIA_JACK_EVENT) | ||
1774 | set_widgets_power_state(codec); | ||
1775 | |||
1776 | res &= ~VIA_JACK_EVENT; | ||
1777 | |||
1778 | if (res == VIA_HP_EVENT) | ||
2170 | via_hp_automute(codec); | 1779 | via_hp_automute(codec); |
2171 | if (res & VIA_GPIO_EVENT) | 1780 | else if (res == VIA_GPIO_EVENT) |
2172 | via_gpio_control(codec); | 1781 | via_gpio_control(codec); |
2173 | if (res & VIA_JACK_EVENT) | 1782 | else if (res == VIA_MONO_EVENT) |
2174 | set_jack_power_state(codec); | ||
2175 | if (res & VIA_MONO_EVENT) | ||
2176 | via_mono_automute(codec); | 1783 | via_mono_automute(codec); |
2177 | if (res & VIA_SPEAKER_EVENT) | 1784 | else if (res == VIA_SPEAKER_EVENT) |
2178 | via_speaker_automute(codec); | 1785 | via_speaker_automute(codec); |
2179 | if (res & VIA_BIND_HP_EVENT) | 1786 | else if (res == VIA_BIND_HP_EVENT) |
2180 | via_hp_bind_automute(codec); | 1787 | via_hp_bind_automute(codec); |
2181 | } | 1788 | } |
2182 | 1789 | ||
@@ -2187,10 +1794,6 @@ static int via_init(struct hda_codec *codec) | |||
2187 | for (i = 0; i < spec->num_iverbs; i++) | 1794 | for (i = 0; i < spec->num_iverbs; i++) |
2188 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 1795 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
2189 | 1796 | ||
2190 | spec->codec_type = get_codec_type(codec); | ||
2191 | if (spec->codec_type == VT1708BCE) | ||
2192 | spec->codec_type = VT1708S; /* VT1708BCE & VT1708S are almost | ||
2193 | same */ | ||
2194 | /* Lydia Add for EAPD enable */ | 1797 | /* Lydia Add for EAPD enable */ |
2195 | if (!spec->dig_in_nid) { /* No Digital In connection */ | 1798 | if (!spec->dig_in_nid) { /* No Digital In connection */ |
2196 | if (spec->dig_in_pin) { | 1799 | if (spec->dig_in_pin) { |
@@ -2230,7 +1833,7 @@ static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) | |||
2230 | 1833 | ||
2231 | /* | 1834 | /* |
2232 | */ | 1835 | */ |
2233 | static struct hda_codec_ops via_patch_ops = { | 1836 | static const struct hda_codec_ops via_patch_ops = { |
2234 | .build_controls = via_build_controls, | 1837 | .build_controls = via_build_controls, |
2235 | .build_pcms = via_build_pcms, | 1838 | .build_pcms = via_build_pcms, |
2236 | .init = via_init, | 1839 | .init = via_init, |
@@ -2260,16 +1863,16 @@ static int vt1708_auto_fill_dac_nids(struct via_spec *spec, | |||
2260 | /* config dac list */ | 1863 | /* config dac list */ |
2261 | switch (i) { | 1864 | switch (i) { |
2262 | case AUTO_SEQ_FRONT: | 1865 | case AUTO_SEQ_FRONT: |
2263 | spec->multiout.dac_nids[i] = 0x10; | 1866 | spec->private_dac_nids[i] = 0x10; |
2264 | break; | 1867 | break; |
2265 | case AUTO_SEQ_CENLFE: | 1868 | case AUTO_SEQ_CENLFE: |
2266 | spec->multiout.dac_nids[i] = 0x12; | 1869 | spec->private_dac_nids[i] = 0x12; |
2267 | break; | 1870 | break; |
2268 | case AUTO_SEQ_SURROUND: | 1871 | case AUTO_SEQ_SURROUND: |
2269 | spec->multiout.dac_nids[i] = 0x11; | 1872 | spec->private_dac_nids[i] = 0x11; |
2270 | break; | 1873 | break; |
2271 | case AUTO_SEQ_SIDE: | 1874 | case AUTO_SEQ_SIDE: |
2272 | spec->multiout.dac_nids[i] = 0x13; | 1875 | spec->private_dac_nids[i] = 0x13; |
2273 | break; | 1876 | break; |
2274 | } | 1877 | } |
2275 | } | 1878 | } |
@@ -2283,7 +1886,9 @@ static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec, | |||
2283 | const struct auto_pin_cfg *cfg) | 1886 | const struct auto_pin_cfg *cfg) |
2284 | { | 1887 | { |
2285 | char name[32]; | 1888 | char name[32]; |
2286 | static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; | 1889 | static const char * const chname[4] = { |
1890 | "Front", "Surround", "C/LFE", "Side" | ||
1891 | }; | ||
2287 | hda_nid_t nid, nid_vol, nid_vols[] = {0x17, 0x19, 0x1a, 0x1b}; | 1892 | hda_nid_t nid, nid_vol, nid_vols[] = {0x17, 0x19, 0x1a, 0x1b}; |
2288 | int i, err; | 1893 | int i, err; |
2289 | 1894 | ||
@@ -2372,16 +1977,11 @@ static void create_hp_imux(struct via_spec *spec) | |||
2372 | { | 1977 | { |
2373 | int i; | 1978 | int i; |
2374 | struct hda_input_mux *imux = &spec->private_imux[1]; | 1979 | struct hda_input_mux *imux = &spec->private_imux[1]; |
2375 | static const char *texts[] = { "OFF", "ON", NULL}; | 1980 | static const char * const texts[] = { "OFF", "ON", NULL}; |
2376 | 1981 | ||
2377 | /* for hp mode select */ | 1982 | /* for hp mode select */ |
2378 | i = 0; | 1983 | for (i = 0; texts[i]; i++) |
2379 | while (texts[i] != NULL) { | 1984 | snd_hda_add_imux_item(imux, texts[i], i, NULL); |
2380 | imux->items[imux->num_items].label = texts[i]; | ||
2381 | imux->items[imux->num_items].index = i; | ||
2382 | imux->num_items++; | ||
2383 | i++; | ||
2384 | } | ||
2385 | 1985 | ||
2386 | spec->hp_mux = &spec->private_imux[1]; | 1986 | spec->hp_mux = &spec->private_imux[1]; |
2387 | } | 1987 | } |
@@ -2413,53 +2013,63 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
2413 | } | 2013 | } |
2414 | 2014 | ||
2415 | /* create playback/capture controls for input pins */ | 2015 | /* create playback/capture controls for input pins */ |
2416 | static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, | 2016 | static int vt_auto_create_analog_input_ctls(struct hda_codec *codec, |
2417 | const struct auto_pin_cfg *cfg) | 2017 | const struct auto_pin_cfg *cfg, |
2018 | hda_nid_t cap_nid, | ||
2019 | const hda_nid_t pin_idxs[], | ||
2020 | int num_idxs) | ||
2418 | { | 2021 | { |
2419 | static char *labels[] = { | 2022 | struct via_spec *spec = codec->spec; |
2420 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
2421 | }; | ||
2422 | struct hda_input_mux *imux = &spec->private_imux[0]; | 2023 | struct hda_input_mux *imux = &spec->private_imux[0]; |
2423 | int i, err, idx = 0; | 2024 | int i, err, idx, type, type_idx = 0; |
2424 | 2025 | ||
2425 | /* for internal loopback recording select */ | 2026 | /* for internal loopback recording select */ |
2426 | imux->items[imux->num_items].label = "Stereo Mixer"; | 2027 | for (idx = 0; idx < num_idxs; idx++) { |
2427 | imux->items[imux->num_items].index = idx; | 2028 | if (pin_idxs[idx] == 0xff) { |
2428 | imux->num_items++; | 2029 | snd_hda_add_imux_item(imux, "Stereo Mixer", idx, NULL); |
2429 | |||
2430 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
2431 | if (!cfg->input_pins[i]) | ||
2432 | continue; | ||
2433 | |||
2434 | switch (cfg->input_pins[i]) { | ||
2435 | case 0x1d: /* Mic */ | ||
2436 | idx = 2; | ||
2437 | break; | ||
2438 | |||
2439 | case 0x1e: /* Line In */ | ||
2440 | idx = 3; | ||
2441 | break; | ||
2442 | |||
2443 | case 0x21: /* Front Mic */ | ||
2444 | idx = 4; | ||
2445 | break; | ||
2446 | |||
2447 | case 0x24: /* CD */ | ||
2448 | idx = 1; | ||
2449 | break; | 2030 | break; |
2450 | } | 2031 | } |
2451 | err = via_new_analog_input(spec, labels[i], idx, 0x17); | 2032 | } |
2033 | |||
2034 | for (i = 0; i < cfg->num_inputs; i++) { | ||
2035 | const char *label; | ||
2036 | type = cfg->inputs[i].type; | ||
2037 | for (idx = 0; idx < num_idxs; idx++) | ||
2038 | if (pin_idxs[idx] == cfg->inputs[i].pin) | ||
2039 | break; | ||
2040 | if (idx >= num_idxs) | ||
2041 | continue; | ||
2042 | if (i > 0 && type == cfg->inputs[i - 1].type) | ||
2043 | type_idx++; | ||
2044 | else | ||
2045 | type_idx = 0; | ||
2046 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
2047 | if (spec->codec_type == VT1708S || | ||
2048 | spec->codec_type == VT1702 || | ||
2049 | spec->codec_type == VT1716S) | ||
2050 | err = via_new_analog_input(spec, label, type_idx, | ||
2051 | idx+1, cap_nid); | ||
2052 | else | ||
2053 | err = via_new_analog_input(spec, label, type_idx, | ||
2054 | idx, cap_nid); | ||
2452 | if (err < 0) | 2055 | if (err < 0) |
2453 | return err; | 2056 | return err; |
2454 | imux->items[imux->num_items].label = labels[i]; | 2057 | snd_hda_add_imux_item(imux, label, idx, NULL); |
2455 | imux->items[imux->num_items].index = idx; | ||
2456 | imux->num_items++; | ||
2457 | } | 2058 | } |
2458 | return 0; | 2059 | return 0; |
2459 | } | 2060 | } |
2460 | 2061 | ||
2062 | /* create playback/capture controls for input pins */ | ||
2063 | static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec, | ||
2064 | const struct auto_pin_cfg *cfg) | ||
2065 | { | ||
2066 | static const hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 }; | ||
2067 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs, | ||
2068 | ARRAY_SIZE(pin_idxs)); | ||
2069 | } | ||
2070 | |||
2461 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2071 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
2462 | static struct hda_amp_list vt1708_loopbacks[] = { | 2072 | static const struct hda_amp_list vt1708_loopbacks[] = { |
2463 | { 0x17, HDA_INPUT, 1 }, | 2073 | { 0x17, HDA_INPUT, 1 }, |
2464 | { 0x17, HDA_INPUT, 2 }, | 2074 | { 0x17, HDA_INPUT, 2 }, |
2465 | { 0x17, HDA_INPUT, 3 }, | 2075 | { 0x17, HDA_INPUT, 3 }, |
@@ -2518,7 +2128,7 @@ static int vt1708_jack_detectect_put(struct snd_kcontrol *kcontrol, | |||
2518 | return change; | 2128 | return change; |
2519 | } | 2129 | } |
2520 | 2130 | ||
2521 | static struct snd_kcontrol_new vt1708_jack_detectect[] = { | 2131 | static const struct snd_kcontrol_new vt1708_jack_detectect[] = { |
2522 | { | 2132 | { |
2523 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2133 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2524 | .name = "Jack Detect", | 2134 | .name = "Jack Detect", |
@@ -2554,7 +2164,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
2554 | err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 2164 | err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
2555 | if (err < 0) | 2165 | if (err < 0) |
2556 | return err; | 2166 | return err; |
2557 | err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg); | 2167 | err = vt1708_auto_create_analog_input_ctls(codec, &spec->autocfg); |
2558 | if (err < 0) | 2168 | if (err < 0) |
2559 | return err; | 2169 | return err; |
2560 | /* add jack detect on/off control */ | 2170 | /* add jack detect on/off control */ |
@@ -2593,7 +2203,8 @@ static int via_auto_init(struct hda_codec *codec) | |||
2593 | via_auto_init_multi_out(codec); | 2203 | via_auto_init_multi_out(codec); |
2594 | via_auto_init_hp_out(codec); | 2204 | via_auto_init_hp_out(codec); |
2595 | via_auto_init_analog_input(codec); | 2205 | via_auto_init_analog_input(codec); |
2596 | if (spec->codec_type == VT2002P || spec->codec_type == VT1812) { | 2206 | |
2207 | if (VT2002P_COMPATIBLE(spec)) { | ||
2597 | via_hp_bind_automute(codec); | 2208 | via_hp_bind_automute(codec); |
2598 | } else { | 2209 | } else { |
2599 | via_hp_automute(codec); | 2210 | via_hp_automute(codec); |
@@ -2697,7 +2308,7 @@ static int patch_vt1708(struct hda_codec *codec) | |||
2697 | } | 2308 | } |
2698 | 2309 | ||
2699 | /* capture mixer elements */ | 2310 | /* capture mixer elements */ |
2700 | static struct snd_kcontrol_new vt1709_capture_mixer[] = { | 2311 | static const struct snd_kcontrol_new vt1709_capture_mixer[] = { |
2701 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT), | 2312 | HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT), |
2702 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT), | 2313 | HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT), |
2703 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT), | 2314 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT), |
@@ -2719,7 +2330,7 @@ static struct snd_kcontrol_new vt1709_capture_mixer[] = { | |||
2719 | { } /* end */ | 2330 | { } /* end */ |
2720 | }; | 2331 | }; |
2721 | 2332 | ||
2722 | static struct hda_verb vt1709_uniwill_init_verbs[] = { | 2333 | static const struct hda_verb vt1709_uniwill_init_verbs[] = { |
2723 | {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, | 2334 | {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, |
2724 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, | 2335 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, |
2725 | { } | 2336 | { } |
@@ -2728,7 +2339,7 @@ static struct hda_verb vt1709_uniwill_init_verbs[] = { | |||
2728 | /* | 2339 | /* |
2729 | * generic initialization of ADC, input mixers and output mixers | 2340 | * generic initialization of ADC, input mixers and output mixers |
2730 | */ | 2341 | */ |
2731 | static struct hda_verb vt1709_10ch_volume_init_verbs[] = { | 2342 | static const struct hda_verb vt1709_10ch_volume_init_verbs[] = { |
2732 | /* | 2343 | /* |
2733 | * Unmute ADC0-2 and set the default input to mic-in | 2344 | * Unmute ADC0-2 and set the default input to mic-in |
2734 | */ | 2345 | */ |
@@ -2768,7 +2379,7 @@ static struct hda_verb vt1709_10ch_volume_init_verbs[] = { | |||
2768 | { } | 2379 | { } |
2769 | }; | 2380 | }; |
2770 | 2381 | ||
2771 | static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = { | 2382 | static const struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = { |
2772 | .substreams = 1, | 2383 | .substreams = 1, |
2773 | .channels_min = 2, | 2384 | .channels_min = 2, |
2774 | .channels_max = 10, | 2385 | .channels_max = 10, |
@@ -2780,7 +2391,7 @@ static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = { | |||
2780 | }, | 2391 | }, |
2781 | }; | 2392 | }; |
2782 | 2393 | ||
2783 | static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = { | 2394 | static const struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = { |
2784 | .substreams = 1, | 2395 | .substreams = 1, |
2785 | .channels_min = 2, | 2396 | .channels_min = 2, |
2786 | .channels_max = 6, | 2397 | .channels_max = 6, |
@@ -2792,7 +2403,7 @@ static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = { | |||
2792 | }, | 2403 | }, |
2793 | }; | 2404 | }; |
2794 | 2405 | ||
2795 | static struct hda_pcm_stream vt1709_pcm_analog_capture = { | 2406 | static const struct hda_pcm_stream vt1709_pcm_analog_capture = { |
2796 | .substreams = 2, | 2407 | .substreams = 2, |
2797 | .channels_min = 2, | 2408 | .channels_min = 2, |
2798 | .channels_max = 2, | 2409 | .channels_max = 2, |
@@ -2803,7 +2414,7 @@ static struct hda_pcm_stream vt1709_pcm_analog_capture = { | |||
2803 | }, | 2414 | }, |
2804 | }; | 2415 | }; |
2805 | 2416 | ||
2806 | static struct hda_pcm_stream vt1709_pcm_digital_playback = { | 2417 | static const struct hda_pcm_stream vt1709_pcm_digital_playback = { |
2807 | .substreams = 1, | 2418 | .substreams = 1, |
2808 | .channels_min = 2, | 2419 | .channels_min = 2, |
2809 | .channels_max = 2, | 2420 | .channels_max = 2, |
@@ -2814,7 +2425,7 @@ static struct hda_pcm_stream vt1709_pcm_digital_playback = { | |||
2814 | }, | 2425 | }, |
2815 | }; | 2426 | }; |
2816 | 2427 | ||
2817 | static struct hda_pcm_stream vt1709_pcm_digital_capture = { | 2428 | static const struct hda_pcm_stream vt1709_pcm_digital_capture = { |
2818 | .substreams = 1, | 2429 | .substreams = 1, |
2819 | .channels_min = 2, | 2430 | .channels_min = 2, |
2820 | .channels_max = 2, | 2431 | .channels_max = 2, |
@@ -2841,26 +2452,26 @@ static int vt1709_auto_fill_dac_nids(struct via_spec *spec, | |||
2841 | switch (i) { | 2452 | switch (i) { |
2842 | case AUTO_SEQ_FRONT: | 2453 | case AUTO_SEQ_FRONT: |
2843 | /* AOW0 */ | 2454 | /* AOW0 */ |
2844 | spec->multiout.dac_nids[i] = 0x10; | 2455 | spec->private_dac_nids[i] = 0x10; |
2845 | break; | 2456 | break; |
2846 | case AUTO_SEQ_CENLFE: | 2457 | case AUTO_SEQ_CENLFE: |
2847 | /* AOW2 */ | 2458 | /* AOW2 */ |
2848 | spec->multiout.dac_nids[i] = 0x12; | 2459 | spec->private_dac_nids[i] = 0x12; |
2849 | break; | 2460 | break; |
2850 | case AUTO_SEQ_SURROUND: | 2461 | case AUTO_SEQ_SURROUND: |
2851 | /* AOW3 */ | 2462 | /* AOW3 */ |
2852 | spec->multiout.dac_nids[i] = 0x11; | 2463 | spec->private_dac_nids[i] = 0x11; |
2853 | break; | 2464 | break; |
2854 | case AUTO_SEQ_SIDE: | 2465 | case AUTO_SEQ_SIDE: |
2855 | /* AOW1 */ | 2466 | /* AOW1 */ |
2856 | spec->multiout.dac_nids[i] = 0x27; | 2467 | spec->private_dac_nids[i] = 0x27; |
2857 | break; | 2468 | break; |
2858 | default: | 2469 | default: |
2859 | break; | 2470 | break; |
2860 | } | 2471 | } |
2861 | } | 2472 | } |
2862 | } | 2473 | } |
2863 | spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */ | 2474 | spec->private_dac_nids[cfg->line_outs] = 0x28; /* AOW4 */ |
2864 | 2475 | ||
2865 | } else if (cfg->line_outs == 3) { /* 6 channels */ | 2476 | } else if (cfg->line_outs == 3) { /* 6 channels */ |
2866 | for (i = 0; i < cfg->line_outs; i++) { | 2477 | for (i = 0; i < cfg->line_outs; i++) { |
@@ -2870,15 +2481,15 @@ static int vt1709_auto_fill_dac_nids(struct via_spec *spec, | |||
2870 | switch (i) { | 2481 | switch (i) { |
2871 | case AUTO_SEQ_FRONT: | 2482 | case AUTO_SEQ_FRONT: |
2872 | /* AOW0 */ | 2483 | /* AOW0 */ |
2873 | spec->multiout.dac_nids[i] = 0x10; | 2484 | spec->private_dac_nids[i] = 0x10; |
2874 | break; | 2485 | break; |
2875 | case AUTO_SEQ_CENLFE: | 2486 | case AUTO_SEQ_CENLFE: |
2876 | /* AOW2 */ | 2487 | /* AOW2 */ |
2877 | spec->multiout.dac_nids[i] = 0x12; | 2488 | spec->private_dac_nids[i] = 0x12; |
2878 | break; | 2489 | break; |
2879 | case AUTO_SEQ_SURROUND: | 2490 | case AUTO_SEQ_SURROUND: |
2880 | /* AOW1 */ | 2491 | /* AOW1 */ |
2881 | spec->multiout.dac_nids[i] = 0x11; | 2492 | spec->private_dac_nids[i] = 0x11; |
2882 | break; | 2493 | break; |
2883 | default: | 2494 | default: |
2884 | break; | 2495 | break; |
@@ -2895,7 +2506,9 @@ static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec, | |||
2895 | const struct auto_pin_cfg *cfg) | 2506 | const struct auto_pin_cfg *cfg) |
2896 | { | 2507 | { |
2897 | char name[32]; | 2508 | char name[32]; |
2898 | static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; | 2509 | static const char * const chname[4] = { |
2510 | "Front", "Surround", "C/LFE", "Side" | ||
2511 | }; | ||
2899 | hda_nid_t nid, nid_vol, nid_vols[] = {0x18, 0x1a, 0x1b, 0x29}; | 2512 | hda_nid_t nid, nid_vol, nid_vols[] = {0x18, 0x1a, 0x1b, 0x29}; |
2900 | int i, err; | 2513 | int i, err; |
2901 | 2514 | ||
@@ -3021,49 +2634,12 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
3021 | } | 2634 | } |
3022 | 2635 | ||
3023 | /* create playback/capture controls for input pins */ | 2636 | /* create playback/capture controls for input pins */ |
3024 | static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec, | 2637 | static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec, |
3025 | const struct auto_pin_cfg *cfg) | 2638 | const struct auto_pin_cfg *cfg) |
3026 | { | 2639 | { |
3027 | static char *labels[] = { | 2640 | static const hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 }; |
3028 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 2641 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs, |
3029 | }; | 2642 | ARRAY_SIZE(pin_idxs)); |
3030 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
3031 | int i, err, idx = 0; | ||
3032 | |||
3033 | /* for internal loopback recording select */ | ||
3034 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
3035 | imux->items[imux->num_items].index = idx; | ||
3036 | imux->num_items++; | ||
3037 | |||
3038 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
3039 | if (!cfg->input_pins[i]) | ||
3040 | continue; | ||
3041 | |||
3042 | switch (cfg->input_pins[i]) { | ||
3043 | case 0x1d: /* Mic */ | ||
3044 | idx = 2; | ||
3045 | break; | ||
3046 | |||
3047 | case 0x1e: /* Line In */ | ||
3048 | idx = 3; | ||
3049 | break; | ||
3050 | |||
3051 | case 0x21: /* Front Mic */ | ||
3052 | idx = 4; | ||
3053 | break; | ||
3054 | |||
3055 | case 0x23: /* CD */ | ||
3056 | idx = 1; | ||
3057 | break; | ||
3058 | } | ||
3059 | err = via_new_analog_input(spec, labels[i], idx, 0x18); | ||
3060 | if (err < 0) | ||
3061 | return err; | ||
3062 | imux->items[imux->num_items].label = labels[i]; | ||
3063 | imux->items[imux->num_items].index = idx; | ||
3064 | imux->num_items++; | ||
3065 | } | ||
3066 | return 0; | ||
3067 | } | 2643 | } |
3068 | 2644 | ||
3069 | static int vt1709_parse_auto_config(struct hda_codec *codec) | 2645 | static int vt1709_parse_auto_config(struct hda_codec *codec) |
@@ -3086,7 +2662,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
3086 | err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 2662 | err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
3087 | if (err < 0) | 2663 | if (err < 0) |
3088 | return err; | 2664 | return err; |
3089 | err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg); | 2665 | err = vt1709_auto_create_analog_input_ctls(codec, &spec->autocfg); |
3090 | if (err < 0) | 2666 | if (err < 0) |
3091 | return err; | 2667 | return err; |
3092 | 2668 | ||
@@ -3111,7 +2687,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
3111 | } | 2687 | } |
3112 | 2688 | ||
3113 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2689 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
3114 | static struct hda_amp_list vt1709_loopbacks[] = { | 2690 | static const struct hda_amp_list vt1709_loopbacks[] = { |
3115 | { 0x18, HDA_INPUT, 1 }, | 2691 | { 0x18, HDA_INPUT, 1 }, |
3116 | { 0x18, HDA_INPUT, 2 }, | 2692 | { 0x18, HDA_INPUT, 2 }, |
3117 | { 0x18, HDA_INPUT, 3 }, | 2693 | { 0x18, HDA_INPUT, 3 }, |
@@ -3172,7 +2748,7 @@ static int patch_vt1709_10ch(struct hda_codec *codec) | |||
3172 | /* | 2748 | /* |
3173 | * generic initialization of ADC, input mixers and output mixers | 2749 | * generic initialization of ADC, input mixers and output mixers |
3174 | */ | 2750 | */ |
3175 | static struct hda_verb vt1709_6ch_volume_init_verbs[] = { | 2751 | static const struct hda_verb vt1709_6ch_volume_init_verbs[] = { |
3176 | /* | 2752 | /* |
3177 | * Unmute ADC0-2 and set the default input to mic-in | 2753 | * Unmute ADC0-2 and set the default input to mic-in |
3178 | */ | 2754 | */ |
@@ -3262,7 +2838,7 @@ static int patch_vt1709_6ch(struct hda_codec *codec) | |||
3262 | } | 2838 | } |
3263 | 2839 | ||
3264 | /* capture mixer elements */ | 2840 | /* capture mixer elements */ |
3265 | static struct snd_kcontrol_new vt1708B_capture_mixer[] = { | 2841 | static const struct snd_kcontrol_new vt1708B_capture_mixer[] = { |
3266 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), | 2842 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), |
3267 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), | 2843 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), |
3268 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), | 2844 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), |
@@ -3284,7 +2860,7 @@ static struct snd_kcontrol_new vt1708B_capture_mixer[] = { | |||
3284 | /* | 2860 | /* |
3285 | * generic initialization of ADC, input mixers and output mixers | 2861 | * generic initialization of ADC, input mixers and output mixers |
3286 | */ | 2862 | */ |
3287 | static struct hda_verb vt1708B_8ch_volume_init_verbs[] = { | 2863 | static const struct hda_verb vt1708B_8ch_volume_init_verbs[] = { |
3288 | /* | 2864 | /* |
3289 | * Unmute ADC0-1 and set the default input to mic-in | 2865 | * Unmute ADC0-1 and set the default input to mic-in |
3290 | */ | 2866 | */ |
@@ -3319,7 +2895,7 @@ static struct hda_verb vt1708B_8ch_volume_init_verbs[] = { | |||
3319 | { } | 2895 | { } |
3320 | }; | 2896 | }; |
3321 | 2897 | ||
3322 | static struct hda_verb vt1708B_4ch_volume_init_verbs[] = { | 2898 | static const struct hda_verb vt1708B_4ch_volume_init_verbs[] = { |
3323 | /* | 2899 | /* |
3324 | * Unmute ADC0-1 and set the default input to mic-in | 2900 | * Unmute ADC0-1 and set the default input to mic-in |
3325 | */ | 2901 | */ |
@@ -3354,7 +2930,7 @@ static struct hda_verb vt1708B_4ch_volume_init_verbs[] = { | |||
3354 | { } | 2930 | { } |
3355 | }; | 2931 | }; |
3356 | 2932 | ||
3357 | static struct hda_verb vt1708B_uniwill_init_verbs[] = { | 2933 | static const struct hda_verb vt1708B_uniwill_init_verbs[] = { |
3358 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, | 2934 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, |
3359 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, | 2935 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, |
3360 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | 2936 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, |
@@ -3378,7 +2954,7 @@ static int via_pcm_open_close(struct hda_pcm_stream *hinfo, | |||
3378 | return 0; | 2954 | return 0; |
3379 | } | 2955 | } |
3380 | 2956 | ||
3381 | static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = { | 2957 | static const struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = { |
3382 | .substreams = 2, | 2958 | .substreams = 2, |
3383 | .channels_min = 2, | 2959 | .channels_min = 2, |
3384 | .channels_max = 8, | 2960 | .channels_max = 8, |
@@ -3391,7 +2967,7 @@ static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = { | |||
3391 | }, | 2967 | }, |
3392 | }; | 2968 | }; |
3393 | 2969 | ||
3394 | static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = { | 2970 | static const struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = { |
3395 | .substreams = 2, | 2971 | .substreams = 2, |
3396 | .channels_min = 2, | 2972 | .channels_min = 2, |
3397 | .channels_max = 4, | 2973 | .channels_max = 4, |
@@ -3403,7 +2979,7 @@ static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = { | |||
3403 | }, | 2979 | }, |
3404 | }; | 2980 | }; |
3405 | 2981 | ||
3406 | static struct hda_pcm_stream vt1708B_pcm_analog_capture = { | 2982 | static const struct hda_pcm_stream vt1708B_pcm_analog_capture = { |
3407 | .substreams = 2, | 2983 | .substreams = 2, |
3408 | .channels_min = 2, | 2984 | .channels_min = 2, |
3409 | .channels_max = 2, | 2985 | .channels_max = 2, |
@@ -3416,7 +2992,7 @@ static struct hda_pcm_stream vt1708B_pcm_analog_capture = { | |||
3416 | }, | 2992 | }, |
3417 | }; | 2993 | }; |
3418 | 2994 | ||
3419 | static struct hda_pcm_stream vt1708B_pcm_digital_playback = { | 2995 | static const struct hda_pcm_stream vt1708B_pcm_digital_playback = { |
3420 | .substreams = 1, | 2996 | .substreams = 1, |
3421 | .channels_min = 2, | 2997 | .channels_min = 2, |
3422 | .channels_max = 2, | 2998 | .channels_max = 2, |
@@ -3429,7 +3005,7 @@ static struct hda_pcm_stream vt1708B_pcm_digital_playback = { | |||
3429 | }, | 3005 | }, |
3430 | }; | 3006 | }; |
3431 | 3007 | ||
3432 | static struct hda_pcm_stream vt1708B_pcm_digital_capture = { | 3008 | static const struct hda_pcm_stream vt1708B_pcm_digital_capture = { |
3433 | .substreams = 1, | 3009 | .substreams = 1, |
3434 | .channels_min = 2, | 3010 | .channels_min = 2, |
3435 | .channels_max = 2, | 3011 | .channels_max = 2, |
@@ -3452,16 +3028,16 @@ static int vt1708B_auto_fill_dac_nids(struct via_spec *spec, | |||
3452 | /* config dac list */ | 3028 | /* config dac list */ |
3453 | switch (i) { | 3029 | switch (i) { |
3454 | case AUTO_SEQ_FRONT: | 3030 | case AUTO_SEQ_FRONT: |
3455 | spec->multiout.dac_nids[i] = 0x10; | 3031 | spec->private_dac_nids[i] = 0x10; |
3456 | break; | 3032 | break; |
3457 | case AUTO_SEQ_CENLFE: | 3033 | case AUTO_SEQ_CENLFE: |
3458 | spec->multiout.dac_nids[i] = 0x24; | 3034 | spec->private_dac_nids[i] = 0x24; |
3459 | break; | 3035 | break; |
3460 | case AUTO_SEQ_SURROUND: | 3036 | case AUTO_SEQ_SURROUND: |
3461 | spec->multiout.dac_nids[i] = 0x11; | 3037 | spec->private_dac_nids[i] = 0x11; |
3462 | break; | 3038 | break; |
3463 | case AUTO_SEQ_SIDE: | 3039 | case AUTO_SEQ_SIDE: |
3464 | spec->multiout.dac_nids[i] = 0x25; | 3040 | spec->private_dac_nids[i] = 0x25; |
3465 | break; | 3041 | break; |
3466 | } | 3042 | } |
3467 | } | 3043 | } |
@@ -3475,7 +3051,9 @@ static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec, | |||
3475 | const struct auto_pin_cfg *cfg) | 3051 | const struct auto_pin_cfg *cfg) |
3476 | { | 3052 | { |
3477 | char name[32]; | 3053 | char name[32]; |
3478 | static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; | 3054 | static const char * const chname[4] = { |
3055 | "Front", "Surround", "C/LFE", "Side" | ||
3056 | }; | ||
3479 | hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27}; | 3057 | hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27}; |
3480 | hda_nid_t nid, nid_vol = 0; | 3058 | hda_nid_t nid, nid_vol = 0; |
3481 | int i, err; | 3059 | int i, err; |
@@ -3588,49 +3166,12 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
3588 | } | 3166 | } |
3589 | 3167 | ||
3590 | /* create playback/capture controls for input pins */ | 3168 | /* create playback/capture controls for input pins */ |
3591 | static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec, | 3169 | static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec, |
3592 | const struct auto_pin_cfg *cfg) | 3170 | const struct auto_pin_cfg *cfg) |
3593 | { | 3171 | { |
3594 | static char *labels[] = { | 3172 | static const hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e }; |
3595 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3173 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
3596 | }; | 3174 | ARRAY_SIZE(pin_idxs)); |
3597 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
3598 | int i, err, idx = 0; | ||
3599 | |||
3600 | /* for internal loopback recording select */ | ||
3601 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
3602 | imux->items[imux->num_items].index = idx; | ||
3603 | imux->num_items++; | ||
3604 | |||
3605 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
3606 | if (!cfg->input_pins[i]) | ||
3607 | continue; | ||
3608 | |||
3609 | switch (cfg->input_pins[i]) { | ||
3610 | case 0x1a: /* Mic */ | ||
3611 | idx = 2; | ||
3612 | break; | ||
3613 | |||
3614 | case 0x1b: /* Line In */ | ||
3615 | idx = 3; | ||
3616 | break; | ||
3617 | |||
3618 | case 0x1e: /* Front Mic */ | ||
3619 | idx = 4; | ||
3620 | break; | ||
3621 | |||
3622 | case 0x1f: /* CD */ | ||
3623 | idx = 1; | ||
3624 | break; | ||
3625 | } | ||
3626 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
3627 | if (err < 0) | ||
3628 | return err; | ||
3629 | imux->items[imux->num_items].label = labels[i]; | ||
3630 | imux->items[imux->num_items].index = idx; | ||
3631 | imux->num_items++; | ||
3632 | } | ||
3633 | return 0; | ||
3634 | } | 3175 | } |
3635 | 3176 | ||
3636 | static int vt1708B_parse_auto_config(struct hda_codec *codec) | 3177 | static int vt1708B_parse_auto_config(struct hda_codec *codec) |
@@ -3653,7 +3194,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
3653 | err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 3194 | err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
3654 | if (err < 0) | 3195 | if (err < 0) |
3655 | return err; | 3196 | return err; |
3656 | err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg); | 3197 | err = vt1708B_auto_create_analog_input_ctls(codec, &spec->autocfg); |
3657 | if (err < 0) | 3198 | if (err < 0) |
3658 | return err; | 3199 | return err; |
3659 | 3200 | ||
@@ -3678,7 +3219,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
3678 | } | 3219 | } |
3679 | 3220 | ||
3680 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3221 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
3681 | static struct hda_amp_list vt1708B_loopbacks[] = { | 3222 | static const struct hda_amp_list vt1708B_loopbacks[] = { |
3682 | { 0x16, HDA_INPUT, 1 }, | 3223 | { 0x16, HDA_INPUT, 1 }, |
3683 | { 0x16, HDA_INPUT, 2 }, | 3224 | { 0x16, HDA_INPUT, 2 }, |
3684 | { 0x16, HDA_INPUT, 3 }, | 3225 | { 0x16, HDA_INPUT, 3 }, |
@@ -3686,6 +3227,87 @@ static struct hda_amp_list vt1708B_loopbacks[] = { | |||
3686 | { } /* end */ | 3227 | { } /* end */ |
3687 | }; | 3228 | }; |
3688 | #endif | 3229 | #endif |
3230 | |||
3231 | static void set_widgets_power_state_vt1708B(struct hda_codec *codec) | ||
3232 | { | ||
3233 | struct via_spec *spec = codec->spec; | ||
3234 | int imux_is_smixer; | ||
3235 | unsigned int parm; | ||
3236 | int is_8ch = 0; | ||
3237 | if ((spec->codec_type != VT1708B_4CH) && | ||
3238 | (codec->vendor_id != 0x11064397)) | ||
3239 | is_8ch = 1; | ||
3240 | |||
3241 | /* SW0 (17h) = stereo mixer */ | ||
3242 | imux_is_smixer = | ||
3243 | (snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) | ||
3244 | == ((spec->codec_type == VT1708S) ? 5 : 0)); | ||
3245 | /* inputs */ | ||
3246 | /* PW 1/2/5 (1ah/1bh/1eh) */ | ||
3247 | parm = AC_PWRST_D3; | ||
3248 | set_pin_power_state(codec, 0x1a, &parm); | ||
3249 | set_pin_power_state(codec, 0x1b, &parm); | ||
3250 | set_pin_power_state(codec, 0x1e, &parm); | ||
3251 | if (imux_is_smixer) | ||
3252 | parm = AC_PWRST_D0; | ||
3253 | /* SW0 (17h), AIW 0/1 (13h/14h) */ | ||
3254 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); | ||
3255 | snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); | ||
3256 | snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); | ||
3257 | |||
3258 | /* outputs */ | ||
3259 | /* PW0 (19h), SW1 (18h), AOW1 (11h) */ | ||
3260 | parm = AC_PWRST_D3; | ||
3261 | set_pin_power_state(codec, 0x19, &parm); | ||
3262 | if (spec->smart51_enabled) | ||
3263 | set_pin_power_state(codec, 0x1b, &parm); | ||
3264 | snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); | ||
3265 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); | ||
3266 | |||
3267 | /* PW6 (22h), SW2 (26h), AOW2 (24h) */ | ||
3268 | if (is_8ch) { | ||
3269 | parm = AC_PWRST_D3; | ||
3270 | set_pin_power_state(codec, 0x22, &parm); | ||
3271 | if (spec->smart51_enabled) | ||
3272 | set_pin_power_state(codec, 0x1a, &parm); | ||
3273 | snd_hda_codec_write(codec, 0x26, 0, | ||
3274 | AC_VERB_SET_POWER_STATE, parm); | ||
3275 | snd_hda_codec_write(codec, 0x24, 0, | ||
3276 | AC_VERB_SET_POWER_STATE, parm); | ||
3277 | } else if (codec->vendor_id == 0x11064397) { | ||
3278 | /* PW7(23h), SW2(27h), AOW2(25h) */ | ||
3279 | parm = AC_PWRST_D3; | ||
3280 | set_pin_power_state(codec, 0x23, &parm); | ||
3281 | if (spec->smart51_enabled) | ||
3282 | set_pin_power_state(codec, 0x1a, &parm); | ||
3283 | snd_hda_codec_write(codec, 0x27, 0, | ||
3284 | AC_VERB_SET_POWER_STATE, parm); | ||
3285 | snd_hda_codec_write(codec, 0x25, 0, | ||
3286 | AC_VERB_SET_POWER_STATE, parm); | ||
3287 | } | ||
3288 | |||
3289 | /* PW 3/4/7 (1ch/1dh/23h) */ | ||
3290 | parm = AC_PWRST_D3; | ||
3291 | /* force to D0 for internal Speaker */ | ||
3292 | set_pin_power_state(codec, 0x1c, &parm); | ||
3293 | set_pin_power_state(codec, 0x1d, &parm); | ||
3294 | if (is_8ch) | ||
3295 | set_pin_power_state(codec, 0x23, &parm); | ||
3296 | |||
3297 | /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */ | ||
3298 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, | ||
3299 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
3300 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); | ||
3301 | if (is_8ch) { | ||
3302 | snd_hda_codec_write(codec, 0x25, 0, | ||
3303 | AC_VERB_SET_POWER_STATE, parm); | ||
3304 | snd_hda_codec_write(codec, 0x27, 0, | ||
3305 | AC_VERB_SET_POWER_STATE, parm); | ||
3306 | } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode) | ||
3307 | snd_hda_codec_write(codec, 0x25, 0, | ||
3308 | AC_VERB_SET_POWER_STATE, parm); | ||
3309 | } | ||
3310 | |||
3689 | static int patch_vt1708S(struct hda_codec *codec); | 3311 | static int patch_vt1708S(struct hda_codec *codec); |
3690 | static int patch_vt1708B_8ch(struct hda_codec *codec) | 3312 | static int patch_vt1708B_8ch(struct hda_codec *codec) |
3691 | { | 3313 | { |
@@ -3736,6 +3358,8 @@ static int patch_vt1708B_8ch(struct hda_codec *codec) | |||
3736 | spec->loopback.amplist = vt1708B_loopbacks; | 3358 | spec->loopback.amplist = vt1708B_loopbacks; |
3737 | #endif | 3359 | #endif |
3738 | 3360 | ||
3361 | spec->set_widgets_power_state = set_widgets_power_state_vt1708B; | ||
3362 | |||
3739 | return 0; | 3363 | return 0; |
3740 | } | 3364 | } |
3741 | 3365 | ||
@@ -3786,13 +3410,15 @@ static int patch_vt1708B_4ch(struct hda_codec *codec) | |||
3786 | spec->loopback.amplist = vt1708B_loopbacks; | 3410 | spec->loopback.amplist = vt1708B_loopbacks; |
3787 | #endif | 3411 | #endif |
3788 | 3412 | ||
3413 | spec->set_widgets_power_state = set_widgets_power_state_vt1708B; | ||
3414 | |||
3789 | return 0; | 3415 | return 0; |
3790 | } | 3416 | } |
3791 | 3417 | ||
3792 | /* Patch for VT1708S */ | 3418 | /* Patch for VT1708S */ |
3793 | 3419 | ||
3794 | /* capture mixer elements */ | 3420 | /* capture mixer elements */ |
3795 | static struct snd_kcontrol_new vt1708S_capture_mixer[] = { | 3421 | static const struct snd_kcontrol_new vt1708S_capture_mixer[] = { |
3796 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), | 3422 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), |
3797 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), | 3423 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), |
3798 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), | 3424 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), |
@@ -3815,7 +3441,7 @@ static struct snd_kcontrol_new vt1708S_capture_mixer[] = { | |||
3815 | { } /* end */ | 3441 | { } /* end */ |
3816 | }; | 3442 | }; |
3817 | 3443 | ||
3818 | static struct hda_verb vt1708S_volume_init_verbs[] = { | 3444 | static const struct hda_verb vt1708S_volume_init_verbs[] = { |
3819 | /* Unmute ADC0-1 and set the default input to mic-in */ | 3445 | /* Unmute ADC0-1 and set the default input to mic-in */ |
3820 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 3446 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
3821 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 3447 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -3841,7 +3467,7 @@ static struct hda_verb vt1708S_volume_init_verbs[] = { | |||
3841 | { } | 3467 | { } |
3842 | }; | 3468 | }; |
3843 | 3469 | ||
3844 | static struct hda_verb vt1708S_uniwill_init_verbs[] = { | 3470 | static const struct hda_verb vt1708S_uniwill_init_verbs[] = { |
3845 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, | 3471 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, |
3846 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, | 3472 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, |
3847 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | 3473 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, |
@@ -3854,7 +3480,19 @@ static struct hda_verb vt1708S_uniwill_init_verbs[] = { | |||
3854 | { } | 3480 | { } |
3855 | }; | 3481 | }; |
3856 | 3482 | ||
3857 | static struct hda_pcm_stream vt1708S_pcm_analog_playback = { | 3483 | static const struct hda_verb vt1705_uniwill_init_verbs[] = { |
3484 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, | ||
3485 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, | ||
3486 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
3487 | {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
3488 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
3489 | {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
3490 | {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
3491 | {0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
3492 | { } | ||
3493 | }; | ||
3494 | |||
3495 | static const struct hda_pcm_stream vt1708S_pcm_analog_playback = { | ||
3858 | .substreams = 2, | 3496 | .substreams = 2, |
3859 | .channels_min = 2, | 3497 | .channels_min = 2, |
3860 | .channels_max = 8, | 3498 | .channels_max = 8, |
@@ -3867,7 +3505,20 @@ static struct hda_pcm_stream vt1708S_pcm_analog_playback = { | |||
3867 | }, | 3505 | }, |
3868 | }; | 3506 | }; |
3869 | 3507 | ||
3870 | static struct hda_pcm_stream vt1708S_pcm_analog_capture = { | 3508 | static const struct hda_pcm_stream vt1705_pcm_analog_playback = { |
3509 | .substreams = 2, | ||
3510 | .channels_min = 2, | ||
3511 | .channels_max = 6, | ||
3512 | .nid = 0x10, /* NID to query formats and rates */ | ||
3513 | .ops = { | ||
3514 | .open = via_playback_pcm_open, | ||
3515 | .prepare = via_playback_multi_pcm_prepare, | ||
3516 | .cleanup = via_playback_multi_pcm_cleanup, | ||
3517 | .close = via_pcm_open_close | ||
3518 | }, | ||
3519 | }; | ||
3520 | |||
3521 | static const struct hda_pcm_stream vt1708S_pcm_analog_capture = { | ||
3871 | .substreams = 2, | 3522 | .substreams = 2, |
3872 | .channels_min = 2, | 3523 | .channels_min = 2, |
3873 | .channels_max = 2, | 3524 | .channels_max = 2, |
@@ -3880,7 +3531,7 @@ static struct hda_pcm_stream vt1708S_pcm_analog_capture = { | |||
3880 | }, | 3531 | }, |
3881 | }; | 3532 | }; |
3882 | 3533 | ||
3883 | static struct hda_pcm_stream vt1708S_pcm_digital_playback = { | 3534 | static const struct hda_pcm_stream vt1708S_pcm_digital_playback = { |
3884 | .substreams = 1, | 3535 | .substreams = 1, |
3885 | .channels_min = 2, | 3536 | .channels_min = 2, |
3886 | .channels_max = 2, | 3537 | .channels_max = 2, |
@@ -3910,16 +3561,19 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec, | |||
3910 | /* config dac list */ | 3561 | /* config dac list */ |
3911 | switch (i) { | 3562 | switch (i) { |
3912 | case AUTO_SEQ_FRONT: | 3563 | case AUTO_SEQ_FRONT: |
3913 | spec->multiout.dac_nids[i] = 0x10; | 3564 | spec->private_dac_nids[i] = 0x10; |
3914 | break; | 3565 | break; |
3915 | case AUTO_SEQ_CENLFE: | 3566 | case AUTO_SEQ_CENLFE: |
3916 | spec->multiout.dac_nids[i] = 0x24; | 3567 | if (spec->codec->vendor_id == 0x11064397) |
3568 | spec->private_dac_nids[i] = 0x25; | ||
3569 | else | ||
3570 | spec->private_dac_nids[i] = 0x24; | ||
3917 | break; | 3571 | break; |
3918 | case AUTO_SEQ_SURROUND: | 3572 | case AUTO_SEQ_SURROUND: |
3919 | spec->multiout.dac_nids[i] = 0x11; | 3573 | spec->private_dac_nids[i] = 0x11; |
3920 | break; | 3574 | break; |
3921 | case AUTO_SEQ_SIDE: | 3575 | case AUTO_SEQ_SIDE: |
3922 | spec->multiout.dac_nids[i] = 0x25; | 3576 | spec->private_dac_nids[i] = 0x25; |
3923 | break; | 3577 | break; |
3924 | } | 3578 | } |
3925 | } | 3579 | } |
@@ -3928,21 +3582,29 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec, | |||
3928 | /* for Smart 5.1, line/mic inputs double as output pins */ | 3582 | /* for Smart 5.1, line/mic inputs double as output pins */ |
3929 | if (cfg->line_outs == 1) { | 3583 | if (cfg->line_outs == 1) { |
3930 | spec->multiout.num_dacs = 3; | 3584 | spec->multiout.num_dacs = 3; |
3931 | spec->multiout.dac_nids[AUTO_SEQ_SURROUND] = 0x11; | 3585 | spec->private_dac_nids[AUTO_SEQ_SURROUND] = 0x11; |
3932 | spec->multiout.dac_nids[AUTO_SEQ_CENLFE] = 0x24; | 3586 | if (spec->codec->vendor_id == 0x11064397) |
3587 | spec->private_dac_nids[AUTO_SEQ_CENLFE] = 0x25; | ||
3588 | else | ||
3589 | spec->private_dac_nids[AUTO_SEQ_CENLFE] = 0x24; | ||
3933 | } | 3590 | } |
3934 | 3591 | ||
3935 | return 0; | 3592 | return 0; |
3936 | } | 3593 | } |
3937 | 3594 | ||
3938 | /* add playback controls from the parsed DAC table */ | 3595 | /* add playback controls from the parsed DAC table */ |
3939 | static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec, | 3596 | static int vt1708S_auto_create_multi_out_ctls(struct hda_codec *codec, |
3940 | const struct auto_pin_cfg *cfg) | 3597 | const struct auto_pin_cfg *cfg) |
3941 | { | 3598 | { |
3599 | struct via_spec *spec = codec->spec; | ||
3942 | char name[32]; | 3600 | char name[32]; |
3943 | static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; | 3601 | static const char * const chname[4] = { |
3944 | hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25}; | 3602 | "Front", "Surround", "C/LFE", "Side" |
3945 | hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27}; | 3603 | }; |
3604 | hda_nid_t nid_vols[2][4] = { {0x10, 0x11, 0x24, 0x25}, | ||
3605 | {0x10, 0x11, 0x25, 0} }; | ||
3606 | hda_nid_t nid_mutes[2][4] = { {0x1C, 0x18, 0x26, 0x27}, | ||
3607 | {0x1C, 0x18, 0x27, 0} }; | ||
3946 | hda_nid_t nid, nid_vol, nid_mute; | 3608 | hda_nid_t nid, nid_vol, nid_mute; |
3947 | int i, err; | 3609 | int i, err; |
3948 | 3610 | ||
@@ -3953,8 +3615,15 @@ static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec, | |||
3953 | if (!nid && i > AUTO_SEQ_CENLFE) | 3615 | if (!nid && i > AUTO_SEQ_CENLFE) |
3954 | continue; | 3616 | continue; |
3955 | 3617 | ||
3956 | nid_vol = nid_vols[i]; | 3618 | if (codec->vendor_id == 0x11064397) { |
3957 | nid_mute = nid_mutes[i]; | 3619 | nid_vol = nid_vols[1][i]; |
3620 | nid_mute = nid_mutes[1][i]; | ||
3621 | } else { | ||
3622 | nid_vol = nid_vols[0][i]; | ||
3623 | nid_mute = nid_mutes[0][i]; | ||
3624 | } | ||
3625 | if (!nid_vol && !nid_mute) | ||
3626 | continue; | ||
3958 | 3627 | ||
3959 | if (i == AUTO_SEQ_CENLFE) { | 3628 | if (i == AUTO_SEQ_CENLFE) { |
3960 | /* Center/LFE */ | 3629 | /* Center/LFE */ |
@@ -4061,49 +3730,12 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
4061 | } | 3730 | } |
4062 | 3731 | ||
4063 | /* create playback/capture controls for input pins */ | 3732 | /* create playback/capture controls for input pins */ |
4064 | static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec, | 3733 | static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec, |
4065 | const struct auto_pin_cfg *cfg) | 3734 | const struct auto_pin_cfg *cfg) |
4066 | { | 3735 | { |
4067 | static char *labels[] = { | 3736 | static const hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; |
4068 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3737 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
4069 | }; | 3738 | ARRAY_SIZE(pin_idxs)); |
4070 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
4071 | int i, err, idx = 0; | ||
4072 | |||
4073 | /* for internal loopback recording select */ | ||
4074 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
4075 | imux->items[imux->num_items].index = 5; | ||
4076 | imux->num_items++; | ||
4077 | |||
4078 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
4079 | if (!cfg->input_pins[i]) | ||
4080 | continue; | ||
4081 | |||
4082 | switch (cfg->input_pins[i]) { | ||
4083 | case 0x1a: /* Mic */ | ||
4084 | idx = 2; | ||
4085 | break; | ||
4086 | |||
4087 | case 0x1b: /* Line In */ | ||
4088 | idx = 3; | ||
4089 | break; | ||
4090 | |||
4091 | case 0x1e: /* Front Mic */ | ||
4092 | idx = 4; | ||
4093 | break; | ||
4094 | |||
4095 | case 0x1f: /* CD */ | ||
4096 | idx = 1; | ||
4097 | break; | ||
4098 | } | ||
4099 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
4100 | if (err < 0) | ||
4101 | return err; | ||
4102 | imux->items[imux->num_items].label = labels[i]; | ||
4103 | imux->items[imux->num_items].index = idx-1; | ||
4104 | imux->num_items++; | ||
4105 | } | ||
4106 | return 0; | ||
4107 | } | 3739 | } |
4108 | 3740 | ||
4109 | /* fill out digital output widgets; one for master and one for slave outputs */ | 3741 | /* fill out digital output widgets; one for master and one for slave outputs */ |
@@ -4145,13 +3777,13 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
4145 | if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0]) | 3777 | if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0]) |
4146 | return 0; /* can't find valid BIOS pin config */ | 3778 | return 0; /* can't find valid BIOS pin config */ |
4147 | 3779 | ||
4148 | err = vt1708S_auto_create_multi_out_ctls(spec, &spec->autocfg); | 3780 | err = vt1708S_auto_create_multi_out_ctls(codec, &spec->autocfg); |
4149 | if (err < 0) | 3781 | if (err < 0) |
4150 | return err; | 3782 | return err; |
4151 | err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 3783 | err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
4152 | if (err < 0) | 3784 | if (err < 0) |
4153 | return err; | 3785 | return err; |
4154 | err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 3786 | err = vt1708S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
4155 | if (err < 0) | 3787 | if (err < 0) |
4156 | return err; | 3788 | return err; |
4157 | 3789 | ||
@@ -4172,7 +3804,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
4172 | } | 3804 | } |
4173 | 3805 | ||
4174 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3806 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
4175 | static struct hda_amp_list vt1708S_loopbacks[] = { | 3807 | static const struct hda_amp_list vt1708S_loopbacks[] = { |
4176 | { 0x16, HDA_INPUT, 1 }, | 3808 | { 0x16, HDA_INPUT, 1 }, |
4177 | { 0x16, HDA_INPUT, 2 }, | 3809 | { 0x16, HDA_INPUT, 2 }, |
4178 | { 0x16, HDA_INPUT, 3 }, | 3810 | { 0x16, HDA_INPUT, 3 }, |
@@ -4212,17 +3844,29 @@ static int patch_vt1708S(struct hda_codec *codec) | |||
4212 | } | 3844 | } |
4213 | 3845 | ||
4214 | spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs; | 3846 | spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs; |
4215 | spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs; | 3847 | if (codec->vendor_id == 0x11064397) |
3848 | spec->init_verbs[spec->num_iverbs++] = | ||
3849 | vt1705_uniwill_init_verbs; | ||
3850 | else | ||
3851 | spec->init_verbs[spec->num_iverbs++] = | ||
3852 | vt1708S_uniwill_init_verbs; | ||
4216 | 3853 | ||
4217 | if (codec->vendor_id == 0x11060440) | 3854 | if (codec->vendor_id == 0x11060440) |
4218 | spec->stream_name_analog = "VT1818S Analog"; | 3855 | spec->stream_name_analog = "VT1818S Analog"; |
3856 | else if (codec->vendor_id == 0x11064397) | ||
3857 | spec->stream_name_analog = "VT1705 Analog"; | ||
4219 | else | 3858 | else |
4220 | spec->stream_name_analog = "VT1708S Analog"; | 3859 | spec->stream_name_analog = "VT1708S Analog"; |
4221 | spec->stream_analog_playback = &vt1708S_pcm_analog_playback; | 3860 | if (codec->vendor_id == 0x11064397) |
3861 | spec->stream_analog_playback = &vt1705_pcm_analog_playback; | ||
3862 | else | ||
3863 | spec->stream_analog_playback = &vt1708S_pcm_analog_playback; | ||
4222 | spec->stream_analog_capture = &vt1708S_pcm_analog_capture; | 3864 | spec->stream_analog_capture = &vt1708S_pcm_analog_capture; |
4223 | 3865 | ||
4224 | if (codec->vendor_id == 0x11060440) | 3866 | if (codec->vendor_id == 0x11060440) |
4225 | spec->stream_name_digital = "VT1818S Digital"; | 3867 | spec->stream_name_digital = "VT1818S Digital"; |
3868 | else if (codec->vendor_id == 0x11064397) | ||
3869 | spec->stream_name_digital = "VT1705 Digital"; | ||
4226 | else | 3870 | else |
4227 | spec->stream_name_digital = "VT1708S Digital"; | 3871 | spec->stream_name_digital = "VT1708S Digital"; |
4228 | spec->stream_digital_playback = &vt1708S_pcm_digital_playback; | 3872 | spec->stream_digital_playback = &vt1708S_pcm_digital_playback; |
@@ -4255,13 +3899,27 @@ static int patch_vt1708S(struct hda_codec *codec) | |||
4255 | spec->stream_name_analog = "VT1708BCE Analog"; | 3899 | spec->stream_name_analog = "VT1708BCE Analog"; |
4256 | spec->stream_name_digital = "VT1708BCE Digital"; | 3900 | spec->stream_name_digital = "VT1708BCE Digital"; |
4257 | } | 3901 | } |
3902 | /* correct names for VT1818S */ | ||
3903 | if (codec->vendor_id == 0x11060440) { | ||
3904 | spec->stream_name_analog = "VT1818S Analog"; | ||
3905 | spec->stream_name_digital = "VT1818S Digital"; | ||
3906 | } | ||
3907 | /* correct names for VT1705 */ | ||
3908 | if (codec->vendor_id == 0x11064397) { | ||
3909 | kfree(codec->chip_name); | ||
3910 | codec->chip_name = kstrdup("VT1705", GFP_KERNEL); | ||
3911 | snprintf(codec->bus->card->mixername, | ||
3912 | sizeof(codec->bus->card->mixername), | ||
3913 | "%s %s", codec->vendor_name, codec->chip_name); | ||
3914 | } | ||
3915 | spec->set_widgets_power_state = set_widgets_power_state_vt1708B; | ||
4258 | return 0; | 3916 | return 0; |
4259 | } | 3917 | } |
4260 | 3918 | ||
4261 | /* Patch for VT1702 */ | 3919 | /* Patch for VT1702 */ |
4262 | 3920 | ||
4263 | /* capture mixer elements */ | 3921 | /* capture mixer elements */ |
4264 | static struct snd_kcontrol_new vt1702_capture_mixer[] = { | 3922 | static const struct snd_kcontrol_new vt1702_capture_mixer[] = { |
4265 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_INPUT), | 3923 | HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_INPUT), |
4266 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_INPUT), | 3924 | HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_INPUT), |
4267 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x20, 0x0, HDA_INPUT), | 3925 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x20, 0x0, HDA_INPUT), |
@@ -4285,7 +3943,7 @@ static struct snd_kcontrol_new vt1702_capture_mixer[] = { | |||
4285 | { } /* end */ | 3943 | { } /* end */ |
4286 | }; | 3944 | }; |
4287 | 3945 | ||
4288 | static struct hda_verb vt1702_volume_init_verbs[] = { | 3946 | static const struct hda_verb vt1702_volume_init_verbs[] = { |
4289 | /* | 3947 | /* |
4290 | * Unmute ADC0-1 and set the default input to mic-in | 3948 | * Unmute ADC0-1 and set the default input to mic-in |
4291 | */ | 3949 | */ |
@@ -4316,7 +3974,7 @@ static struct hda_verb vt1702_volume_init_verbs[] = { | |||
4316 | { } | 3974 | { } |
4317 | }; | 3975 | }; |
4318 | 3976 | ||
4319 | static struct hda_verb vt1702_uniwill_init_verbs[] = { | 3977 | static const struct hda_verb vt1702_uniwill_init_verbs[] = { |
4320 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, | 3978 | {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, |
4321 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, | 3979 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, |
4322 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | 3980 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, |
@@ -4326,7 +3984,7 @@ static struct hda_verb vt1702_uniwill_init_verbs[] = { | |||
4326 | { } | 3984 | { } |
4327 | }; | 3985 | }; |
4328 | 3986 | ||
4329 | static struct hda_pcm_stream vt1702_pcm_analog_playback = { | 3987 | static const struct hda_pcm_stream vt1702_pcm_analog_playback = { |
4330 | .substreams = 2, | 3988 | .substreams = 2, |
4331 | .channels_min = 2, | 3989 | .channels_min = 2, |
4332 | .channels_max = 2, | 3990 | .channels_max = 2, |
@@ -4339,7 +3997,7 @@ static struct hda_pcm_stream vt1702_pcm_analog_playback = { | |||
4339 | }, | 3997 | }, |
4340 | }; | 3998 | }; |
4341 | 3999 | ||
4342 | static struct hda_pcm_stream vt1702_pcm_analog_capture = { | 4000 | static const struct hda_pcm_stream vt1702_pcm_analog_capture = { |
4343 | .substreams = 3, | 4001 | .substreams = 3, |
4344 | .channels_min = 2, | 4002 | .channels_min = 2, |
4345 | .channels_max = 2, | 4003 | .channels_max = 2, |
@@ -4352,7 +4010,7 @@ static struct hda_pcm_stream vt1702_pcm_analog_capture = { | |||
4352 | }, | 4010 | }, |
4353 | }; | 4011 | }; |
4354 | 4012 | ||
4355 | static struct hda_pcm_stream vt1702_pcm_digital_playback = { | 4013 | static const struct hda_pcm_stream vt1702_pcm_digital_playback = { |
4356 | .substreams = 2, | 4014 | .substreams = 2, |
4357 | .channels_min = 2, | 4015 | .channels_min = 2, |
4358 | .channels_max = 2, | 4016 | .channels_max = 2, |
@@ -4374,7 +4032,7 @@ static int vt1702_auto_fill_dac_nids(struct via_spec *spec, | |||
4374 | 4032 | ||
4375 | if (cfg->line_out_pins[0]) { | 4033 | if (cfg->line_out_pins[0]) { |
4376 | /* config dac list */ | 4034 | /* config dac list */ |
4377 | spec->multiout.dac_nids[0] = 0x10; | 4035 | spec->private_dac_nids[0] = 0x10; |
4378 | } | 4036 | } |
4379 | 4037 | ||
4380 | return 0; | 4038 | return 0; |
@@ -4420,7 +4078,7 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
4420 | { | 4078 | { |
4421 | int err, i; | 4079 | int err, i; |
4422 | struct hda_input_mux *imux; | 4080 | struct hda_input_mux *imux; |
4423 | static const char *texts[] = { "ON", "OFF", NULL}; | 4081 | static const char * const texts[] = { "ON", "OFF", NULL}; |
4424 | if (!pin) | 4082 | if (!pin) |
4425 | return 0; | 4083 | return 0; |
4426 | spec->multiout.hp_nid = 0x1D; | 4084 | spec->multiout.hp_nid = 0x1D; |
@@ -4441,58 +4099,20 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
4441 | imux = &spec->private_imux[1]; | 4099 | imux = &spec->private_imux[1]; |
4442 | 4100 | ||
4443 | /* for hp mode select */ | 4101 | /* for hp mode select */ |
4444 | i = 0; | 4102 | for (i = 0; texts[i]; i++) |
4445 | while (texts[i] != NULL) { | 4103 | snd_hda_add_imux_item(imux, texts[i], i, NULL); |
4446 | imux->items[imux->num_items].label = texts[i]; | ||
4447 | imux->items[imux->num_items].index = i; | ||
4448 | imux->num_items++; | ||
4449 | i++; | ||
4450 | } | ||
4451 | 4104 | ||
4452 | spec->hp_mux = &spec->private_imux[1]; | 4105 | spec->hp_mux = &spec->private_imux[1]; |
4453 | return 0; | 4106 | return 0; |
4454 | } | 4107 | } |
4455 | 4108 | ||
4456 | /* create playback/capture controls for input pins */ | 4109 | /* create playback/capture controls for input pins */ |
4457 | static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec, | 4110 | static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec, |
4458 | const struct auto_pin_cfg *cfg) | 4111 | const struct auto_pin_cfg *cfg) |
4459 | { | 4112 | { |
4460 | static char *labels[] = { | 4113 | static const hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff }; |
4461 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 4114 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs, |
4462 | }; | 4115 | ARRAY_SIZE(pin_idxs)); |
4463 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
4464 | int i, err, idx = 0; | ||
4465 | |||
4466 | /* for internal loopback recording select */ | ||
4467 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
4468 | imux->items[imux->num_items].index = 3; | ||
4469 | imux->num_items++; | ||
4470 | |||
4471 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
4472 | if (!cfg->input_pins[i]) | ||
4473 | continue; | ||
4474 | |||
4475 | switch (cfg->input_pins[i]) { | ||
4476 | case 0x14: /* Mic */ | ||
4477 | idx = 1; | ||
4478 | break; | ||
4479 | |||
4480 | case 0x15: /* Line In */ | ||
4481 | idx = 2; | ||
4482 | break; | ||
4483 | |||
4484 | case 0x18: /* Front Mic */ | ||
4485 | idx = 3; | ||
4486 | break; | ||
4487 | } | ||
4488 | err = via_new_analog_input(spec, labels[i], idx, 0x1A); | ||
4489 | if (err < 0) | ||
4490 | return err; | ||
4491 | imux->items[imux->num_items].label = labels[i]; | ||
4492 | imux->items[imux->num_items].index = idx-1; | ||
4493 | imux->num_items++; | ||
4494 | } | ||
4495 | return 0; | ||
4496 | } | 4116 | } |
4497 | 4117 | ||
4498 | static int vt1702_parse_auto_config(struct hda_codec *codec) | 4118 | static int vt1702_parse_auto_config(struct hda_codec *codec) |
@@ -4521,7 +4141,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
4521 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | 4141 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | |
4522 | (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 4142 | (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | |
4523 | (1 << AC_AMPCAP_MUTE_SHIFT)); | 4143 | (1 << AC_AMPCAP_MUTE_SHIFT)); |
4524 | err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4144 | err = vt1702_auto_create_analog_input_ctls(codec, &spec->autocfg); |
4525 | if (err < 0) | 4145 | if (err < 0) |
4526 | return err; | 4146 | return err; |
4527 | 4147 | ||
@@ -4541,7 +4161,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
4541 | } | 4161 | } |
4542 | 4162 | ||
4543 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4163 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
4544 | static struct hda_amp_list vt1702_loopbacks[] = { | 4164 | static const struct hda_amp_list vt1702_loopbacks[] = { |
4545 | { 0x1A, HDA_INPUT, 1 }, | 4165 | { 0x1A, HDA_INPUT, 1 }, |
4546 | { 0x1A, HDA_INPUT, 2 }, | 4166 | { 0x1A, HDA_INPUT, 2 }, |
4547 | { 0x1A, HDA_INPUT, 3 }, | 4167 | { 0x1A, HDA_INPUT, 3 }, |
@@ -4550,6 +4170,37 @@ static struct hda_amp_list vt1702_loopbacks[] = { | |||
4550 | }; | 4170 | }; |
4551 | #endif | 4171 | #endif |
4552 | 4172 | ||
4173 | static void set_widgets_power_state_vt1702(struct hda_codec *codec) | ||
4174 | { | ||
4175 | int imux_is_smixer = | ||
4176 | snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3; | ||
4177 | unsigned int parm; | ||
4178 | /* inputs */ | ||
4179 | /* PW 1/2/5 (14h/15h/18h) */ | ||
4180 | parm = AC_PWRST_D3; | ||
4181 | set_pin_power_state(codec, 0x14, &parm); | ||
4182 | set_pin_power_state(codec, 0x15, &parm); | ||
4183 | set_pin_power_state(codec, 0x18, &parm); | ||
4184 | if (imux_is_smixer) | ||
4185 | parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */ | ||
4186 | /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */ | ||
4187 | snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4188 | snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4189 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4190 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4191 | |||
4192 | /* outputs */ | ||
4193 | /* PW 3/4 (16h/17h) */ | ||
4194 | parm = AC_PWRST_D3; | ||
4195 | set_pin_power_state(codec, 0x17, &parm); | ||
4196 | set_pin_power_state(codec, 0x16, &parm); | ||
4197 | /* MW0 (1ah), AOW 0/1 (10h/1dh) */ | ||
4198 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, | ||
4199 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
4200 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4201 | snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4202 | } | ||
4203 | |||
4553 | static int patch_vt1702(struct hda_codec *codec) | 4204 | static int patch_vt1702(struct hda_codec *codec) |
4554 | { | 4205 | { |
4555 | struct via_spec *spec; | 4206 | struct via_spec *spec; |
@@ -4596,13 +4247,14 @@ static int patch_vt1702(struct hda_codec *codec) | |||
4596 | spec->loopback.amplist = vt1702_loopbacks; | 4247 | spec->loopback.amplist = vt1702_loopbacks; |
4597 | #endif | 4248 | #endif |
4598 | 4249 | ||
4250 | spec->set_widgets_power_state = set_widgets_power_state_vt1702; | ||
4599 | return 0; | 4251 | return 0; |
4600 | } | 4252 | } |
4601 | 4253 | ||
4602 | /* Patch for VT1718S */ | 4254 | /* Patch for VT1718S */ |
4603 | 4255 | ||
4604 | /* capture mixer elements */ | 4256 | /* capture mixer elements */ |
4605 | static struct snd_kcontrol_new vt1718S_capture_mixer[] = { | 4257 | static const struct snd_kcontrol_new vt1718S_capture_mixer[] = { |
4606 | HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT), | 4258 | HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT), |
4607 | HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT), | 4259 | HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT), |
4608 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT), | 4260 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT), |
@@ -4624,14 +4276,15 @@ static struct snd_kcontrol_new vt1718S_capture_mixer[] = { | |||
4624 | { } /* end */ | 4276 | { } /* end */ |
4625 | }; | 4277 | }; |
4626 | 4278 | ||
4627 | static struct hda_verb vt1718S_volume_init_verbs[] = { | 4279 | static const struct hda_verb vt1718S_volume_init_verbs[] = { |
4628 | /* | 4280 | /* |
4629 | * Unmute ADC0-1 and set the default input to mic-in | 4281 | * Unmute ADC0-1 and set the default input to mic-in |
4630 | */ | 4282 | */ |
4631 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4283 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
4632 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4284 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
4633 | 4285 | ||
4634 | 4286 | /* Enable MW0 adjust Gain 5 */ | |
4287 | {0x1, 0xfb2, 0x10}, | ||
4635 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback | 4288 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
4636 | * mixer widget | 4289 | * mixer widget |
4637 | */ | 4290 | */ |
@@ -4640,10 +4293,7 @@ static struct hda_verb vt1718S_volume_init_verbs[] = { | |||
4640 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 4293 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
4641 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | 4294 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
4642 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | 4295 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
4643 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, | 4296 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, |
4644 | |||
4645 | /* Setup default input of Front HP to MW9 */ | ||
4646 | {0x28, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
4647 | /* PW9 PW10 Output enable */ | 4297 | /* PW9 PW10 Output enable */ |
4648 | {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, | 4298 | {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, |
4649 | {0x2e, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, | 4299 | {0x2e, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, |
@@ -4652,10 +4302,10 @@ static struct hda_verb vt1718S_volume_init_verbs[] = { | |||
4652 | /* Enable Boost Volume backdoor */ | 4302 | /* Enable Boost Volume backdoor */ |
4653 | {0x1, 0xf88, 0x8}, | 4303 | {0x1, 0xf88, 0x8}, |
4654 | /* MW0/1/2/3/4: un-mute index 0 (AOWx), mute index 1 (MW9) */ | 4304 | /* MW0/1/2/3/4: un-mute index 0 (AOWx), mute index 1 (MW9) */ |
4655 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4305 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
4656 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4306 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
4657 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4307 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
4658 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4308 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
4659 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 4309 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
4660 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 4310 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
4661 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 4311 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
@@ -4665,13 +4315,11 @@ static struct hda_verb vt1718S_volume_init_verbs[] = { | |||
4665 | /* set MUX1 = 2 (AOW4), MUX2 = 1 (AOW3) */ | 4315 | /* set MUX1 = 2 (AOW4), MUX2 = 1 (AOW3) */ |
4666 | {0x34, AC_VERB_SET_CONNECT_SEL, 0x2}, | 4316 | {0x34, AC_VERB_SET_CONNECT_SEL, 0x2}, |
4667 | {0x35, AC_VERB_SET_CONNECT_SEL, 0x1}, | 4317 | {0x35, AC_VERB_SET_CONNECT_SEL, 0x1}, |
4668 | /* Unmute MW4's index 0 */ | ||
4669 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
4670 | { } | 4318 | { } |
4671 | }; | 4319 | }; |
4672 | 4320 | ||
4673 | 4321 | ||
4674 | static struct hda_verb vt1718S_uniwill_init_verbs[] = { | 4322 | static const struct hda_verb vt1718S_uniwill_init_verbs[] = { |
4675 | {0x28, AC_VERB_SET_UNSOLICITED_ENABLE, | 4323 | {0x28, AC_VERB_SET_UNSOLICITED_ENABLE, |
4676 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, | 4324 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, |
4677 | {0x24, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | 4325 | {0x24, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, |
@@ -4684,7 +4332,7 @@ static struct hda_verb vt1718S_uniwill_init_verbs[] = { | |||
4684 | { } | 4332 | { } |
4685 | }; | 4333 | }; |
4686 | 4334 | ||
4687 | static struct hda_pcm_stream vt1718S_pcm_analog_playback = { | 4335 | static const struct hda_pcm_stream vt1718S_pcm_analog_playback = { |
4688 | .substreams = 2, | 4336 | .substreams = 2, |
4689 | .channels_min = 2, | 4337 | .channels_min = 2, |
4690 | .channels_max = 10, | 4338 | .channels_max = 10, |
@@ -4697,7 +4345,7 @@ static struct hda_pcm_stream vt1718S_pcm_analog_playback = { | |||
4697 | }, | 4345 | }, |
4698 | }; | 4346 | }; |
4699 | 4347 | ||
4700 | static struct hda_pcm_stream vt1718S_pcm_analog_capture = { | 4348 | static const struct hda_pcm_stream vt1718S_pcm_analog_capture = { |
4701 | .substreams = 2, | 4349 | .substreams = 2, |
4702 | .channels_min = 2, | 4350 | .channels_min = 2, |
4703 | .channels_max = 2, | 4351 | .channels_max = 2, |
@@ -4710,7 +4358,7 @@ static struct hda_pcm_stream vt1718S_pcm_analog_capture = { | |||
4710 | }, | 4358 | }, |
4711 | }; | 4359 | }; |
4712 | 4360 | ||
4713 | static struct hda_pcm_stream vt1718S_pcm_digital_playback = { | 4361 | static const struct hda_pcm_stream vt1718S_pcm_digital_playback = { |
4714 | .substreams = 2, | 4362 | .substreams = 2, |
4715 | .channels_min = 2, | 4363 | .channels_min = 2, |
4716 | .channels_max = 2, | 4364 | .channels_max = 2, |
@@ -4723,7 +4371,7 @@ static struct hda_pcm_stream vt1718S_pcm_digital_playback = { | |||
4723 | }, | 4371 | }, |
4724 | }; | 4372 | }; |
4725 | 4373 | ||
4726 | static struct hda_pcm_stream vt1718S_pcm_digital_capture = { | 4374 | static const struct hda_pcm_stream vt1718S_pcm_digital_capture = { |
4727 | .substreams = 1, | 4375 | .substreams = 1, |
4728 | .channels_min = 2, | 4376 | .channels_min = 2, |
4729 | .channels_max = 2, | 4377 | .channels_max = 2, |
@@ -4746,16 +4394,16 @@ static int vt1718S_auto_fill_dac_nids(struct via_spec *spec, | |||
4746 | /* config dac list */ | 4394 | /* config dac list */ |
4747 | switch (i) { | 4395 | switch (i) { |
4748 | case AUTO_SEQ_FRONT: | 4396 | case AUTO_SEQ_FRONT: |
4749 | spec->multiout.dac_nids[i] = 0x8; | 4397 | spec->private_dac_nids[i] = 0x8; |
4750 | break; | 4398 | break; |
4751 | case AUTO_SEQ_CENLFE: | 4399 | case AUTO_SEQ_CENLFE: |
4752 | spec->multiout.dac_nids[i] = 0xa; | 4400 | spec->private_dac_nids[i] = 0xa; |
4753 | break; | 4401 | break; |
4754 | case AUTO_SEQ_SURROUND: | 4402 | case AUTO_SEQ_SURROUND: |
4755 | spec->multiout.dac_nids[i] = 0x9; | 4403 | spec->private_dac_nids[i] = 0x9; |
4756 | break; | 4404 | break; |
4757 | case AUTO_SEQ_SIDE: | 4405 | case AUTO_SEQ_SIDE: |
4758 | spec->multiout.dac_nids[i] = 0xb; | 4406 | spec->private_dac_nids[i] = 0xb; |
4759 | break; | 4407 | break; |
4760 | } | 4408 | } |
4761 | } | 4409 | } |
@@ -4769,7 +4417,9 @@ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec, | |||
4769 | const struct auto_pin_cfg *cfg) | 4417 | const struct auto_pin_cfg *cfg) |
4770 | { | 4418 | { |
4771 | char name[32]; | 4419 | char name[32]; |
4772 | static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" }; | 4420 | static const char * const chname[4] = { |
4421 | "Front", "Surround", "C/LFE", "Side" | ||
4422 | }; | ||
4773 | hda_nid_t nid_vols[] = {0x8, 0x9, 0xa, 0xb}; | 4423 | hda_nid_t nid_vols[] = {0x8, 0x9, 0xa, 0xb}; |
4774 | hda_nid_t nid_mutes[] = {0x24, 0x25, 0x26, 0x27}; | 4424 | hda_nid_t nid_mutes[] = {0x24, 0x25, 0x26, 0x27}; |
4775 | hda_nid_t nid, nid_vol, nid_mute = 0; | 4425 | hda_nid_t nid, nid_vol, nid_mute = 0; |
@@ -4812,6 +4462,19 @@ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec, | |||
4812 | if (err < 0) | 4462 | if (err < 0) |
4813 | return err; | 4463 | return err; |
4814 | } else if (i == AUTO_SEQ_FRONT) { | 4464 | } else if (i == AUTO_SEQ_FRONT) { |
4465 | /* add control to mixer index 0 */ | ||
4466 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | ||
4467 | "Master Front Playback Volume", | ||
4468 | HDA_COMPOSE_AMP_VAL(0x21, 3, 5, | ||
4469 | HDA_INPUT)); | ||
4470 | if (err < 0) | ||
4471 | return err; | ||
4472 | err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, | ||
4473 | "Master Front Playback Switch", | ||
4474 | HDA_COMPOSE_AMP_VAL(0x21, 3, 5, | ||
4475 | HDA_INPUT)); | ||
4476 | if (err < 0) | ||
4477 | return err; | ||
4815 | /* Front */ | 4478 | /* Front */ |
4816 | sprintf(name, "%s Playback Volume", chname[i]); | 4479 | sprintf(name, "%s Playback Volume", chname[i]); |
4817 | err = via_add_control( | 4480 | err = via_add_control( |
@@ -4872,49 +4535,12 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
4872 | } | 4535 | } |
4873 | 4536 | ||
4874 | /* create playback/capture controls for input pins */ | 4537 | /* create playback/capture controls for input pins */ |
4875 | static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec, | 4538 | static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec, |
4876 | const struct auto_pin_cfg *cfg) | 4539 | const struct auto_pin_cfg *cfg) |
4877 | { | 4540 | { |
4878 | static char *labels[] = { | 4541 | static const hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff }; |
4879 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 4542 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, |
4880 | }; | 4543 | ARRAY_SIZE(pin_idxs)); |
4881 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
4882 | int i, err, idx = 0; | ||
4883 | |||
4884 | /* for internal loopback recording select */ | ||
4885 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
4886 | imux->items[imux->num_items].index = 5; | ||
4887 | imux->num_items++; | ||
4888 | |||
4889 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
4890 | if (!cfg->input_pins[i]) | ||
4891 | continue; | ||
4892 | |||
4893 | switch (cfg->input_pins[i]) { | ||
4894 | case 0x2b: /* Mic */ | ||
4895 | idx = 1; | ||
4896 | break; | ||
4897 | |||
4898 | case 0x2a: /* Line In */ | ||
4899 | idx = 2; | ||
4900 | break; | ||
4901 | |||
4902 | case 0x29: /* Front Mic */ | ||
4903 | idx = 3; | ||
4904 | break; | ||
4905 | |||
4906 | case 0x2c: /* CD */ | ||
4907 | idx = 0; | ||
4908 | break; | ||
4909 | } | ||
4910 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
4911 | if (err < 0) | ||
4912 | return err; | ||
4913 | imux->items[imux->num_items].label = labels[i]; | ||
4914 | imux->items[imux->num_items].index = idx; | ||
4915 | imux->num_items++; | ||
4916 | } | ||
4917 | return 0; | ||
4918 | } | 4544 | } |
4919 | 4545 | ||
4920 | static int vt1718S_parse_auto_config(struct hda_codec *codec) | 4546 | static int vt1718S_parse_auto_config(struct hda_codec *codec) |
@@ -4938,7 +4564,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) | |||
4938 | err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 4564 | err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
4939 | if (err < 0) | 4565 | if (err < 0) |
4940 | return err; | 4566 | return err; |
4941 | err = vt1718S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4567 | err = vt1718S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
4942 | if (err < 0) | 4568 | if (err < 0) |
4943 | return err; | 4569 | return err; |
4944 | 4570 | ||
@@ -4963,7 +4589,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) | |||
4963 | } | 4589 | } |
4964 | 4590 | ||
4965 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4591 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
4966 | static struct hda_amp_list vt1718S_loopbacks[] = { | 4592 | static const struct hda_amp_list vt1718S_loopbacks[] = { |
4967 | { 0x21, HDA_INPUT, 1 }, | 4593 | { 0x21, HDA_INPUT, 1 }, |
4968 | { 0x21, HDA_INPUT, 2 }, | 4594 | { 0x21, HDA_INPUT, 2 }, |
4969 | { 0x21, HDA_INPUT, 3 }, | 4595 | { 0x21, HDA_INPUT, 3 }, |
@@ -4972,6 +4598,72 @@ static struct hda_amp_list vt1718S_loopbacks[] = { | |||
4972 | }; | 4598 | }; |
4973 | #endif | 4599 | #endif |
4974 | 4600 | ||
4601 | static void set_widgets_power_state_vt1718S(struct hda_codec *codec) | ||
4602 | { | ||
4603 | struct via_spec *spec = codec->spec; | ||
4604 | int imux_is_smixer; | ||
4605 | unsigned int parm; | ||
4606 | /* MUX6 (1eh) = stereo mixer */ | ||
4607 | imux_is_smixer = | ||
4608 | snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; | ||
4609 | /* inputs */ | ||
4610 | /* PW 5/6/7 (29h/2ah/2bh) */ | ||
4611 | parm = AC_PWRST_D3; | ||
4612 | set_pin_power_state(codec, 0x29, &parm); | ||
4613 | set_pin_power_state(codec, 0x2a, &parm); | ||
4614 | set_pin_power_state(codec, 0x2b, &parm); | ||
4615 | if (imux_is_smixer) | ||
4616 | parm = AC_PWRST_D0; | ||
4617 | /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */ | ||
4618 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4619 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4620 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4621 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4622 | |||
4623 | /* outputs */ | ||
4624 | /* PW3 (27h), MW2 (1ah), AOW3 (bh) */ | ||
4625 | parm = AC_PWRST_D3; | ||
4626 | set_pin_power_state(codec, 0x27, &parm); | ||
4627 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4628 | snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4629 | |||
4630 | /* PW2 (26h), AOW2 (ah) */ | ||
4631 | parm = AC_PWRST_D3; | ||
4632 | set_pin_power_state(codec, 0x26, &parm); | ||
4633 | if (spec->smart51_enabled) | ||
4634 | set_pin_power_state(codec, 0x2b, &parm); | ||
4635 | snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4636 | |||
4637 | /* PW0 (24h), AOW0 (8h) */ | ||
4638 | parm = AC_PWRST_D3; | ||
4639 | set_pin_power_state(codec, 0x24, &parm); | ||
4640 | if (!spec->hp_independent_mode) /* check for redirected HP */ | ||
4641 | set_pin_power_state(codec, 0x28, &parm); | ||
4642 | snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4643 | /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ | ||
4644 | snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE, | ||
4645 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
4646 | |||
4647 | /* PW1 (25h), AOW1 (9h) */ | ||
4648 | parm = AC_PWRST_D3; | ||
4649 | set_pin_power_state(codec, 0x25, &parm); | ||
4650 | if (spec->smart51_enabled) | ||
4651 | set_pin_power_state(codec, 0x2a, &parm); | ||
4652 | snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm); | ||
4653 | |||
4654 | if (spec->hp_independent_mode) { | ||
4655 | /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */ | ||
4656 | parm = AC_PWRST_D3; | ||
4657 | set_pin_power_state(codec, 0x28, &parm); | ||
4658 | snd_hda_codec_write(codec, 0x1b, 0, | ||
4659 | AC_VERB_SET_POWER_STATE, parm); | ||
4660 | snd_hda_codec_write(codec, 0x34, 0, | ||
4661 | AC_VERB_SET_POWER_STATE, parm); | ||
4662 | snd_hda_codec_write(codec, 0xc, 0, | ||
4663 | AC_VERB_SET_POWER_STATE, parm); | ||
4664 | } | ||
4665 | } | ||
4666 | |||
4975 | static int patch_vt1718S(struct hda_codec *codec) | 4667 | static int patch_vt1718S(struct hda_codec *codec) |
4976 | { | 4668 | { |
4977 | struct via_spec *spec; | 4669 | struct via_spec *spec; |
@@ -5033,6 +4725,8 @@ static int patch_vt1718S(struct hda_codec *codec) | |||
5033 | spec->loopback.amplist = vt1718S_loopbacks; | 4725 | spec->loopback.amplist = vt1718S_loopbacks; |
5034 | #endif | 4726 | #endif |
5035 | 4727 | ||
4728 | spec->set_widgets_power_state = set_widgets_power_state_vt1718S; | ||
4729 | |||
5036 | return 0; | 4730 | return 0; |
5037 | } | 4731 | } |
5038 | 4732 | ||
@@ -5072,13 +4766,12 @@ static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol, | |||
5072 | snd_hda_codec_write(codec, 0x26, 0, | 4766 | snd_hda_codec_write(codec, 0x26, 0, |
5073 | AC_VERB_SET_CONNECT_SEL, index); | 4767 | AC_VERB_SET_CONNECT_SEL, index); |
5074 | spec->dmic_enabled = index; | 4768 | spec->dmic_enabled = index; |
5075 | set_jack_power_state(codec); | 4769 | set_widgets_power_state(codec); |
5076 | |||
5077 | return 1; | 4770 | return 1; |
5078 | } | 4771 | } |
5079 | 4772 | ||
5080 | /* capture mixer elements */ | 4773 | /* capture mixer elements */ |
5081 | static struct snd_kcontrol_new vt1716S_capture_mixer[] = { | 4774 | static const struct snd_kcontrol_new vt1716S_capture_mixer[] = { |
5082 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), | 4775 | HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT), |
5083 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), | 4776 | HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT), |
5084 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), | 4777 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT), |
@@ -5097,7 +4790,7 @@ static struct snd_kcontrol_new vt1716S_capture_mixer[] = { | |||
5097 | { } /* end */ | 4790 | { } /* end */ |
5098 | }; | 4791 | }; |
5099 | 4792 | ||
5100 | static struct snd_kcontrol_new vt1716s_dmic_mixer[] = { | 4793 | static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = { |
5101 | HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT), | 4794 | HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT), |
5102 | { | 4795 | { |
5103 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 4796 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -5113,12 +4806,12 @@ static struct snd_kcontrol_new vt1716s_dmic_mixer[] = { | |||
5113 | 4806 | ||
5114 | 4807 | ||
5115 | /* mono-out mixer elements */ | 4808 | /* mono-out mixer elements */ |
5116 | static struct snd_kcontrol_new vt1716S_mono_out_mixer[] = { | 4809 | static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = { |
5117 | HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT), | 4810 | HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT), |
5118 | { } /* end */ | 4811 | { } /* end */ |
5119 | }; | 4812 | }; |
5120 | 4813 | ||
5121 | static struct hda_verb vt1716S_volume_init_verbs[] = { | 4814 | static const struct hda_verb vt1716S_volume_init_verbs[] = { |
5122 | /* | 4815 | /* |
5123 | * Unmute ADC0-1 and set the default input to mic-in | 4816 | * Unmute ADC0-1 and set the default input to mic-in |
5124 | */ | 4817 | */ |
@@ -5167,7 +4860,7 @@ static struct hda_verb vt1716S_volume_init_verbs[] = { | |||
5167 | }; | 4860 | }; |
5168 | 4861 | ||
5169 | 4862 | ||
5170 | static struct hda_verb vt1716S_uniwill_init_verbs[] = { | 4863 | static const struct hda_verb vt1716S_uniwill_init_verbs[] = { |
5171 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, | 4864 | {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, |
5172 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, | 4865 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT}, |
5173 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | 4866 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, |
@@ -5180,7 +4873,7 @@ static struct hda_verb vt1716S_uniwill_init_verbs[] = { | |||
5180 | { } | 4873 | { } |
5181 | }; | 4874 | }; |
5182 | 4875 | ||
5183 | static struct hda_pcm_stream vt1716S_pcm_analog_playback = { | 4876 | static const struct hda_pcm_stream vt1716S_pcm_analog_playback = { |
5184 | .substreams = 2, | 4877 | .substreams = 2, |
5185 | .channels_min = 2, | 4878 | .channels_min = 2, |
5186 | .channels_max = 6, | 4879 | .channels_max = 6, |
@@ -5193,7 +4886,7 @@ static struct hda_pcm_stream vt1716S_pcm_analog_playback = { | |||
5193 | }, | 4886 | }, |
5194 | }; | 4887 | }; |
5195 | 4888 | ||
5196 | static struct hda_pcm_stream vt1716S_pcm_analog_capture = { | 4889 | static const struct hda_pcm_stream vt1716S_pcm_analog_capture = { |
5197 | .substreams = 2, | 4890 | .substreams = 2, |
5198 | .channels_min = 2, | 4891 | .channels_min = 2, |
5199 | .channels_max = 2, | 4892 | .channels_max = 2, |
@@ -5206,7 +4899,7 @@ static struct hda_pcm_stream vt1716S_pcm_analog_capture = { | |||
5206 | }, | 4899 | }, |
5207 | }; | 4900 | }; |
5208 | 4901 | ||
5209 | static struct hda_pcm_stream vt1716S_pcm_digital_playback = { | 4902 | static const struct hda_pcm_stream vt1716S_pcm_digital_playback = { |
5210 | .substreams = 2, | 4903 | .substreams = 2, |
5211 | .channels_min = 2, | 4904 | .channels_min = 2, |
5212 | .channels_max = 2, | 4905 | .channels_max = 2, |
@@ -5235,13 +4928,13 @@ static int vt1716S_auto_fill_dac_nids(struct via_spec *spec, | |||
5235 | /* config dac list */ | 4928 | /* config dac list */ |
5236 | switch (i) { | 4929 | switch (i) { |
5237 | case AUTO_SEQ_FRONT: | 4930 | case AUTO_SEQ_FRONT: |
5238 | spec->multiout.dac_nids[i] = 0x10; | 4931 | spec->private_dac_nids[i] = 0x10; |
5239 | break; | 4932 | break; |
5240 | case AUTO_SEQ_CENLFE: | 4933 | case AUTO_SEQ_CENLFE: |
5241 | spec->multiout.dac_nids[i] = 0x25; | 4934 | spec->private_dac_nids[i] = 0x25; |
5242 | break; | 4935 | break; |
5243 | case AUTO_SEQ_SURROUND: | 4936 | case AUTO_SEQ_SURROUND: |
5244 | spec->multiout.dac_nids[i] = 0x11; | 4937 | spec->private_dac_nids[i] = 0x11; |
5245 | break; | 4938 | break; |
5246 | } | 4939 | } |
5247 | } | 4940 | } |
@@ -5255,7 +4948,9 @@ static int vt1716S_auto_create_multi_out_ctls(struct via_spec *spec, | |||
5255 | const struct auto_pin_cfg *cfg) | 4948 | const struct auto_pin_cfg *cfg) |
5256 | { | 4949 | { |
5257 | char name[32]; | 4950 | char name[32]; |
5258 | static const char *chname[3] = { "Front", "Surround", "C/LFE" }; | 4951 | static const char * const chname[3] = { |
4952 | "Front", "Surround", "C/LFE" | ||
4953 | }; | ||
5259 | hda_nid_t nid_vols[] = {0x10, 0x11, 0x25}; | 4954 | hda_nid_t nid_vols[] = {0x10, 0x11, 0x25}; |
5260 | hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x27}; | 4955 | hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x27}; |
5261 | hda_nid_t nid, nid_vol, nid_mute; | 4956 | hda_nid_t nid, nid_vol, nid_mute; |
@@ -5371,49 +5066,12 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
5371 | } | 5066 | } |
5372 | 5067 | ||
5373 | /* create playback/capture controls for input pins */ | 5068 | /* create playback/capture controls for input pins */ |
5374 | static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec, | 5069 | static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec, |
5375 | const struct auto_pin_cfg *cfg) | 5070 | const struct auto_pin_cfg *cfg) |
5376 | { | 5071 | { |
5377 | static char *labels[] = { | 5072 | static const hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; |
5378 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 5073 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
5379 | }; | 5074 | ARRAY_SIZE(pin_idxs)); |
5380 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
5381 | int i, err, idx = 0; | ||
5382 | |||
5383 | /* for internal loopback recording select */ | ||
5384 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
5385 | imux->items[imux->num_items].index = 5; | ||
5386 | imux->num_items++; | ||
5387 | |||
5388 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
5389 | if (!cfg->input_pins[i]) | ||
5390 | continue; | ||
5391 | |||
5392 | switch (cfg->input_pins[i]) { | ||
5393 | case 0x1a: /* Mic */ | ||
5394 | idx = 2; | ||
5395 | break; | ||
5396 | |||
5397 | case 0x1b: /* Line In */ | ||
5398 | idx = 3; | ||
5399 | break; | ||
5400 | |||
5401 | case 0x1e: /* Front Mic */ | ||
5402 | idx = 4; | ||
5403 | break; | ||
5404 | |||
5405 | case 0x1f: /* CD */ | ||
5406 | idx = 1; | ||
5407 | break; | ||
5408 | } | ||
5409 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
5410 | if (err < 0) | ||
5411 | return err; | ||
5412 | imux->items[imux->num_items].label = labels[i]; | ||
5413 | imux->items[imux->num_items].index = idx-1; | ||
5414 | imux->num_items++; | ||
5415 | } | ||
5416 | return 0; | ||
5417 | } | 5075 | } |
5418 | 5076 | ||
5419 | static int vt1716S_parse_auto_config(struct hda_codec *codec) | 5077 | static int vt1716S_parse_auto_config(struct hda_codec *codec) |
@@ -5436,7 +5094,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) | |||
5436 | err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5094 | err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
5437 | if (err < 0) | 5095 | if (err < 0) |
5438 | return err; | 5096 | return err; |
5439 | err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5097 | err = vt1716S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
5440 | if (err < 0) | 5098 | if (err < 0) |
5441 | return err; | 5099 | return err; |
5442 | 5100 | ||
@@ -5458,7 +5116,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) | |||
5458 | } | 5116 | } |
5459 | 5117 | ||
5460 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5118 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5461 | static struct hda_amp_list vt1716S_loopbacks[] = { | 5119 | static const struct hda_amp_list vt1716S_loopbacks[] = { |
5462 | { 0x16, HDA_INPUT, 1 }, | 5120 | { 0x16, HDA_INPUT, 1 }, |
5463 | { 0x16, HDA_INPUT, 2 }, | 5121 | { 0x16, HDA_INPUT, 2 }, |
5464 | { 0x16, HDA_INPUT, 3 }, | 5122 | { 0x16, HDA_INPUT, 3 }, |
@@ -5467,6 +5125,99 @@ static struct hda_amp_list vt1716S_loopbacks[] = { | |||
5467 | }; | 5125 | }; |
5468 | #endif | 5126 | #endif |
5469 | 5127 | ||
5128 | static void set_widgets_power_state_vt1716S(struct hda_codec *codec) | ||
5129 | { | ||
5130 | struct via_spec *spec = codec->spec; | ||
5131 | int imux_is_smixer; | ||
5132 | unsigned int parm; | ||
5133 | unsigned int mono_out, present; | ||
5134 | /* SW0 (17h) = stereo mixer */ | ||
5135 | imux_is_smixer = | ||
5136 | (snd_hda_codec_read(codec, 0x17, 0, | ||
5137 | AC_VERB_GET_CONNECT_SEL, 0x00) == 5); | ||
5138 | /* inputs */ | ||
5139 | /* PW 1/2/5 (1ah/1bh/1eh) */ | ||
5140 | parm = AC_PWRST_D3; | ||
5141 | set_pin_power_state(codec, 0x1a, &parm); | ||
5142 | set_pin_power_state(codec, 0x1b, &parm); | ||
5143 | set_pin_power_state(codec, 0x1e, &parm); | ||
5144 | if (imux_is_smixer) | ||
5145 | parm = AC_PWRST_D0; | ||
5146 | /* SW0 (17h), AIW0(13h) */ | ||
5147 | snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5148 | snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5149 | |||
5150 | parm = AC_PWRST_D3; | ||
5151 | set_pin_power_state(codec, 0x1e, &parm); | ||
5152 | /* PW11 (22h) */ | ||
5153 | if (spec->dmic_enabled) | ||
5154 | set_pin_power_state(codec, 0x22, &parm); | ||
5155 | else | ||
5156 | snd_hda_codec_write(codec, 0x22, 0, | ||
5157 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
5158 | |||
5159 | /* SW2(26h), AIW1(14h) */ | ||
5160 | snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5161 | snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5162 | |||
5163 | /* outputs */ | ||
5164 | /* PW0 (19h), SW1 (18h), AOW1 (11h) */ | ||
5165 | parm = AC_PWRST_D3; | ||
5166 | set_pin_power_state(codec, 0x19, &parm); | ||
5167 | /* Smart 5.1 PW2(1bh) */ | ||
5168 | if (spec->smart51_enabled) | ||
5169 | set_pin_power_state(codec, 0x1b, &parm); | ||
5170 | snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5171 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5172 | |||
5173 | /* PW7 (23h), SW3 (27h), AOW3 (25h) */ | ||
5174 | parm = AC_PWRST_D3; | ||
5175 | set_pin_power_state(codec, 0x23, &parm); | ||
5176 | /* Smart 5.1 PW1(1ah) */ | ||
5177 | if (spec->smart51_enabled) | ||
5178 | set_pin_power_state(codec, 0x1a, &parm); | ||
5179 | snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5180 | |||
5181 | /* Smart 5.1 PW5(1eh) */ | ||
5182 | if (spec->smart51_enabled) | ||
5183 | set_pin_power_state(codec, 0x1e, &parm); | ||
5184 | snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5185 | |||
5186 | /* Mono out */ | ||
5187 | /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/ | ||
5188 | present = snd_hda_jack_detect(codec, 0x1c); | ||
5189 | |||
5190 | if (present) | ||
5191 | mono_out = 0; | ||
5192 | else { | ||
5193 | present = snd_hda_jack_detect(codec, 0x1d); | ||
5194 | if (!spec->hp_independent_mode && present) | ||
5195 | mono_out = 0; | ||
5196 | else | ||
5197 | mono_out = 1; | ||
5198 | } | ||
5199 | parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3; | ||
5200 | snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5201 | snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5202 | snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5203 | |||
5204 | /* PW 3/4 (1ch/1dh) */ | ||
5205 | parm = AC_PWRST_D3; | ||
5206 | set_pin_power_state(codec, 0x1c, &parm); | ||
5207 | set_pin_power_state(codec, 0x1d, &parm); | ||
5208 | /* HP Independent Mode, power on AOW3 */ | ||
5209 | if (spec->hp_independent_mode) | ||
5210 | snd_hda_codec_write(codec, 0x25, 0, | ||
5211 | AC_VERB_SET_POWER_STATE, parm); | ||
5212 | |||
5213 | /* force to D0 for internal Speaker */ | ||
5214 | /* MW0 (16h), AOW0 (10h) */ | ||
5215 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, | ||
5216 | imux_is_smixer ? AC_PWRST_D0 : parm); | ||
5217 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, | ||
5218 | mono_out ? AC_PWRST_D0 : parm); | ||
5219 | } | ||
5220 | |||
5470 | static int patch_vt1716S(struct hda_codec *codec) | 5221 | static int patch_vt1716S(struct hda_codec *codec) |
5471 | { | 5222 | { |
5472 | struct via_spec *spec; | 5223 | struct via_spec *spec; |
@@ -5521,13 +5272,14 @@ static int patch_vt1716S(struct hda_codec *codec) | |||
5521 | spec->loopback.amplist = vt1716S_loopbacks; | 5272 | spec->loopback.amplist = vt1716S_loopbacks; |
5522 | #endif | 5273 | #endif |
5523 | 5274 | ||
5275 | spec->set_widgets_power_state = set_widgets_power_state_vt1716S; | ||
5524 | return 0; | 5276 | return 0; |
5525 | } | 5277 | } |
5526 | 5278 | ||
5527 | /* for vt2002P */ | 5279 | /* for vt2002P */ |
5528 | 5280 | ||
5529 | /* capture mixer elements */ | 5281 | /* capture mixer elements */ |
5530 | static struct snd_kcontrol_new vt2002P_capture_mixer[] = { | 5282 | static const struct snd_kcontrol_new vt2002P_capture_mixer[] = { |
5531 | HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT), | 5283 | HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT), |
5532 | HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT), | 5284 | HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT), |
5533 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT), | 5285 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT), |
@@ -5550,7 +5302,11 @@ static struct snd_kcontrol_new vt2002P_capture_mixer[] = { | |||
5550 | { } /* end */ | 5302 | { } /* end */ |
5551 | }; | 5303 | }; |
5552 | 5304 | ||
5553 | static struct hda_verb vt2002P_volume_init_verbs[] = { | 5305 | static const struct hda_verb vt2002P_volume_init_verbs[] = { |
5306 | /* Class-D speaker related verbs */ | ||
5307 | {0x1, 0xfe0, 0x4}, | ||
5308 | {0x1, 0xfe9, 0x80}, | ||
5309 | {0x1, 0xfe2, 0x22}, | ||
5554 | /* | 5310 | /* |
5555 | * Unmute ADC0-1 and set the default input to mic-in | 5311 | * Unmute ADC0-1 and set the default input to mic-in |
5556 | */ | 5312 | */ |
@@ -5601,9 +5357,60 @@ static struct hda_verb vt2002P_volume_init_verbs[] = { | |||
5601 | {0x1, 0xfb8, 0x88}, | 5357 | {0x1, 0xfb8, 0x88}, |
5602 | { } | 5358 | { } |
5603 | }; | 5359 | }; |
5360 | static const struct hda_verb vt1802_volume_init_verbs[] = { | ||
5361 | /* | ||
5362 | * Unmute ADC0-1 and set the default input to mic-in | ||
5363 | */ | ||
5364 | {0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5365 | {0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5604 | 5366 | ||
5605 | 5367 | ||
5606 | static struct hda_verb vt2002P_uniwill_init_verbs[] = { | 5368 | /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
5369 | * mixer widget | ||
5370 | */ | ||
5371 | /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */ | ||
5372 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
5373 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
5374 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
5375 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
5376 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
5377 | |||
5378 | /* MUX Indices: Mic = 0 */ | ||
5379 | {0x1e, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5380 | {0x1f, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5381 | |||
5382 | /* PW9 Output enable */ | ||
5383 | {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN}, | ||
5384 | |||
5385 | /* Enable Boost Volume backdoor */ | ||
5386 | {0x1, 0xfb9, 0x24}, | ||
5387 | |||
5388 | /* MW0/1/4/8: un-mute index 0 (MUXx), un-mute index 1 (MW9) */ | ||
5389 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5390 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5391 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5392 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
5393 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5394 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5395 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5396 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
5397 | |||
5398 | /* set MUX0/1/4/8 = 0 (AOW0) */ | ||
5399 | {0x34, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5400 | {0x35, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5401 | {0x38, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5402 | {0x3c, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5403 | |||
5404 | /* set PW0 index=0 (MW0) */ | ||
5405 | {0x24, AC_VERB_SET_CONNECT_SEL, 0}, | ||
5406 | |||
5407 | /* Enable AOW0 to MW9 */ | ||
5408 | {0x1, 0xfb8, 0x88}, | ||
5409 | { } | ||
5410 | }; | ||
5411 | |||
5412 | |||
5413 | static const struct hda_verb vt2002P_uniwill_init_verbs[] = { | ||
5607 | {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, | 5414 | {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, |
5608 | AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT}, | 5415 | AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT}, |
5609 | {0x26, AC_VERB_SET_UNSOLICITED_ENABLE, | 5416 | {0x26, AC_VERB_SET_UNSOLICITED_ENABLE, |
@@ -5613,8 +5420,18 @@ static struct hda_verb vt2002P_uniwill_init_verbs[] = { | |||
5613 | {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | 5420 | {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, |
5614 | { } | 5421 | { } |
5615 | }; | 5422 | }; |
5423 | static const struct hda_verb vt1802_uniwill_init_verbs[] = { | ||
5424 | {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, | ||
5425 | AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT}, | ||
5426 | {0x28, AC_VERB_SET_UNSOLICITED_ENABLE, | ||
5427 | AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT}, | ||
5428 | {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
5429 | {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
5430 | {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT}, | ||
5431 | { } | ||
5432 | }; | ||
5616 | 5433 | ||
5617 | static struct hda_pcm_stream vt2002P_pcm_analog_playback = { | 5434 | static const struct hda_pcm_stream vt2002P_pcm_analog_playback = { |
5618 | .substreams = 2, | 5435 | .substreams = 2, |
5619 | .channels_min = 2, | 5436 | .channels_min = 2, |
5620 | .channels_max = 2, | 5437 | .channels_max = 2, |
@@ -5627,7 +5444,7 @@ static struct hda_pcm_stream vt2002P_pcm_analog_playback = { | |||
5627 | }, | 5444 | }, |
5628 | }; | 5445 | }; |
5629 | 5446 | ||
5630 | static struct hda_pcm_stream vt2002P_pcm_analog_capture = { | 5447 | static const struct hda_pcm_stream vt2002P_pcm_analog_capture = { |
5631 | .substreams = 2, | 5448 | .substreams = 2, |
5632 | .channels_min = 2, | 5449 | .channels_min = 2, |
5633 | .channels_max = 2, | 5450 | .channels_max = 2, |
@@ -5640,7 +5457,7 @@ static struct hda_pcm_stream vt2002P_pcm_analog_capture = { | |||
5640 | }, | 5457 | }, |
5641 | }; | 5458 | }; |
5642 | 5459 | ||
5643 | static struct hda_pcm_stream vt2002P_pcm_digital_playback = { | 5460 | static const struct hda_pcm_stream vt2002P_pcm_digital_playback = { |
5644 | .substreams = 1, | 5461 | .substreams = 1, |
5645 | .channels_min = 2, | 5462 | .channels_min = 2, |
5646 | .channels_max = 2, | 5463 | .channels_max = 2, |
@@ -5660,7 +5477,7 @@ static int vt2002P_auto_fill_dac_nids(struct via_spec *spec, | |||
5660 | spec->multiout.num_dacs = 1; | 5477 | spec->multiout.num_dacs = 1; |
5661 | spec->multiout.dac_nids = spec->private_dac_nids; | 5478 | spec->multiout.dac_nids = spec->private_dac_nids; |
5662 | if (cfg->line_out_pins[0]) | 5479 | if (cfg->line_out_pins[0]) |
5663 | spec->multiout.dac_nids[0] = 0x8; | 5480 | spec->private_dac_nids[0] = 0x8; |
5664 | return 0; | 5481 | return 0; |
5665 | } | 5482 | } |
5666 | 5483 | ||
@@ -5669,10 +5486,15 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec, | |||
5669 | const struct auto_pin_cfg *cfg) | 5486 | const struct auto_pin_cfg *cfg) |
5670 | { | 5487 | { |
5671 | int err; | 5488 | int err; |
5489 | hda_nid_t sw_nid; | ||
5672 | 5490 | ||
5673 | if (!cfg->line_out_pins[0]) | 5491 | if (!cfg->line_out_pins[0]) |
5674 | return -1; | 5492 | return -1; |
5675 | 5493 | ||
5494 | if (spec->codec_type == VT1802) | ||
5495 | sw_nid = 0x28; | ||
5496 | else | ||
5497 | sw_nid = 0x26; | ||
5676 | 5498 | ||
5677 | /* Line-Out: PortE */ | 5499 | /* Line-Out: PortE */ |
5678 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, | 5500 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, |
@@ -5682,7 +5504,7 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec, | |||
5682 | return err; | 5504 | return err; |
5683 | err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE, | 5505 | err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE, |
5684 | "Master Front Playback Switch", | 5506 | "Master Front Playback Switch", |
5685 | HDA_COMPOSE_AMP_VAL(0x26, 3, 0, HDA_OUTPUT)); | 5507 | HDA_COMPOSE_AMP_VAL(sw_nid, 3, 0, HDA_OUTPUT)); |
5686 | if (err < 0) | 5508 | if (err < 0) |
5687 | return err; | 5509 | return err; |
5688 | 5510 | ||
@@ -5717,54 +5539,25 @@ static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
5717 | } | 5539 | } |
5718 | 5540 | ||
5719 | /* create playback/capture controls for input pins */ | 5541 | /* create playback/capture controls for input pins */ |
5720 | static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec, | 5542 | static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec, |
5721 | const struct auto_pin_cfg *cfg) | 5543 | const struct auto_pin_cfg *cfg) |
5722 | { | 5544 | { |
5723 | static char *labels[] = { | 5545 | struct via_spec *spec = codec->spec; |
5724 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
5725 | }; | ||
5726 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5546 | struct hda_input_mux *imux = &spec->private_imux[0]; |
5727 | int i, err, idx = 0; | 5547 | static const hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff }; |
5728 | 5548 | int err; | |
5729 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
5730 | if (!cfg->input_pins[i]) | ||
5731 | continue; | ||
5732 | |||
5733 | switch (cfg->input_pins[i]) { | ||
5734 | case 0x2b: /* Mic */ | ||
5735 | idx = 0; | ||
5736 | break; | ||
5737 | |||
5738 | case 0x2a: /* Line In */ | ||
5739 | idx = 1; | ||
5740 | break; | ||
5741 | |||
5742 | case 0x29: /* Front Mic */ | ||
5743 | idx = 2; | ||
5744 | break; | ||
5745 | } | ||
5746 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
5747 | if (err < 0) | ||
5748 | return err; | ||
5749 | imux->items[imux->num_items].label = labels[i]; | ||
5750 | imux->items[imux->num_items].index = idx; | ||
5751 | imux->num_items++; | ||
5752 | } | ||
5753 | 5549 | ||
5550 | err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, | ||
5551 | ARRAY_SIZE(pin_idxs)); | ||
5552 | if (err < 0) | ||
5553 | return err; | ||
5754 | /* build volume/mute control of loopback */ | 5554 | /* build volume/mute control of loopback */ |
5755 | err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21); | 5555 | err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21); |
5756 | if (err < 0) | 5556 | if (err < 0) |
5757 | return err; | 5557 | return err; |
5758 | 5558 | ||
5759 | /* for internal loopback recording select */ | ||
5760 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
5761 | imux->items[imux->num_items].index = 3; | ||
5762 | imux->num_items++; | ||
5763 | |||
5764 | /* for digital mic select */ | 5559 | /* for digital mic select */ |
5765 | imux->items[imux->num_items].label = "Digital Mic"; | 5560 | snd_hda_add_imux_item(imux, "Digital Mic", 4, NULL); |
5766 | imux->items[imux->num_items].index = 4; | ||
5767 | imux->num_items++; | ||
5768 | 5561 | ||
5769 | return 0; | 5562 | return 0; |
5770 | } | 5563 | } |
@@ -5792,7 +5585,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) | |||
5792 | err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5585 | err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
5793 | if (err < 0) | 5586 | if (err < 0) |
5794 | return err; | 5587 | return err; |
5795 | err = vt2002P_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5588 | err = vt2002P_auto_create_analog_input_ctls(codec, &spec->autocfg); |
5796 | if (err < 0) | 5589 | if (err < 0) |
5797 | return err; | 5590 | return err; |
5798 | 5591 | ||
@@ -5812,7 +5605,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) | |||
5812 | } | 5605 | } |
5813 | 5606 | ||
5814 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5607 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5815 | static struct hda_amp_list vt2002P_loopbacks[] = { | 5608 | static const struct hda_amp_list vt2002P_loopbacks[] = { |
5816 | { 0x21, HDA_INPUT, 0 }, | 5609 | { 0x21, HDA_INPUT, 0 }, |
5817 | { 0x21, HDA_INPUT, 1 }, | 5610 | { 0x21, HDA_INPUT, 1 }, |
5818 | { 0x21, HDA_INPUT, 2 }, | 5611 | { 0x21, HDA_INPUT, 2 }, |
@@ -5820,6 +5613,116 @@ static struct hda_amp_list vt2002P_loopbacks[] = { | |||
5820 | }; | 5613 | }; |
5821 | #endif | 5614 | #endif |
5822 | 5615 | ||
5616 | static void set_widgets_power_state_vt2002P(struct hda_codec *codec) | ||
5617 | { | ||
5618 | struct via_spec *spec = codec->spec; | ||
5619 | int imux_is_smixer; | ||
5620 | unsigned int parm; | ||
5621 | unsigned int present; | ||
5622 | /* MUX9 (1eh) = stereo mixer */ | ||
5623 | imux_is_smixer = | ||
5624 | snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3; | ||
5625 | /* inputs */ | ||
5626 | /* PW 5/6/7 (29h/2ah/2bh) */ | ||
5627 | parm = AC_PWRST_D3; | ||
5628 | set_pin_power_state(codec, 0x29, &parm); | ||
5629 | set_pin_power_state(codec, 0x2a, &parm); | ||
5630 | set_pin_power_state(codec, 0x2b, &parm); | ||
5631 | parm = AC_PWRST_D0; | ||
5632 | /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */ | ||
5633 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5634 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5635 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5636 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5637 | |||
5638 | /* outputs */ | ||
5639 | /* AOW0 (8h)*/ | ||
5640 | snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5641 | |||
5642 | if (spec->codec_type == VT1802) { | ||
5643 | /* PW4 (28h), MW4 (18h), MUX4(38h) */ | ||
5644 | parm = AC_PWRST_D3; | ||
5645 | set_pin_power_state(codec, 0x28, &parm); | ||
5646 | snd_hda_codec_write(codec, 0x18, 0, | ||
5647 | AC_VERB_SET_POWER_STATE, parm); | ||
5648 | snd_hda_codec_write(codec, 0x38, 0, | ||
5649 | AC_VERB_SET_POWER_STATE, parm); | ||
5650 | } else { | ||
5651 | /* PW4 (26h), MW4 (1ch), MUX4(37h) */ | ||
5652 | parm = AC_PWRST_D3; | ||
5653 | set_pin_power_state(codec, 0x26, &parm); | ||
5654 | snd_hda_codec_write(codec, 0x1c, 0, | ||
5655 | AC_VERB_SET_POWER_STATE, parm); | ||
5656 | snd_hda_codec_write(codec, 0x37, 0, | ||
5657 | AC_VERB_SET_POWER_STATE, parm); | ||
5658 | } | ||
5659 | |||
5660 | if (spec->codec_type == VT1802) { | ||
5661 | /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ | ||
5662 | parm = AC_PWRST_D3; | ||
5663 | set_pin_power_state(codec, 0x25, &parm); | ||
5664 | snd_hda_codec_write(codec, 0x15, 0, | ||
5665 | AC_VERB_SET_POWER_STATE, parm); | ||
5666 | snd_hda_codec_write(codec, 0x35, 0, | ||
5667 | AC_VERB_SET_POWER_STATE, parm); | ||
5668 | } else { | ||
5669 | /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */ | ||
5670 | parm = AC_PWRST_D3; | ||
5671 | set_pin_power_state(codec, 0x25, &parm); | ||
5672 | snd_hda_codec_write(codec, 0x19, 0, | ||
5673 | AC_VERB_SET_POWER_STATE, parm); | ||
5674 | snd_hda_codec_write(codec, 0x35, 0, | ||
5675 | AC_VERB_SET_POWER_STATE, parm); | ||
5676 | } | ||
5677 | |||
5678 | if (spec->hp_independent_mode) | ||
5679 | snd_hda_codec_write(codec, 0x9, 0, | ||
5680 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
5681 | |||
5682 | /* Class-D */ | ||
5683 | /* PW0 (24h), MW0(18h/14h), MUX0(34h) */ | ||
5684 | present = snd_hda_jack_detect(codec, 0x25); | ||
5685 | |||
5686 | parm = AC_PWRST_D3; | ||
5687 | set_pin_power_state(codec, 0x24, &parm); | ||
5688 | parm = present ? AC_PWRST_D3 : AC_PWRST_D0; | ||
5689 | if (spec->codec_type == VT1802) | ||
5690 | snd_hda_codec_write(codec, 0x14, 0, | ||
5691 | AC_VERB_SET_POWER_STATE, parm); | ||
5692 | else | ||
5693 | snd_hda_codec_write(codec, 0x18, 0, | ||
5694 | AC_VERB_SET_POWER_STATE, parm); | ||
5695 | snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm); | ||
5696 | |||
5697 | /* Mono Out */ | ||
5698 | present = snd_hda_jack_detect(codec, 0x26); | ||
5699 | |||
5700 | parm = present ? AC_PWRST_D3 : AC_PWRST_D0; | ||
5701 | if (spec->codec_type == VT1802) { | ||
5702 | /* PW15 (33h), MW8(1ch), MUX8(3ch) */ | ||
5703 | snd_hda_codec_write(codec, 0x33, 0, | ||
5704 | AC_VERB_SET_POWER_STATE, parm); | ||
5705 | snd_hda_codec_write(codec, 0x1c, 0, | ||
5706 | AC_VERB_SET_POWER_STATE, parm); | ||
5707 | snd_hda_codec_write(codec, 0x3c, 0, | ||
5708 | AC_VERB_SET_POWER_STATE, parm); | ||
5709 | } else { | ||
5710 | /* PW15 (31h), MW8(17h), MUX8(3bh) */ | ||
5711 | snd_hda_codec_write(codec, 0x31, 0, | ||
5712 | AC_VERB_SET_POWER_STATE, parm); | ||
5713 | snd_hda_codec_write(codec, 0x17, 0, | ||
5714 | AC_VERB_SET_POWER_STATE, parm); | ||
5715 | snd_hda_codec_write(codec, 0x3b, 0, | ||
5716 | AC_VERB_SET_POWER_STATE, parm); | ||
5717 | } | ||
5718 | /* MW9 (21h) */ | ||
5719 | if (imux_is_smixer || !is_aa_path_mute(codec)) | ||
5720 | snd_hda_codec_write(codec, 0x21, 0, | ||
5721 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
5722 | else | ||
5723 | snd_hda_codec_write(codec, 0x21, 0, | ||
5724 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
5725 | } | ||
5823 | 5726 | ||
5824 | /* patch for vt2002P */ | 5727 | /* patch for vt2002P */ |
5825 | static int patch_vt2002P(struct hda_codec *codec) | 5728 | static int patch_vt2002P(struct hda_codec *codec) |
@@ -5842,14 +5745,31 @@ static int patch_vt2002P(struct hda_codec *codec) | |||
5842 | "from BIOS. Using genenic mode...\n"); | 5745 | "from BIOS. Using genenic mode...\n"); |
5843 | } | 5746 | } |
5844 | 5747 | ||
5845 | spec->init_verbs[spec->num_iverbs++] = vt2002P_volume_init_verbs; | 5748 | if (spec->codec_type == VT1802) |
5846 | spec->init_verbs[spec->num_iverbs++] = vt2002P_uniwill_init_verbs; | 5749 | spec->init_verbs[spec->num_iverbs++] = |
5750 | vt1802_volume_init_verbs; | ||
5751 | else | ||
5752 | spec->init_verbs[spec->num_iverbs++] = | ||
5753 | vt2002P_volume_init_verbs; | ||
5754 | |||
5755 | if (spec->codec_type == VT1802) | ||
5756 | spec->init_verbs[spec->num_iverbs++] = | ||
5757 | vt1802_uniwill_init_verbs; | ||
5758 | else | ||
5759 | spec->init_verbs[spec->num_iverbs++] = | ||
5760 | vt2002P_uniwill_init_verbs; | ||
5847 | 5761 | ||
5848 | spec->stream_name_analog = "VT2002P Analog"; | 5762 | if (spec->codec_type == VT1802) |
5763 | spec->stream_name_analog = "VT1802 Analog"; | ||
5764 | else | ||
5765 | spec->stream_name_analog = "VT2002P Analog"; | ||
5849 | spec->stream_analog_playback = &vt2002P_pcm_analog_playback; | 5766 | spec->stream_analog_playback = &vt2002P_pcm_analog_playback; |
5850 | spec->stream_analog_capture = &vt2002P_pcm_analog_capture; | 5767 | spec->stream_analog_capture = &vt2002P_pcm_analog_capture; |
5851 | 5768 | ||
5852 | spec->stream_name_digital = "VT2002P Digital"; | 5769 | if (spec->codec_type == VT1802) |
5770 | spec->stream_name_digital = "VT1802 Digital"; | ||
5771 | else | ||
5772 | spec->stream_name_digital = "VT2002P Digital"; | ||
5853 | spec->stream_digital_playback = &vt2002P_pcm_digital_playback; | 5773 | spec->stream_digital_playback = &vt2002P_pcm_digital_playback; |
5854 | 5774 | ||
5855 | if (!spec->adc_nids && spec->input_mux) { | 5775 | if (!spec->adc_nids && spec->input_mux) { |
@@ -5871,13 +5791,14 @@ static int patch_vt2002P(struct hda_codec *codec) | |||
5871 | spec->loopback.amplist = vt2002P_loopbacks; | 5791 | spec->loopback.amplist = vt2002P_loopbacks; |
5872 | #endif | 5792 | #endif |
5873 | 5793 | ||
5794 | spec->set_widgets_power_state = set_widgets_power_state_vt2002P; | ||
5874 | return 0; | 5795 | return 0; |
5875 | } | 5796 | } |
5876 | 5797 | ||
5877 | /* for vt1812 */ | 5798 | /* for vt1812 */ |
5878 | 5799 | ||
5879 | /* capture mixer elements */ | 5800 | /* capture mixer elements */ |
5880 | static struct snd_kcontrol_new vt1812_capture_mixer[] = { | 5801 | static const struct snd_kcontrol_new vt1812_capture_mixer[] = { |
5881 | HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT), | 5802 | HDA_CODEC_VOLUME("Capture Volume", 0x10, 0x0, HDA_INPUT), |
5882 | HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT), | 5803 | HDA_CODEC_MUTE("Capture Switch", 0x10, 0x0, HDA_INPUT), |
5883 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT), | 5804 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x11, 0x0, HDA_INPUT), |
@@ -5899,7 +5820,7 @@ static struct snd_kcontrol_new vt1812_capture_mixer[] = { | |||
5899 | { } /* end */ | 5820 | { } /* end */ |
5900 | }; | 5821 | }; |
5901 | 5822 | ||
5902 | static struct hda_verb vt1812_volume_init_verbs[] = { | 5823 | static const struct hda_verb vt1812_volume_init_verbs[] = { |
5903 | /* | 5824 | /* |
5904 | * Unmute ADC0-1 and set the default input to mic-in | 5825 | * Unmute ADC0-1 and set the default input to mic-in |
5905 | */ | 5826 | */ |
@@ -5952,7 +5873,7 @@ static struct hda_verb vt1812_volume_init_verbs[] = { | |||
5952 | }; | 5873 | }; |
5953 | 5874 | ||
5954 | 5875 | ||
5955 | static struct hda_verb vt1812_uniwill_init_verbs[] = { | 5876 | static const struct hda_verb vt1812_uniwill_init_verbs[] = { |
5956 | {0x33, AC_VERB_SET_UNSOLICITED_ENABLE, | 5877 | {0x33, AC_VERB_SET_UNSOLICITED_ENABLE, |
5957 | AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT}, | 5878 | AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT}, |
5958 | {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT }, | 5879 | {0x25, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT }, |
@@ -5964,7 +5885,7 @@ static struct hda_verb vt1812_uniwill_init_verbs[] = { | |||
5964 | { } | 5885 | { } |
5965 | }; | 5886 | }; |
5966 | 5887 | ||
5967 | static struct hda_pcm_stream vt1812_pcm_analog_playback = { | 5888 | static const struct hda_pcm_stream vt1812_pcm_analog_playback = { |
5968 | .substreams = 2, | 5889 | .substreams = 2, |
5969 | .channels_min = 2, | 5890 | .channels_min = 2, |
5970 | .channels_max = 2, | 5891 | .channels_max = 2, |
@@ -5977,7 +5898,7 @@ static struct hda_pcm_stream vt1812_pcm_analog_playback = { | |||
5977 | }, | 5898 | }, |
5978 | }; | 5899 | }; |
5979 | 5900 | ||
5980 | static struct hda_pcm_stream vt1812_pcm_analog_capture = { | 5901 | static const struct hda_pcm_stream vt1812_pcm_analog_capture = { |
5981 | .substreams = 2, | 5902 | .substreams = 2, |
5982 | .channels_min = 2, | 5903 | .channels_min = 2, |
5983 | .channels_max = 2, | 5904 | .channels_max = 2, |
@@ -5990,7 +5911,7 @@ static struct hda_pcm_stream vt1812_pcm_analog_capture = { | |||
5990 | }, | 5911 | }, |
5991 | }; | 5912 | }; |
5992 | 5913 | ||
5993 | static struct hda_pcm_stream vt1812_pcm_digital_playback = { | 5914 | static const struct hda_pcm_stream vt1812_pcm_digital_playback = { |
5994 | .substreams = 1, | 5915 | .substreams = 1, |
5995 | .channels_min = 2, | 5916 | .channels_min = 2, |
5996 | .channels_max = 2, | 5917 | .channels_max = 2, |
@@ -6009,7 +5930,7 @@ static int vt1812_auto_fill_dac_nids(struct via_spec *spec, | |||
6009 | spec->multiout.num_dacs = 1; | 5930 | spec->multiout.num_dacs = 1; |
6010 | spec->multiout.dac_nids = spec->private_dac_nids; | 5931 | spec->multiout.dac_nids = spec->private_dac_nids; |
6011 | if (cfg->line_out_pins[0]) | 5932 | if (cfg->line_out_pins[0]) |
6012 | spec->multiout.dac_nids[0] = 0x8; | 5933 | spec->private_dac_nids[0] = 0x8; |
6013 | return 0; | 5934 | return 0; |
6014 | } | 5935 | } |
6015 | 5936 | ||
@@ -6067,53 +5988,26 @@ static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
6067 | } | 5988 | } |
6068 | 5989 | ||
6069 | /* create playback/capture controls for input pins */ | 5990 | /* create playback/capture controls for input pins */ |
6070 | static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec, | 5991 | static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec, |
6071 | const struct auto_pin_cfg *cfg) | 5992 | const struct auto_pin_cfg *cfg) |
6072 | { | 5993 | { |
6073 | static char *labels[] = { | 5994 | struct via_spec *spec = codec->spec; |
6074 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
6075 | }; | ||
6076 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5995 | struct hda_input_mux *imux = &spec->private_imux[0]; |
6077 | int i, err, idx = 0; | 5996 | static const hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff }; |
6078 | 5997 | int err; | |
6079 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
6080 | if (!cfg->input_pins[i]) | ||
6081 | continue; | ||
6082 | |||
6083 | switch (cfg->input_pins[i]) { | ||
6084 | case 0x2b: /* Mic */ | ||
6085 | idx = 0; | ||
6086 | break; | ||
6087 | 5998 | ||
6088 | case 0x2a: /* Line In */ | 5999 | err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, |
6089 | idx = 1; | 6000 | ARRAY_SIZE(pin_idxs)); |
6090 | break; | 6001 | if (err < 0) |
6002 | return err; | ||
6091 | 6003 | ||
6092 | case 0x29: /* Front Mic */ | ||
6093 | idx = 2; | ||
6094 | break; | ||
6095 | } | ||
6096 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
6097 | if (err < 0) | ||
6098 | return err; | ||
6099 | imux->items[imux->num_items].label = labels[i]; | ||
6100 | imux->items[imux->num_items].index = idx; | ||
6101 | imux->num_items++; | ||
6102 | } | ||
6103 | /* build volume/mute control of loopback */ | 6004 | /* build volume/mute control of loopback */ |
6104 | err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21); | 6005 | err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21); |
6105 | if (err < 0) | 6006 | if (err < 0) |
6106 | return err; | 6007 | return err; |
6107 | 6008 | ||
6108 | /* for internal loopback recording select */ | ||
6109 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
6110 | imux->items[imux->num_items].index = 5; | ||
6111 | imux->num_items++; | ||
6112 | |||
6113 | /* for digital mic select */ | 6009 | /* for digital mic select */ |
6114 | imux->items[imux->num_items].label = "Digital Mic"; | 6010 | snd_hda_add_imux_item(imux, "Digital Mic", 6, NULL); |
6115 | imux->items[imux->num_items].index = 6; | ||
6116 | imux->num_items++; | ||
6117 | 6011 | ||
6118 | return 0; | 6012 | return 0; |
6119 | } | 6013 | } |
@@ -6141,7 +6035,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) | |||
6141 | err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 6035 | err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
6142 | if (err < 0) | 6036 | if (err < 0) |
6143 | return err; | 6037 | return err; |
6144 | err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg); | 6038 | err = vt1812_auto_create_analog_input_ctls(codec, &spec->autocfg); |
6145 | if (err < 0) | 6039 | if (err < 0) |
6146 | return err; | 6040 | return err; |
6147 | 6041 | ||
@@ -6161,7 +6055,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) | |||
6161 | } | 6055 | } |
6162 | 6056 | ||
6163 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6057 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
6164 | static struct hda_amp_list vt1812_loopbacks[] = { | 6058 | static const struct hda_amp_list vt1812_loopbacks[] = { |
6165 | { 0x21, HDA_INPUT, 0 }, | 6059 | { 0x21, HDA_INPUT, 0 }, |
6166 | { 0x21, HDA_INPUT, 1 }, | 6060 | { 0x21, HDA_INPUT, 1 }, |
6167 | { 0x21, HDA_INPUT, 2 }, | 6061 | { 0x21, HDA_INPUT, 2 }, |
@@ -6169,6 +6063,97 @@ static struct hda_amp_list vt1812_loopbacks[] = { | |||
6169 | }; | 6063 | }; |
6170 | #endif | 6064 | #endif |
6171 | 6065 | ||
6066 | static void set_widgets_power_state_vt1812(struct hda_codec *codec) | ||
6067 | { | ||
6068 | struct via_spec *spec = codec->spec; | ||
6069 | int imux_is_smixer = | ||
6070 | snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3; | ||
6071 | unsigned int parm; | ||
6072 | unsigned int present; | ||
6073 | /* MUX10 (1eh) = stereo mixer */ | ||
6074 | imux_is_smixer = | ||
6075 | snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; | ||
6076 | /* inputs */ | ||
6077 | /* PW 5/6/7 (29h/2ah/2bh) */ | ||
6078 | parm = AC_PWRST_D3; | ||
6079 | set_pin_power_state(codec, 0x29, &parm); | ||
6080 | set_pin_power_state(codec, 0x2a, &parm); | ||
6081 | set_pin_power_state(codec, 0x2b, &parm); | ||
6082 | parm = AC_PWRST_D0; | ||
6083 | /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */ | ||
6084 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6085 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6086 | snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6087 | snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6088 | |||
6089 | /* outputs */ | ||
6090 | /* AOW0 (8h)*/ | ||
6091 | snd_hda_codec_write(codec, 0x8, 0, | ||
6092 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
6093 | |||
6094 | /* PW4 (28h), MW4 (18h), MUX4(38h) */ | ||
6095 | parm = AC_PWRST_D3; | ||
6096 | set_pin_power_state(codec, 0x28, &parm); | ||
6097 | snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6098 | snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6099 | |||
6100 | /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */ | ||
6101 | parm = AC_PWRST_D3; | ||
6102 | set_pin_power_state(codec, 0x25, &parm); | ||
6103 | snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6104 | snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6105 | if (spec->hp_independent_mode) | ||
6106 | snd_hda_codec_write(codec, 0x9, 0, | ||
6107 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
6108 | |||
6109 | /* Internal Speaker */ | ||
6110 | /* PW0 (24h), MW0(14h), MUX0(34h) */ | ||
6111 | present = snd_hda_jack_detect(codec, 0x25); | ||
6112 | |||
6113 | parm = AC_PWRST_D3; | ||
6114 | set_pin_power_state(codec, 0x24, &parm); | ||
6115 | if (present) { | ||
6116 | snd_hda_codec_write(codec, 0x14, 0, | ||
6117 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
6118 | snd_hda_codec_write(codec, 0x34, 0, | ||
6119 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
6120 | } else { | ||
6121 | snd_hda_codec_write(codec, 0x14, 0, | ||
6122 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
6123 | snd_hda_codec_write(codec, 0x34, 0, | ||
6124 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
6125 | } | ||
6126 | |||
6127 | |||
6128 | /* Mono Out */ | ||
6129 | /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */ | ||
6130 | present = snd_hda_jack_detect(codec, 0x28); | ||
6131 | |||
6132 | parm = AC_PWRST_D3; | ||
6133 | set_pin_power_state(codec, 0x31, &parm); | ||
6134 | if (present) { | ||
6135 | snd_hda_codec_write(codec, 0x1c, 0, | ||
6136 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
6137 | snd_hda_codec_write(codec, 0x3c, 0, | ||
6138 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
6139 | snd_hda_codec_write(codec, 0x3e, 0, | ||
6140 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
6141 | } else { | ||
6142 | snd_hda_codec_write(codec, 0x1c, 0, | ||
6143 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
6144 | snd_hda_codec_write(codec, 0x3c, 0, | ||
6145 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
6146 | snd_hda_codec_write(codec, 0x3e, 0, | ||
6147 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | ||
6148 | } | ||
6149 | |||
6150 | /* PW15 (33h), MW15 (1dh), MUX15(3dh) */ | ||
6151 | parm = AC_PWRST_D3; | ||
6152 | set_pin_power_state(codec, 0x33, &parm); | ||
6153 | snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6154 | snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm); | ||
6155 | |||
6156 | } | ||
6172 | 6157 | ||
6173 | /* patch for vt1812 */ | 6158 | /* patch for vt1812 */ |
6174 | static int patch_vt1812(struct hda_codec *codec) | 6159 | static int patch_vt1812(struct hda_codec *codec) |
@@ -6222,13 +6207,14 @@ static int patch_vt1812(struct hda_codec *codec) | |||
6222 | spec->loopback.amplist = vt1812_loopbacks; | 6207 | spec->loopback.amplist = vt1812_loopbacks; |
6223 | #endif | 6208 | #endif |
6224 | 6209 | ||
6210 | spec->set_widgets_power_state = set_widgets_power_state_vt1812; | ||
6225 | return 0; | 6211 | return 0; |
6226 | } | 6212 | } |
6227 | 6213 | ||
6228 | /* | 6214 | /* |
6229 | * patch entries | 6215 | * patch entries |
6230 | */ | 6216 | */ |
6231 | static struct hda_codec_preset snd_hda_preset_via[] = { | 6217 | static const struct hda_codec_preset snd_hda_preset_via[] = { |
6232 | { .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708}, | 6218 | { .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708}, |
6233 | { .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708}, | 6219 | { .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708}, |
6234 | { .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708}, | 6220 | { .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708}, |
@@ -6273,7 +6259,7 @@ static struct hda_codec_preset snd_hda_preset_via[] = { | |||
6273 | .patch = patch_vt1708S}, | 6259 | .patch = patch_vt1708S}, |
6274 | { .id = 0x11063397, .name = "VT1708S", | 6260 | { .id = 0x11063397, .name = "VT1708S", |
6275 | .patch = patch_vt1708S}, | 6261 | .patch = patch_vt1708S}, |
6276 | { .id = 0x11064397, .name = "VT1708S", | 6262 | { .id = 0x11064397, .name = "VT1705", |
6277 | .patch = patch_vt1708S}, | 6263 | .patch = patch_vt1708S}, |
6278 | { .id = 0x11065397, .name = "VT1708S", | 6264 | { .id = 0x11065397, .name = "VT1708S", |
6279 | .patch = patch_vt1708S}, | 6265 | .patch = patch_vt1708S}, |
@@ -6314,6 +6300,10 @@ static struct hda_codec_preset snd_hda_preset_via[] = { | |||
6314 | { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812}, | 6300 | { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812}, |
6315 | { .id = 0x11060440, .name = "VT1818S", | 6301 | { .id = 0x11060440, .name = "VT1818S", |
6316 | .patch = patch_vt1708S}, | 6302 | .patch = patch_vt1708S}, |
6303 | { .id = 0x11060446, .name = "VT1802", | ||
6304 | .patch = patch_vt2002P}, | ||
6305 | { .id = 0x11068446, .name = "VT1802", | ||
6306 | .patch = patch_vt2002P}, | ||
6317 | {} /* terminator */ | 6307 | {} /* terminator */ |
6318 | }; | 6308 | }; |
6319 | 6309 | ||