aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_generic.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-09-24 01:52:47 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-24 01:52:47 -0400
commit23930fa1cebfea6f79881c588ccd1b0781e49e3f (patch)
tree36d29e3f83661c4f5f45b6f74ac0d5f9886867a8 /sound/pci/hda/hda_generic.c
parent36b35a5be0e4b406acd816e2122d153e875105be (diff)
parent4f5537de7c1531398e84e18a24f667e49cc94208 (diff)
Merge branch 'master' into upstream
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r--sound/pci/hda/hda_generic.c199
1 files changed, 142 insertions, 57 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 85ad164ada59..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 }
@@ -461,14 +475,19 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
461 return "Front Line"; 475 return "Front Line";
462 return "Line"; 476 return "Line";
463 case AC_JACK_CD: 477 case AC_JACK_CD:
478#if 0
464 if (pinctl) 479 if (pinctl)
465 *pinctl |= AC_PINCTL_VREF_GRD; 480 *pinctl |= AC_PINCTL_VREF_GRD;
481#endif
466 return "CD"; 482 return "CD";
467 case AC_JACK_AUX: 483 case AC_JACK_AUX:
468 if ((location & 0x0f) == AC_JACK_LOC_FRONT) 484 if ((location & 0x0f) == AC_JACK_LOC_FRONT)
469 return "Front Aux"; 485 return "Front Aux";
470 return "Aux"; 486 return "Aux";
471 case AC_JACK_MIC_IN: 487 case AC_JACK_MIC_IN:
488 if (node->pin_caps &
489 (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT))
490 *pinctl |= AC_PINCTL_VREF_80;
472 if ((location & 0x0f) == AC_JACK_LOC_FRONT) 491 if ((location & 0x0f) == AC_JACK_LOC_FRONT)
473 return "Front Mic"; 492 return "Front Mic";
474 return "Mic"; 493 return "Mic";
@@ -556,6 +575,29 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
556 return 1; /* found */ 575 return 1; /* found */
557} 576}
558 577
578/* add a capture source element */
579static void add_cap_src(struct hda_gspec *spec, int idx)
580{
581 struct hda_input_mux_item *csrc;
582 char *buf;
583 int num, ocap;
584
585 num = spec->input_mux.num_items;
586 csrc = &spec->input_mux.items[num];
587 buf = spec->cap_labels[num];
588 for (ocap = 0; ocap < num; ocap++) {
589 if (! strcmp(buf, spec->cap_labels[ocap])) {
590 /* same label already exists,
591 * put the index number to be unique
592 */
593 sprintf(buf, "%s %d", spec->cap_labels[ocap], num);
594 break;
595 }
596 }
597 csrc->index = idx;
598 spec->input_mux.num_items++;
599}
600
559/* 601/*
560 * parse input 602 * parse input
561 */ 603 */
@@ -576,28 +618,26 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
576 * if it reaches to a proper input PIN, add the path as the 618 * if it reaches to a proper input PIN, add the path as the
577 * input path. 619 * input path.
578 */ 620 */
621 /* first, check the direct connections to PIN widgets */
579 for (i = 0; i < adc_node->nconns; i++) { 622 for (i = 0; i < adc_node->nconns; i++) {
580 node = hda_get_node(spec, adc_node->conn_list[i]); 623 node = hda_get_node(spec, adc_node->conn_list[i]);
581 if (! node) 624 if (node && node->type == AC_WID_PIN) {
582 continue; 625 err = parse_adc_sub_nodes(codec, spec, node);
583 err = parse_adc_sub_nodes(codec, spec, node); 626 if (err < 0)
584 if (err < 0) 627 return err;
585 return err; 628 else if (err > 0)
586 else if (err > 0) { 629 add_cap_src(spec, i);
587 struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items]; 630 }
588 char *buf = spec->cap_labels[spec->input_mux.num_items]; 631 }
589 int ocap; 632 /* ... then check the rests, more complicated connections */
590 for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) { 633 for (i = 0; i < adc_node->nconns; i++) {
591 if (! strcmp(buf, spec->cap_labels[ocap])) { 634 node = hda_get_node(spec, adc_node->conn_list[i]);
592 /* same label already exists, 635 if (node && node->type != AC_WID_PIN) {
593 * put the index number to be unique 636 err = parse_adc_sub_nodes(codec, spec, node);
594 */ 637 if (err < 0)
595 sprintf(buf, "%s %d", spec->cap_labels[ocap], 638 return err;
596 spec->input_mux.num_items); 639 else if (err > 0)
597 } 640 add_cap_src(spec, i);
598 }
599 csrc->index = i;
600 spec->input_mux.num_items++;
601 } 641 }
602 } 642 }
603 643
@@ -647,9 +687,6 @@ static int parse_input(struct hda_codec *codec)
647/* 687/*
648 * create mixer controls if possible 688 * create mixer controls if possible
649 */ 689 */
650#define DIR_OUT 0x1
651#define DIR_IN 0x2
652
653static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, 690static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
654 unsigned int index, const char *type, const char *dir_sfx) 691 unsigned int index, const char *type, const char *dir_sfx)
655{ 692{
@@ -722,49 +759,97 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con
722/* 759/*
723 * build output mixer controls 760 * build output mixer controls
724 */ 761 */
725static int build_output_controls(struct hda_codec *codec) 762static int create_output_mixers(struct hda_codec *codec, const char **names)
726{ 763{
727 struct hda_gspec *spec = codec->spec; 764 struct hda_gspec *spec = codec->spec;
728 static const char *types[2] = { "Master", "Headphone" };
729 int i, err; 765 int i, err;
730 766
731 for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { 767 for (i = 0; i < spec->pcm_vol_nodes; i++) {
732 err = create_mixer(codec, spec->pcm_vol_node[i], 768 err = create_mixer(codec, spec->pcm_vol[i].node,
733 spec->pcm_vol_index[i], 769 spec->pcm_vol[i].index,
734 types[i], "Playback"); 770 names[i], "Playback");
735 if (err < 0) 771 if (err < 0)
736 return err; 772 return err;
737 } 773 }
738 return 0; 774 return 0;
739} 775}
740 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
741/* create capture volume/switch */ 797/* create capture volume/switch */
742static int build_input_controls(struct hda_codec *codec) 798static int build_input_controls(struct hda_codec *codec)
743{ 799{
744 struct hda_gspec *spec = codec->spec; 800 struct hda_gspec *spec = codec->spec;
745 struct hda_gnode *adc_node = spec->adc_node; 801 struct hda_gnode *adc_node = spec->adc_node;
746 int err; 802 int i, err;
747 803 static struct snd_kcontrol_new cap_sel = {
748 if (! adc_node) 804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
805 .name = "Capture Source",
806 .info = capture_source_info,
807 .get = capture_source_get,
808 .put = capture_source_put,
809 };
810
811 if (! adc_node || ! spec->input_mux.num_items)
749 return 0; /* not found */ 812 return 0; /* not found */
750 813
814 spec->cur_cap_src = 0;
815 select_input_connection(codec, adc_node,
816 spec->input_mux.items[0].index);
817
751 /* create capture volume and switch controls if the ADC has an amp */ 818 /* create capture volume and switch controls if the ADC has an amp */
752 err = create_mixer(codec, adc_node, 0, NULL, "Capture"); 819 /* do we have only a single item? */
820 if (spec->input_mux.num_items == 1) {
821 err = create_mixer(codec, adc_node,
822 spec->input_mux.items[0].index,
823 NULL, "Capture");
824 if (err < 0)
825 return err;
826 return 0;
827 }
753 828
754 /* create input MUX if multiple sources are available */ 829 /* create input MUX if multiple sources are available */
755 if (spec->input_mux.num_items > 1) { 830 if ((err = snd_ctl_add(codec->bus->card,
756 static struct snd_kcontrol_new cap_sel = { 831 snd_ctl_new1(&cap_sel, codec))) < 0)
757 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 832 return err;
758 .name = "Capture Source", 833
759 .info = capture_source_info, 834 /* no volume control? */
760 .get = capture_source_get, 835 if (! (adc_node->wid_caps & AC_WCAP_IN_AMP) ||
761 .put = capture_source_put, 836 ! (adc_node->amp_in_caps & AC_AMPCAP_NUM_STEPS))
762 }; 837 return 0;
763 if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0) 838
839 for (i = 0; i < spec->input_mux.num_items; i++) {
840 struct snd_kcontrol_new knew;
841 char name[32];
842 sprintf(name, "%s Capture Volume",
843 spec->input_mux.items[i].label);
844 knew = (struct snd_kcontrol_new)
845 HDA_CODEC_VOLUME(name, adc_node->nid,
846 spec->input_mux.items[i].index,
847 HDA_INPUT);
848 if ((err = snd_ctl_add(codec->bus->card,
849 snd_ctl_new1(&knew, codec))) < 0)
764 return err; 850 return err;
765 spec->cur_cap_src = 0;
766 select_input_connection(codec, adc_node, spec->input_mux.items[0].index);
767 } 851 }
852
768 return 0; 853 return 0;
769} 854}
770 855