diff options
Diffstat (limited to 'sound/pci/hda/patch_cirrus.c')
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 151 |
1 files changed, 99 insertions, 52 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 488fd9ade1ba..26a1521045bb 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -51,7 +51,7 @@ struct cs_spec { | |||
51 | unsigned int cur_adc_format; | 51 | unsigned int cur_adc_format; |
52 | hda_nid_t dig_in; | 52 | hda_nid_t dig_in; |
53 | 53 | ||
54 | struct hda_bind_ctls *capture_bind[2]; | 54 | const struct hda_bind_ctls *capture_bind[2]; |
55 | 55 | ||
56 | unsigned int gpio_mask; | 56 | unsigned int gpio_mask; |
57 | unsigned int gpio_dir; | 57 | unsigned int gpio_dir; |
@@ -65,6 +65,7 @@ struct cs_spec { | |||
65 | 65 | ||
66 | /* available models */ | 66 | /* available models */ |
67 | enum { | 67 | enum { |
68 | CS420X_MBP53, | ||
68 | CS420X_MBP55, | 69 | CS420X_MBP55, |
69 | CS420X_IMAC27, | 70 | CS420X_IMAC27, |
70 | CS420X_AUTO, | 71 | CS420X_AUTO, |
@@ -230,7 +231,7 @@ static int cs_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
230 | 231 | ||
231 | /* | 232 | /* |
232 | */ | 233 | */ |
233 | static struct hda_pcm_stream cs_pcm_analog_playback = { | 234 | static const struct hda_pcm_stream cs_pcm_analog_playback = { |
234 | .substreams = 1, | 235 | .substreams = 1, |
235 | .channels_min = 2, | 236 | .channels_min = 2, |
236 | .channels_max = 2, | 237 | .channels_max = 2, |
@@ -241,7 +242,7 @@ static struct hda_pcm_stream cs_pcm_analog_playback = { | |||
241 | }, | 242 | }, |
242 | }; | 243 | }; |
243 | 244 | ||
244 | static struct hda_pcm_stream cs_pcm_analog_capture = { | 245 | static const struct hda_pcm_stream cs_pcm_analog_capture = { |
245 | .substreams = 1, | 246 | .substreams = 1, |
246 | .channels_min = 2, | 247 | .channels_min = 2, |
247 | .channels_max = 2, | 248 | .channels_max = 2, |
@@ -251,7 +252,7 @@ static struct hda_pcm_stream cs_pcm_analog_capture = { | |||
251 | }, | 252 | }, |
252 | }; | 253 | }; |
253 | 254 | ||
254 | static struct hda_pcm_stream cs_pcm_digital_playback = { | 255 | static const struct hda_pcm_stream cs_pcm_digital_playback = { |
255 | .substreams = 1, | 256 | .substreams = 1, |
256 | .channels_min = 2, | 257 | .channels_min = 2, |
257 | .channels_max = 2, | 258 | .channels_max = 2, |
@@ -263,7 +264,7 @@ static struct hda_pcm_stream cs_pcm_digital_playback = { | |||
263 | }, | 264 | }, |
264 | }; | 265 | }; |
265 | 266 | ||
266 | static struct hda_pcm_stream cs_pcm_digital_capture = { | 267 | static const struct hda_pcm_stream cs_pcm_digital_capture = { |
267 | .substreams = 1, | 268 | .substreams = 1, |
268 | .channels_min = 2, | 269 | .channels_min = 2, |
269 | .channels_max = 2, | 270 | .channels_max = 2, |
@@ -329,12 +330,12 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx) | |||
329 | { | 330 | { |
330 | struct cs_spec *spec = codec->spec; | 331 | struct cs_spec *spec = codec->spec; |
331 | struct auto_pin_cfg *cfg = &spec->autocfg; | 332 | struct auto_pin_cfg *cfg = &spec->autocfg; |
332 | hda_nid_t pin = cfg->input_pins[idx]; | 333 | hda_nid_t pin = cfg->inputs[idx].pin; |
333 | unsigned int val = snd_hda_query_pin_caps(codec, pin); | 334 | unsigned int val; |
334 | if (!(val & AC_PINCAP_PRES_DETECT)) | 335 | if (!is_jack_detectable(codec, pin)) |
335 | return 0; | 336 | return 0; |
336 | val = snd_hda_codec_get_pincfg(codec, pin); | 337 | val = snd_hda_codec_get_pincfg(codec, pin); |
337 | return (get_defcfg_connect(val) == AC_JACK_PORT_COMPLEX); | 338 | return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT); |
338 | } | 339 | } |
339 | 340 | ||
340 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | 341 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, |
@@ -348,8 +349,7 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | |||
348 | hda_nid_t pins[2]; | 349 | hda_nid_t pins[2]; |
349 | unsigned int type; | 350 | unsigned int type; |
350 | int j, nums; | 351 | int j, nums; |
351 | type = (get_wcaps(codec, nid) & AC_WCAP_TYPE) | 352 | type = get_wcaps_type(get_wcaps(codec, nid)); |
352 | >> AC_WCAP_TYPE_SHIFT; | ||
353 | if (type != AC_WID_AUD_IN) | 353 | if (type != AC_WID_AUD_IN) |
354 | continue; | 354 | continue; |
355 | nums = snd_hda_get_connections(codec, nid, pins, | 355 | nums = snd_hda_get_connections(codec, nid, pins, |
@@ -424,10 +424,8 @@ static int parse_input(struct hda_codec *codec) | |||
424 | struct auto_pin_cfg *cfg = &spec->autocfg; | 424 | struct auto_pin_cfg *cfg = &spec->autocfg; |
425 | int i; | 425 | int i; |
426 | 426 | ||
427 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 427 | for (i = 0; i < cfg->num_inputs; i++) { |
428 | hda_nid_t pin = cfg->input_pins[i]; | 428 | hda_nid_t pin = cfg->inputs[i].pin; |
429 | if (!pin) | ||
430 | continue; | ||
431 | spec->input_idx[spec->num_inputs] = i; | 429 | spec->input_idx[spec->num_inputs] = i; |
432 | spec->capsrc_idx[i] = spec->num_inputs++; | 430 | spec->capsrc_idx[i] = spec->num_inputs++; |
433 | spec->cur_input = i; | 431 | spec->cur_input = i; |
@@ -438,16 +436,17 @@ static int parse_input(struct hda_codec *codec) | |||
438 | 436 | ||
439 | /* check whether the automatic mic switch is available */ | 437 | /* check whether the automatic mic switch is available */ |
440 | if (spec->num_inputs == 2 && | 438 | if (spec->num_inputs == 2 && |
441 | spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) { | 439 | cfg->inputs[0].type == AUTO_PIN_MIC && |
442 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) { | 440 | cfg->inputs[1].type == AUTO_PIN_MIC) { |
443 | if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 441 | if (is_ext_mic(codec, cfg->inputs[0].pin)) { |
442 | if (!is_ext_mic(codec, cfg->inputs[1].pin)) { | ||
444 | spec->mic_detect = 1; | 443 | spec->mic_detect = 1; |
445 | spec->automic_idx = AUTO_PIN_FRONT_MIC; | 444 | spec->automic_idx = 0; |
446 | } | 445 | } |
447 | } else { | 446 | } else { |
448 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 447 | if (is_ext_mic(codec, cfg->inputs[1].pin)) { |
449 | spec->mic_detect = 1; | 448 | spec->mic_detect = 1; |
450 | spec->automic_idx = AUTO_PIN_MIC; | 449 | spec->automic_idx = 1; |
451 | } | 450 | } |
452 | } | 451 | } |
453 | } | 452 | } |
@@ -490,7 +489,7 @@ static int parse_digital_input(struct hda_codec *codec) | |||
490 | * create mixer controls | 489 | * create mixer controls |
491 | */ | 490 | */ |
492 | 491 | ||
493 | static const char *dir_sfx[2] = { "Playback", "Capture" }; | 492 | static const char * const dir_sfx[2] = { "Playback", "Capture" }; |
494 | 493 | ||
495 | static int add_mute(struct hda_codec *codec, const char *name, int index, | 494 | static int add_mute(struct hda_codec *codec, const char *name, int index, |
496 | unsigned int pval, int dir, struct snd_kcontrol **kctlp) | 495 | unsigned int pval, int dir, struct snd_kcontrol **kctlp) |
@@ -559,10 +558,10 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx, | |||
559 | const char *name; | 558 | const char *name; |
560 | int err, index; | 559 | int err, index; |
561 | struct snd_kcontrol *kctl; | 560 | struct snd_kcontrol *kctl; |
562 | static char *speakers[] = { | 561 | static const char * const speakers[] = { |
563 | "Front Speaker", "Surround Speaker", "Bass Speaker" | 562 | "Front Speaker", "Surround Speaker", "Bass Speaker" |
564 | }; | 563 | }; |
565 | static char *line_outs[] = { | 564 | static const char * const line_outs[] = { |
566 | "Front Line-Out", "Surround Line-Out", "Bass Line-Out" | 565 | "Front Line-Out", "Surround Line-Out", "Bass Line-Out" |
567 | }; | 566 | }; |
568 | 567 | ||
@@ -642,7 +641,7 @@ static int build_output(struct hda_codec *codec) | |||
642 | /* | 641 | /* |
643 | */ | 642 | */ |
644 | 643 | ||
645 | static struct snd_kcontrol_new cs_capture_ctls[] = { | 644 | static const struct snd_kcontrol_new cs_capture_ctls[] = { |
646 | HDA_BIND_SW("Capture Switch", 0), | 645 | HDA_BIND_SW("Capture Switch", 0), |
647 | HDA_BIND_VOL("Capture Volume", 0), | 646 | HDA_BIND_VOL("Capture Volume", 0), |
648 | }; | 647 | }; |
@@ -674,6 +673,7 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
674 | { | 673 | { |
675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 674 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
676 | struct cs_spec *spec = codec->spec; | 675 | struct cs_spec *spec = codec->spec; |
676 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
677 | unsigned int idx; | 677 | unsigned int idx; |
678 | 678 | ||
679 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 679 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
@@ -682,7 +682,8 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
682 | if (uinfo->value.enumerated.item >= spec->num_inputs) | 682 | if (uinfo->value.enumerated.item >= spec->num_inputs) |
683 | uinfo->value.enumerated.item = spec->num_inputs - 1; | 683 | uinfo->value.enumerated.item = spec->num_inputs - 1; |
684 | idx = spec->input_idx[uinfo->value.enumerated.item]; | 684 | idx = spec->input_idx[uinfo->value.enumerated.item]; |
685 | strcpy(uinfo->value.enumerated.name, auto_pin_cfg_labels[idx]); | 685 | strcpy(uinfo->value.enumerated.name, |
686 | hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1)); | ||
686 | return 0; | 687 | return 0; |
687 | } | 688 | } |
688 | 689 | ||
@@ -708,7 +709,7 @@ static int cs_capture_source_put(struct snd_kcontrol *kcontrol, | |||
708 | return change_cur_input(codec, idx, 0); | 709 | return change_cur_input(codec, idx, 0); |
709 | } | 710 | } |
710 | 711 | ||
711 | static struct snd_kcontrol_new cs_capture_source = { | 712 | static const struct snd_kcontrol_new cs_capture_source = { |
712 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 713 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
713 | .name = "Capture Source", | 714 | .name = "Capture Source", |
714 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | 715 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, |
@@ -717,7 +718,7 @@ static struct snd_kcontrol_new cs_capture_source = { | |||
717 | .put = cs_capture_source_put, | 718 | .put = cs_capture_source_put, |
718 | }; | 719 | }; |
719 | 720 | ||
720 | static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec, | 721 | static const struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec, |
721 | struct hda_ctl_ops *ops) | 722 | struct hda_ctl_ops *ops) |
722 | { | 723 | { |
723 | struct cs_spec *spec = codec->spec; | 724 | struct cs_spec *spec = codec->spec; |
@@ -740,6 +741,27 @@ static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec, | |||
740 | return bind; | 741 | return bind; |
741 | } | 742 | } |
742 | 743 | ||
744 | /* add a (input-boost) volume control to the given input pin */ | ||
745 | static int add_input_volume_control(struct hda_codec *codec, | ||
746 | struct auto_pin_cfg *cfg, | ||
747 | int item) | ||
748 | { | ||
749 | hda_nid_t pin = cfg->inputs[item].pin; | ||
750 | u32 caps; | ||
751 | const char *label; | ||
752 | struct snd_kcontrol *kctl; | ||
753 | |||
754 | if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP)) | ||
755 | return 0; | ||
756 | caps = query_amp_caps(codec, pin, HDA_INPUT); | ||
757 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | ||
758 | if (caps <= 1) | ||
759 | return 0; | ||
760 | label = hda_get_autocfg_input_label(codec, cfg, item); | ||
761 | return add_volume(codec, label, 0, | ||
762 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl); | ||
763 | } | ||
764 | |||
743 | static int build_input(struct hda_codec *codec) | 765 | static int build_input(struct hda_codec *codec) |
744 | { | 766 | { |
745 | struct cs_spec *spec = codec->spec; | 767 | struct cs_spec *spec = codec->spec; |
@@ -779,6 +801,12 @@ static int build_input(struct hda_codec *codec) | |||
779 | return err; | 801 | return err; |
780 | } | 802 | } |
781 | 803 | ||
804 | for (i = 0; i < spec->num_inputs; i++) { | ||
805 | err = add_input_volume_control(codec, &spec->autocfg, i); | ||
806 | if (err < 0) | ||
807 | return err; | ||
808 | } | ||
809 | |||
782 | return 0; | 810 | return 0; |
783 | } | 811 | } |
784 | 812 | ||
@@ -818,15 +846,14 @@ static void cs_automute(struct hda_codec *codec) | |||
818 | { | 846 | { |
819 | struct cs_spec *spec = codec->spec; | 847 | struct cs_spec *spec = codec->spec; |
820 | struct auto_pin_cfg *cfg = &spec->autocfg; | 848 | struct auto_pin_cfg *cfg = &spec->autocfg; |
821 | unsigned int caps, hp_present; | 849 | unsigned int hp_present; |
822 | hda_nid_t nid; | 850 | hda_nid_t nid; |
823 | int i; | 851 | int i; |
824 | 852 | ||
825 | hp_present = 0; | 853 | hp_present = 0; |
826 | for (i = 0; i < cfg->hp_outs; i++) { | 854 | for (i = 0; i < cfg->hp_outs; i++) { |
827 | nid = cfg->hp_pins[i]; | 855 | nid = cfg->hp_pins[i]; |
828 | caps = snd_hda_query_pin_caps(codec, nid); | 856 | if (!is_jack_detectable(codec, nid)) |
829 | if (!(caps & AC_PINCAP_PRES_DETECT)) | ||
830 | continue; | 857 | continue; |
831 | hp_present = snd_hda_jack_detect(codec, nid); | 858 | hp_present = snd_hda_jack_detect(codec, nid); |
832 | if (hp_present) | 859 | if (hp_present) |
@@ -838,7 +865,8 @@ static void cs_automute(struct hda_codec *codec) | |||
838 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 865 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
839 | hp_present ? 0 : PIN_OUT); | 866 | hp_present ? 0 : PIN_OUT); |
840 | } | 867 | } |
841 | if (spec->board_config == CS420X_MBP55 || | 868 | if (spec->board_config == CS420X_MBP53 || |
869 | spec->board_config == CS420X_MBP55 || | ||
842 | spec->board_config == CS420X_IMAC27) { | 870 | spec->board_config == CS420X_IMAC27) { |
843 | unsigned int gpio = hp_present ? 0x02 : 0x08; | 871 | unsigned int gpio = hp_present ? 0x02 : 0x08; |
844 | snd_hda_codec_write(codec, 0x01, 0, | 872 | snd_hda_codec_write(codec, 0x01, 0, |
@@ -853,15 +881,12 @@ static void cs_automic(struct hda_codec *codec) | |||
853 | hda_nid_t nid; | 881 | hda_nid_t nid; |
854 | unsigned int present; | 882 | unsigned int present; |
855 | 883 | ||
856 | nid = cfg->input_pins[spec->automic_idx]; | 884 | nid = cfg->inputs[spec->automic_idx].pin; |
857 | present = snd_hda_jack_detect(codec, nid); | 885 | present = snd_hda_jack_detect(codec, nid); |
858 | if (present) | 886 | if (present) |
859 | change_cur_input(codec, spec->automic_idx, 0); | 887 | change_cur_input(codec, spec->automic_idx, 0); |
860 | else { | 888 | else |
861 | unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? | 889 | change_cur_input(codec, !spec->automic_idx, 0); |
862 | AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC; | ||
863 | change_cur_input(codec, imic, 0); | ||
864 | } | ||
865 | } | 890 | } |
866 | 891 | ||
867 | /* | 892 | /* |
@@ -897,7 +922,7 @@ static void init_output(struct hda_codec *codec) | |||
897 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | 922 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); |
898 | if (!cfg->speaker_outs) | 923 | if (!cfg->speaker_outs) |
899 | continue; | 924 | continue; |
900 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { | 925 | if (is_jack_detectable(codec, nid)) { |
901 | snd_hda_codec_write(codec, nid, 0, | 926 | snd_hda_codec_write(codec, nid, 0, |
902 | AC_VERB_SET_UNSOLICITED_ENABLE, | 927 | AC_VERB_SET_UNSOLICITED_ENABLE, |
903 | AC_USRSP_EN | HP_EVENT); | 928 | AC_USRSP_EN | HP_EVENT); |
@@ -918,14 +943,14 @@ static void init_input(struct hda_codec *codec) | |||
918 | unsigned int coef; | 943 | unsigned int coef; |
919 | int i; | 944 | int i; |
920 | 945 | ||
921 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 946 | for (i = 0; i < cfg->num_inputs; i++) { |
922 | unsigned int ctl; | 947 | unsigned int ctl; |
923 | hda_nid_t pin = cfg->input_pins[i]; | 948 | hda_nid_t pin = cfg->inputs[i].pin; |
924 | if (!pin || !spec->adc_nid[i]) | 949 | if (!spec->adc_nid[i]) |
925 | continue; | 950 | continue; |
926 | /* set appropriate pin control and mute first */ | 951 | /* set appropriate pin control and mute first */ |
927 | ctl = PIN_IN; | 952 | ctl = PIN_IN; |
928 | if (i <= AUTO_PIN_FRONT_MIC) { | 953 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { |
929 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); | 954 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); |
930 | caps >>= AC_PINCAP_VREF_SHIFT; | 955 | caps >>= AC_PINCAP_VREF_SHIFT; |
931 | if (caps & AC_PINCAP_VREF_80) | 956 | if (caps & AC_PINCAP_VREF_80) |
@@ -956,7 +981,7 @@ static void init_input(struct hda_codec *codec) | |||
956 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); | 981 | cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); |
957 | } | 982 | } |
958 | 983 | ||
959 | static struct hda_verb cs_coef_init_verbs[] = { | 984 | static const struct hda_verb cs_coef_init_verbs[] = { |
960 | {0x11, AC_VERB_SET_PROC_STATE, 1}, | 985 | {0x11, AC_VERB_SET_PROC_STATE, 1}, |
961 | {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, | 986 | {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, |
962 | {0x11, AC_VERB_SET_PROC_COEF, | 987 | {0x11, AC_VERB_SET_PROC_COEF, |
@@ -990,7 +1015,7 @@ static struct hda_verb cs_coef_init_verbs[] = { | |||
990 | * blocks, which will alleviate the issue. | 1015 | * blocks, which will alleviate the issue. |
991 | */ | 1016 | */ |
992 | 1017 | ||
993 | static struct hda_verb cs_errata_init_verbs[] = { | 1018 | static const struct hda_verb cs_errata_init_verbs[] = { |
994 | {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */ | 1019 | {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */ |
995 | {0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ | 1020 | {0x11, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */ |
996 | 1021 | ||
@@ -1012,9 +1037,11 @@ static struct hda_verb cs_errata_init_verbs[] = { | |||
1012 | {0x11, AC_VERB_SET_PROC_COEF, 0x0008}, | 1037 | {0x11, AC_VERB_SET_PROC_COEF, 0x0008}, |
1013 | {0x11, AC_VERB_SET_PROC_STATE, 0x00}, | 1038 | {0x11, AC_VERB_SET_PROC_STATE, 0x00}, |
1014 | 1039 | ||
1040 | #if 0 /* Don't to set to D3 as we are in power-up sequence */ | ||
1015 | {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */ | 1041 | {0x07, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Rx: D3 */ |
1016 | {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */ | 1042 | {0x08, AC_VERB_SET_POWER_STATE, 0x03}, /* S/PDIF Tx: D3 */ |
1017 | /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */ | 1043 | /*{0x01, AC_VERB_SET_POWER_STATE, 0x03},*/ /* AFG: D3 This is already handled */ |
1044 | #endif | ||
1018 | 1045 | ||
1019 | {} /* terminator */ | 1046 | {} /* terminator */ |
1020 | }; | 1047 | }; |
@@ -1097,7 +1124,7 @@ static void cs_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1097 | } | 1124 | } |
1098 | } | 1125 | } |
1099 | 1126 | ||
1100 | static struct hda_codec_ops cs_patch_ops = { | 1127 | static const struct hda_codec_ops cs_patch_ops = { |
1101 | .build_controls = cs_build_controls, | 1128 | .build_controls = cs_build_controls, |
1102 | .build_pcms = cs_build_pcms, | 1129 | .build_pcms = cs_build_pcms, |
1103 | .init = cs_init, | 1130 | .init = cs_init, |
@@ -1129,15 +1156,19 @@ static int cs_parse_auto_config(struct hda_codec *codec) | |||
1129 | return 0; | 1156 | return 0; |
1130 | } | 1157 | } |
1131 | 1158 | ||
1132 | static const char *cs420x_models[CS420X_MODELS] = { | 1159 | static const char * const cs420x_models[CS420X_MODELS] = { |
1160 | [CS420X_MBP53] = "mbp53", | ||
1133 | [CS420X_MBP55] = "mbp55", | 1161 | [CS420X_MBP55] = "mbp55", |
1134 | [CS420X_IMAC27] = "imac27", | 1162 | [CS420X_IMAC27] = "imac27", |
1135 | [CS420X_AUTO] = "auto", | 1163 | [CS420X_AUTO] = "auto", |
1136 | }; | 1164 | }; |
1137 | 1165 | ||
1138 | 1166 | ||
1139 | static struct snd_pci_quirk cs420x_cfg_tbl[] = { | 1167 | static const struct snd_pci_quirk cs420x_cfg_tbl[] = { |
1168 | SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), | ||
1169 | SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), | ||
1140 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), | 1170 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), |
1171 | SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), | ||
1141 | SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), | 1172 | SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), |
1142 | {} /* terminator */ | 1173 | {} /* terminator */ |
1143 | }; | 1174 | }; |
@@ -1147,7 +1178,21 @@ struct cs_pincfg { | |||
1147 | u32 val; | 1178 | u32 val; |
1148 | }; | 1179 | }; |
1149 | 1180 | ||
1150 | static struct cs_pincfg mbp55_pincfgs[] = { | 1181 | static const struct cs_pincfg mbp53_pincfgs[] = { |
1182 | { 0x09, 0x012b4050 }, | ||
1183 | { 0x0a, 0x90100141 }, | ||
1184 | { 0x0b, 0x90100140 }, | ||
1185 | { 0x0c, 0x018b3020 }, | ||
1186 | { 0x0d, 0x90a00110 }, | ||
1187 | { 0x0e, 0x400000f0 }, | ||
1188 | { 0x0f, 0x01cbe030 }, | ||
1189 | { 0x10, 0x014be060 }, | ||
1190 | { 0x12, 0x400000f0 }, | ||
1191 | { 0x15, 0x400000f0 }, | ||
1192 | {} /* terminator */ | ||
1193 | }; | ||
1194 | |||
1195 | static const struct cs_pincfg mbp55_pincfgs[] = { | ||
1151 | { 0x09, 0x012b4030 }, | 1196 | { 0x09, 0x012b4030 }, |
1152 | { 0x0a, 0x90100121 }, | 1197 | { 0x0a, 0x90100121 }, |
1153 | { 0x0b, 0x90100120 }, | 1198 | { 0x0b, 0x90100120 }, |
@@ -1161,7 +1206,7 @@ static struct cs_pincfg mbp55_pincfgs[] = { | |||
1161 | {} /* terminator */ | 1206 | {} /* terminator */ |
1162 | }; | 1207 | }; |
1163 | 1208 | ||
1164 | static struct cs_pincfg imac27_pincfgs[] = { | 1209 | static const struct cs_pincfg imac27_pincfgs[] = { |
1165 | { 0x09, 0x012b4050 }, | 1210 | { 0x09, 0x012b4050 }, |
1166 | { 0x0a, 0x90100140 }, | 1211 | { 0x0a, 0x90100140 }, |
1167 | { 0x0b, 0x90100142 }, | 1212 | { 0x0b, 0x90100142 }, |
@@ -1175,7 +1220,8 @@ static struct cs_pincfg imac27_pincfgs[] = { | |||
1175 | {} /* terminator */ | 1220 | {} /* terminator */ |
1176 | }; | 1221 | }; |
1177 | 1222 | ||
1178 | static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { | 1223 | static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { |
1224 | [CS420X_MBP53] = mbp53_pincfgs, | ||
1179 | [CS420X_MBP55] = mbp55_pincfgs, | 1225 | [CS420X_MBP55] = mbp55_pincfgs, |
1180 | [CS420X_IMAC27] = imac27_pincfgs, | 1226 | [CS420X_IMAC27] = imac27_pincfgs, |
1181 | }; | 1227 | }; |
@@ -1208,6 +1254,7 @@ static int patch_cs420x(struct hda_codec *codec) | |||
1208 | 1254 | ||
1209 | switch (spec->board_config) { | 1255 | switch (spec->board_config) { |
1210 | case CS420X_IMAC27: | 1256 | case CS420X_IMAC27: |
1257 | case CS420X_MBP53: | ||
1211 | case CS420X_MBP55: | 1258 | case CS420X_MBP55: |
1212 | /* GPIO1 = headphones */ | 1259 | /* GPIO1 = headphones */ |
1213 | /* GPIO3 = speakers */ | 1260 | /* GPIO3 = speakers */ |
@@ -1234,7 +1281,7 @@ static int patch_cs420x(struct hda_codec *codec) | |||
1234 | /* | 1281 | /* |
1235 | * patch entries | 1282 | * patch entries |
1236 | */ | 1283 | */ |
1237 | static struct hda_codec_preset snd_hda_preset_cirrus[] = { | 1284 | static const struct hda_codec_preset snd_hda_preset_cirrus[] = { |
1238 | { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, | 1285 | { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, |
1239 | { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, | 1286 | { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, |
1240 | {} /* terminator */ | 1287 | {} /* terminator */ |