aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_generic.c71
1 files changed, 52 insertions, 19 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index dedfc5b1083a..97e9af130b71 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -46,11 +46,18 @@ struct hda_gnode {
46}; 46};
47 47
48/* patch-specific record */ 48/* patch-specific record */
49
50#define MAX_PCM_VOLS 2
51struct pcm_vol {
52 struct hda_gnode *node; /* Node for PCM volume */
53 unsigned int index; /* connection of PCM volume */
54};
55
49struct hda_gspec { 56struct hda_gspec {
50 struct hda_gnode *dac_node[2]; /* DAC node */ 57 struct hda_gnode *dac_node[2]; /* DAC node */
51 struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ 58 struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */
52 struct hda_gnode *pcm_vol_node[2]; /* Node for PCM volume */ 59 struct pcm_vol pcm_vol[MAX_PCM_VOLS]; /* PCM volumes */
53 unsigned int pcm_vol_index[2]; /* connection of PCM volume */ 60 unsigned int pcm_vol_nodes; /* number of PCM volumes */
54 61
55 struct hda_gnode *adc_node; /* ADC node */ 62 struct hda_gnode *adc_node; /* ADC node */
56 struct hda_gnode *cap_vol_node; /* Node for capture volume */ 63 struct hda_gnode *cap_vol_node; /* Node for capture volume */
@@ -285,9 +292,11 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec,
285 return node == spec->dac_node[dac_idx]; 292 return node == spec->dac_node[dac_idx];
286 } 293 }
287 spec->dac_node[dac_idx] = node; 294 spec->dac_node[dac_idx] = node;
288 if (node->wid_caps & AC_WCAP_OUT_AMP) { 295 if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
289 spec->pcm_vol_node[dac_idx] = node; 296 spec->pcm_vol_nodes < MAX_PCM_VOLS) {
290 spec->pcm_vol_index[dac_idx] = 0; 297 spec->pcm_vol[spec->pcm_vol_nodes].node = node;
298 spec->pcm_vol[spec->pcm_vol_nodes].index = 0;
299 spec->pcm_vol_nodes++;
291 } 300 }
292 return 1; /* found */ 301 return 1; /* found */
293 } 302 }
@@ -307,13 +316,16 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec,
307 select_input_connection(codec, node, i); 316 select_input_connection(codec, node, i);
308 unmute_input(codec, node, i); 317 unmute_input(codec, node, i);
309 unmute_output(codec, node); 318 unmute_output(codec, node);
310 if (! spec->pcm_vol_node[dac_idx]) { 319 if (spec->dac_node[dac_idx] &&
311 if (node->wid_caps & AC_WCAP_IN_AMP) { 320 spec->pcm_vol_nodes < MAX_PCM_VOLS &&
312 spec->pcm_vol_node[dac_idx] = node; 321 !(spec->dac_node[dac_idx]->wid_caps &
313 spec->pcm_vol_index[dac_idx] = i; 322 AC_WCAP_OUT_AMP)) {
314 } else if (node->wid_caps & AC_WCAP_OUT_AMP) { 323 if ((node->wid_caps & AC_WCAP_IN_AMP) ||
315 spec->pcm_vol_node[dac_idx] = node; 324 (node->wid_caps & AC_WCAP_OUT_AMP)) {
316 spec->pcm_vol_index[dac_idx] = 0; 325 int n = spec->pcm_vol_nodes;
326 spec->pcm_vol[n].node = node;
327 spec->pcm_vol[n].index = i;
328 spec->pcm_vol_nodes++;
317 } 329 }
318 } 330 }
319 return 1; 331 return 1;
@@ -370,7 +382,9 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
370 /* set PIN-Out enable */ 382 /* set PIN-Out enable */
371 snd_hda_codec_write(codec, node->nid, 0, 383 snd_hda_codec_write(codec, node->nid, 0,
372 AC_VERB_SET_PIN_WIDGET_CONTROL, 384 AC_VERB_SET_PIN_WIDGET_CONTROL,
373 AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); 385 AC_PINCTL_OUT_EN |
386 ((node->pin_caps & AC_PINCAP_HP_DRV) ?
387 AC_PINCTL_HP_EN : 0));
374 return node; 388 return node;
375 } 389 }
376 } 390 }
@@ -745,22 +759,41 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con
745/* 759/*
746 * build output mixer controls 760 * build output mixer controls
747 */ 761 */
748static int build_output_controls(struct hda_codec *codec) 762static int create_output_mixers(struct hda_codec *codec, const char **names)
749{ 763{
750 struct hda_gspec *spec = codec->spec; 764 struct hda_gspec *spec = codec->spec;
751 static const char *types[2] = { "Master", "Headphone" };
752 int i, err; 765 int i, err;
753 766
754 for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { 767 for (i = 0; i < spec->pcm_vol_nodes; i++) {
755 err = create_mixer(codec, spec->pcm_vol_node[i], 768 err = create_mixer(codec, spec->pcm_vol[i].node,
756 spec->pcm_vol_index[i], 769 spec->pcm_vol[i].index,
757 types[i], "Playback"); 770 names[i], "Playback");
758 if (err < 0) 771 if (err < 0)
759 return err; 772 return err;
760 } 773 }
761 return 0; 774 return 0;
762} 775}
763 776
777static int build_output_controls(struct hda_codec *codec)
778{
779 struct hda_gspec *spec = codec->spec;
780 static const char *types_speaker[] = { "Speaker", "Headphone" };
781 static const char *types_line[] = { "Front", "Headphone" };
782
783 switch (spec->pcm_vol_nodes) {
784 case 1:
785 return create_mixer(codec, spec->pcm_vol[0].node,
786 spec->pcm_vol[0].index,
787 "Master", "Playback");
788 case 2:
789 if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER)
790 return create_output_mixers(codec, types_speaker);
791 else
792 return create_output_mixers(codec, types_line);
793 }
794 return 0;
795}
796
764/* create capture volume/switch */ 797/* create capture volume/switch */
765static int build_input_controls(struct hda_codec *codec) 798static int build_input_controls(struct hda_codec *codec)
766{ 799{