diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 176 |
1 files changed, 160 insertions, 16 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 61903848cd43..35c2823a0a2b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -50,10 +50,11 @@ struct sigmatel_spec { | |||
50 | unsigned int surr_switch: 1; | 50 | unsigned int surr_switch: 1; |
51 | unsigned int line_switch: 1; | 51 | unsigned int line_switch: 1; |
52 | unsigned int mic_switch: 1; | 52 | unsigned int mic_switch: 1; |
53 | unsigned int alt_switch: 1; | ||
53 | 54 | ||
54 | /* playback */ | 55 | /* playback */ |
55 | struct hda_multi_out multiout; | 56 | struct hda_multi_out multiout; |
56 | hda_nid_t dac_nids[4]; | 57 | hda_nid_t dac_nids[5]; |
57 | 58 | ||
58 | /* capture */ | 59 | /* capture */ |
59 | hda_nid_t *adc_nids; | 60 | hda_nid_t *adc_nids; |
@@ -73,7 +74,7 @@ struct sigmatel_spec { | |||
73 | 74 | ||
74 | /* capture source */ | 75 | /* capture source */ |
75 | struct hda_input_mux *input_mux; | 76 | struct hda_input_mux *input_mux; |
76 | unsigned int cur_mux[2]; | 77 | unsigned int cur_mux[3]; |
77 | 78 | ||
78 | /* i/o switches */ | 79 | /* i/o switches */ |
79 | unsigned int io_switch[2]; | 80 | unsigned int io_switch[2]; |
@@ -107,6 +108,14 @@ static hda_nid_t stac922x_mux_nids[2] = { | |||
107 | 0x12, 0x13, | 108 | 0x12, 0x13, |
108 | }; | 109 | }; |
109 | 110 | ||
111 | static hda_nid_t stac927x_adc_nids[3] = { | ||
112 | 0x07, 0x08, 0x09 | ||
113 | }; | ||
114 | |||
115 | static hda_nid_t stac927x_mux_nids[3] = { | ||
116 | 0x15, 0x16, 0x17 | ||
117 | }; | ||
118 | |||
110 | static hda_nid_t stac9200_pin_nids[8] = { | 119 | static hda_nid_t stac9200_pin_nids[8] = { |
111 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, | 120 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, |
112 | }; | 121 | }; |
@@ -116,6 +125,12 @@ static hda_nid_t stac922x_pin_nids[10] = { | |||
116 | 0x0f, 0x10, 0x11, 0x15, 0x1b, | 125 | 0x0f, 0x10, 0x11, 0x15, 0x1b, |
117 | }; | 126 | }; |
118 | 127 | ||
128 | static hda_nid_t stac927x_pin_nids[14] = { | ||
129 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
130 | 0x0f, 0x10, 0x11, 0x12, 0x13, | ||
131 | 0x14, 0x21, 0x22, 0x23, | ||
132 | }; | ||
133 | |||
119 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 134 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
120 | { | 135 | { |
121 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 136 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
@@ -155,6 +170,12 @@ static struct hda_verb stac922x_core_init[] = { | |||
155 | {} | 170 | {} |
156 | }; | 171 | }; |
157 | 172 | ||
173 | static struct hda_verb stac927x_core_init[] = { | ||
174 | /* set master volume and direct control */ | ||
175 | { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | ||
176 | {} | ||
177 | }; | ||
178 | |||
158 | static struct snd_kcontrol_new stac9200_mixer[] = { | 179 | static struct snd_kcontrol_new stac9200_mixer[] = { |
159 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 180 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
160 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 181 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
@@ -183,10 +204,26 @@ static struct snd_kcontrol_new stac922x_mixer[] = { | |||
183 | .put = stac92xx_mux_enum_put, | 204 | .put = stac92xx_mux_enum_put, |
184 | }, | 205 | }, |
185 | HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), | 206 | HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), |
207 | HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), | ||
186 | HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), | 208 | HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), |
187 | { } /* end */ | 209 | { } /* end */ |
188 | }; | 210 | }; |
189 | 211 | ||
212 | static snd_kcontrol_new_t stac927x_mixer[] = { | ||
213 | { | ||
214 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
215 | .name = "Input Source", | ||
216 | .count = 1, | ||
217 | .info = stac92xx_mux_enum_info, | ||
218 | .get = stac92xx_mux_enum_get, | ||
219 | .put = stac92xx_mux_enum_put, | ||
220 | }, | ||
221 | HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
222 | HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT), | ||
223 | HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
224 | { } /* end */ | ||
225 | }; | ||
226 | |||
190 | static int stac92xx_build_controls(struct hda_codec *codec) | 227 | static int stac92xx_build_controls(struct hda_codec *codec) |
191 | { | 228 | { |
192 | struct sigmatel_spec *spec = codec->spec; | 229 | struct sigmatel_spec *spec = codec->spec; |
@@ -240,14 +277,14 @@ static unsigned int ref922x_pin_configs[10] = { | |||
240 | }; | 277 | }; |
241 | 278 | ||
242 | static unsigned int d945gtp3_pin_configs[10] = { | 279 | static unsigned int d945gtp3_pin_configs[10] = { |
243 | 0x0221401f, 0x01a19022, 0x01813021, 0x01114010, | 280 | 0x0221401f, 0x01a19022, 0x01813021, 0x01014010, |
244 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, | 281 | 0x40000100, 0x40000100, 0x40000100, 0x40000100, |
245 | 0x02a19120, 0x40000100, | 282 | 0x02a19120, 0x40000100, |
246 | }; | 283 | }; |
247 | 284 | ||
248 | static unsigned int d945gtp5_pin_configs[10] = { | 285 | static unsigned int d945gtp5_pin_configs[10] = { |
249 | 0x0221401f, 0x01111012, 0x01813024, 0x01114010, | 286 | 0x0221401f, 0x01011012, 0x01813024, 0x01014010, |
250 | 0x01a19021, 0x01116011, 0x01452130, 0x40000100, | 287 | 0x01a19021, 0x01016011, 0x01452130, 0x40000100, |
251 | 0x02a19320, 0x40000100, | 288 | 0x02a19320, 0x40000100, |
252 | }; | 289 | }; |
253 | 290 | ||
@@ -274,6 +311,28 @@ static struct hda_board_config stac922x_cfg_tbl[] = { | |||
274 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 311 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
275 | .pci_subdevice = 0x0013, | 312 | .pci_subdevice = 0x0013, |
276 | .config = STAC_D945GTP5 }, /* Intel D955XBK - 5 Stack */ | 313 | .config = STAC_D945GTP5 }, /* Intel D955XBK - 5 Stack */ |
314 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
315 | .pci_subdevice = 0x0417, | ||
316 | .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ | ||
317 | {} /* terminator */ | ||
318 | }; | ||
319 | |||
320 | static unsigned int ref927x_pin_configs[14] = { | ||
321 | 0x01813122, 0x01a19021, 0x01014010, 0x01016011, | ||
322 | 0x01012012, 0x01011014, 0x40000100, 0x40000100, | ||
323 | 0x40000100, 0x40000100, 0x40000100, 0x01441030, | ||
324 | 0x01c41030, 0x40000100, | ||
325 | }; | ||
326 | |||
327 | static unsigned int *stac927x_brd_tbl[] = { | ||
328 | ref927x_pin_configs, | ||
329 | }; | ||
330 | |||
331 | static struct hda_board_config stac927x_cfg_tbl[] = { | ||
332 | { .modelname = "ref", | ||
333 | .pci_subvendor = PCI_VENDOR_ID_INTEL, | ||
334 | .pci_subdevice = 0x2668, /* DFI LanParty */ | ||
335 | .config = STAC_REF }, /* SigmaTel reference board */ | ||
277 | {} /* terminator */ | 336 | {} /* terminator */ |
278 | }; | 337 | }; |
279 | 338 | ||
@@ -408,11 +467,23 @@ static struct hda_pcm_stream stac92xx_pcm_analog_playback = { | |||
408 | }, | 467 | }, |
409 | }; | 468 | }; |
410 | 469 | ||
470 | static struct hda_pcm_stream stac92xx_pcm_analog_alt_playback = { | ||
471 | .substreams = 1, | ||
472 | .channels_min = 2, | ||
473 | .channels_max = 2, | ||
474 | .nid = 0x06, /* NID to query formats and rates */ | ||
475 | .ops = { | ||
476 | .open = stac92xx_playback_pcm_open, | ||
477 | .prepare = stac92xx_playback_pcm_prepare, | ||
478 | .cleanup = stac92xx_playback_pcm_cleanup | ||
479 | }, | ||
480 | }; | ||
481 | |||
411 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { | 482 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { |
412 | .substreams = 2, | 483 | .substreams = 2, |
413 | .channels_min = 2, | 484 | .channels_min = 2, |
414 | .channels_max = 2, | 485 | .channels_max = 2, |
415 | .nid = 0x06, /* NID to query formats and rates */ | 486 | /* NID is set in stac92xx_build_pcms */ |
416 | .ops = { | 487 | .ops = { |
417 | .prepare = stac92xx_capture_pcm_prepare, | 488 | .prepare = stac92xx_capture_pcm_prepare, |
418 | .cleanup = stac92xx_capture_pcm_cleanup | 489 | .cleanup = stac92xx_capture_pcm_cleanup |
@@ -430,6 +501,14 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
430 | info->name = "STAC92xx Analog"; | 501 | info->name = "STAC92xx Analog"; |
431 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | 502 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; |
432 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | 503 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; |
504 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | ||
505 | |||
506 | if (spec->alt_switch) { | ||
507 | codec->num_pcms++; | ||
508 | info++; | ||
509 | info->name = "STAC92xx Analog Alt"; | ||
510 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_alt_playback; | ||
511 | } | ||
433 | 512 | ||
434 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 513 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
435 | codec->num_pcms++; | 514 | codec->num_pcms++; |
@@ -588,6 +667,16 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf | |||
588 | return 0; | 667 | return 0; |
589 | } | 668 | } |
590 | 669 | ||
670 | /* | ||
671 | * XXX The line_out pin widget connection list may not be set to the | ||
672 | * desired DAC nid. This is the case on 927x where ports A and B can | ||
673 | * be routed to several DACs. | ||
674 | * | ||
675 | * This requires an analysis of the line-out/hp pin configuration | ||
676 | * to provide a best fit for pin/DAC configurations that are routable. | ||
677 | * For now, 927x DAC4 is not supported and 927x DAC1 output to ports | ||
678 | * A and B is not supported. | ||
679 | */ | ||
591 | /* fill in the dac_nids table from the parsed pin configuration */ | 680 | /* fill in the dac_nids table from the parsed pin configuration */ |
592 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | 681 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) |
593 | { | 682 | { |
@@ -602,7 +691,13 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct aut | |||
602 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 691 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
603 | } | 692 | } |
604 | 693 | ||
605 | spec->multiout.num_dacs = cfg->line_outs; | 694 | if (cfg->line_outs) |
695 | spec->multiout.num_dacs = cfg->line_outs; | ||
696 | else if (cfg->hp_pin) { | ||
697 | spec->multiout.dac_nids[0] = snd_hda_codec_read(codec, cfg->hp_pin, 0, | ||
698 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
699 | spec->multiout.num_dacs = 1; | ||
700 | } | ||
606 | 701 | ||
607 | return 0; | 702 | return 0; |
608 | } | 703 | } |
@@ -753,19 +848,21 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | |||
753 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 848 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); |
754 | } | 849 | } |
755 | 850 | ||
756 | static int stac922x_parse_auto_config(struct hda_codec *codec) | 851 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) |
757 | { | 852 | { |
758 | struct sigmatel_spec *spec = codec->spec; | 853 | struct sigmatel_spec *spec = codec->spec; |
759 | int err; | 854 | int err; |
760 | 855 | ||
761 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) | 856 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) |
762 | return err; | 857 | return err; |
858 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | ||
859 | return 0; /* can't find valid pin config */ | ||
860 | stac92xx_auto_init_multi_out(codec); | ||
861 | stac92xx_auto_init_hp_out(codec); | ||
763 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) | 862 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) |
764 | return err; | 863 | return err; |
765 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | 864 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) |
766 | return err; | 865 | return err; |
767 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | ||
768 | return 0; /* can't find valid pin config */ | ||
769 | 866 | ||
770 | if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 867 | if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
771 | (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || | 868 | (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || |
@@ -777,11 +874,11 @@ static int stac922x_parse_auto_config(struct hda_codec *codec) | |||
777 | spec->surr_switch = 1; | 874 | spec->surr_switch = 1; |
778 | 875 | ||
779 | if (spec->autocfg.dig_out_pin) { | 876 | if (spec->autocfg.dig_out_pin) { |
780 | spec->multiout.dig_out_nid = 0x08; | 877 | spec->multiout.dig_out_nid = dig_out; |
781 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | 878 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); |
782 | } | 879 | } |
783 | if (spec->autocfg.dig_in_pin) { | 880 | if (spec->autocfg.dig_in_pin) { |
784 | spec->dig_in_nid = 0x09; | 881 | spec->dig_in_nid = dig_in; |
785 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | 882 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); |
786 | } | 883 | } |
787 | 884 | ||
@@ -827,9 +924,6 @@ static int stac92xx_init(struct hda_codec *codec) | |||
827 | 924 | ||
828 | snd_hda_sequence_write(codec, spec->init); | 925 | snd_hda_sequence_write(codec, spec->init); |
829 | 926 | ||
830 | stac92xx_auto_init_multi_out(codec); | ||
831 | stac92xx_auto_init_hp_out(codec); | ||
832 | |||
833 | return 0; | 927 | return 0; |
834 | } | 928 | } |
835 | 929 | ||
@@ -996,7 +1090,47 @@ static int patch_stac922x(struct hda_codec *codec) | |||
996 | 1090 | ||
997 | spec->multiout.dac_nids = spec->dac_nids; | 1091 | spec->multiout.dac_nids = spec->dac_nids; |
998 | 1092 | ||
999 | err = stac922x_parse_auto_config(codec); | 1093 | err = stac92xx_parse_auto_config(codec, 0x08, 0x09); |
1094 | if (err < 0) { | ||
1095 | stac92xx_free(codec); | ||
1096 | return err; | ||
1097 | } | ||
1098 | |||
1099 | codec->patch_ops = stac92xx_patch_ops; | ||
1100 | |||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | static int patch_stac927x(struct hda_codec *codec) | ||
1105 | { | ||
1106 | struct sigmatel_spec *spec; | ||
1107 | int err; | ||
1108 | |||
1109 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
1110 | if (spec == NULL) | ||
1111 | return -ENOMEM; | ||
1112 | |||
1113 | codec->spec = spec; | ||
1114 | spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); | ||
1115 | if (spec->board_config < 0) | ||
1116 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); | ||
1117 | else { | ||
1118 | spec->num_pins = 14; | ||
1119 | spec->pin_nids = stac927x_pin_nids; | ||
1120 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; | ||
1121 | stac92xx_set_config_regs(codec); | ||
1122 | } | ||
1123 | |||
1124 | spec->adc_nids = stac927x_adc_nids; | ||
1125 | spec->mux_nids = stac927x_mux_nids; | ||
1126 | spec->num_muxes = 3; | ||
1127 | |||
1128 | spec->init = stac927x_core_init; | ||
1129 | spec->mixer = stac927x_mixer; | ||
1130 | |||
1131 | spec->multiout.dac_nids = spec->dac_nids; | ||
1132 | |||
1133 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | ||
1000 | if (err < 0) { | 1134 | if (err < 0) { |
1001 | stac92xx_free(codec); | 1135 | stac92xx_free(codec); |
1002 | return err; | 1136 | return err; |
@@ -1018,5 +1152,15 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
1018 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | 1152 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, |
1019 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | 1153 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, |
1020 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | 1154 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, |
1155 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, | ||
1156 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, | ||
1157 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, | ||
1158 | { .id = 0x83847623, .name = "STAC9273D", .patch = patch_stac927x }, | ||
1159 | { .id = 0x83847624, .name = "STAC9272X", .patch = patch_stac927x }, | ||
1160 | { .id = 0x83847625, .name = "STAC9272D", .patch = patch_stac927x }, | ||
1161 | { .id = 0x83847626, .name = "STAC9271X", .patch = patch_stac927x }, | ||
1162 | { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, | ||
1163 | { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, | ||
1164 | { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, | ||
1021 | {} /* terminator */ | 1165 | {} /* terminator */ |
1022 | }; | 1166 | }; |