aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-08-23 12:34:06 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:43:56 -0400
commit071c73ad5fce436ee00c9422b7ca0c5d629451fb (patch)
treeac8c6776f2b4acb24e22c8c55c61832144fc140a
parent11b44bbde52b6c50ed8c9ba579d7ee9ff5b48cd8 (diff)
[ALSA] hda-codec - Fix mic capture with generic parser
Fixed the mic capture with generic parser of hda-codec driver - Use VREF80 for mic pins if available - Handle multiple inputs correctly on audio-input widget node. Confirmed on a conexant codec chip. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r--sound/pci/hda/hda_generic.c128
1 files changed, 90 insertions, 38 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 85ad164ada59..dedfc5b1083a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -461,14 +461,19 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
461 return "Front Line"; 461 return "Front Line";
462 return "Line"; 462 return "Line";
463 case AC_JACK_CD: 463 case AC_JACK_CD:
464#if 0
464 if (pinctl) 465 if (pinctl)
465 *pinctl |= AC_PINCTL_VREF_GRD; 466 *pinctl |= AC_PINCTL_VREF_GRD;
467#endif
466 return "CD"; 468 return "CD";
467 case AC_JACK_AUX: 469 case AC_JACK_AUX:
468 if ((location & 0x0f) == AC_JACK_LOC_FRONT) 470 if ((location & 0x0f) == AC_JACK_LOC_FRONT)
469 return "Front Aux"; 471 return "Front Aux";
470 return "Aux"; 472 return "Aux";
471 case AC_JACK_MIC_IN: 473 case AC_JACK_MIC_IN:
474 if (node->pin_caps &
475 (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT))
476 *pinctl |= AC_PINCTL_VREF_80;
472 if ((location & 0x0f) == AC_JACK_LOC_FRONT) 477 if ((location & 0x0f) == AC_JACK_LOC_FRONT)
473 return "Front Mic"; 478 return "Front Mic";
474 return "Mic"; 479 return "Mic";
@@ -556,6 +561,29 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
556 return 1; /* found */ 561 return 1; /* found */
557} 562}
558 563
564/* add a capture source element */
565static void add_cap_src(struct hda_gspec *spec, int idx)
566{
567 struct hda_input_mux_item *csrc;
568 char *buf;
569 int num, ocap;
570
571 num = spec->input_mux.num_items;
572 csrc = &spec->input_mux.items[num];
573 buf = spec->cap_labels[num];
574 for (ocap = 0; ocap < num; ocap++) {
575 if (! strcmp(buf, spec->cap_labels[ocap])) {
576 /* same label already exists,
577 * put the index number to be unique
578 */
579 sprintf(buf, "%s %d", spec->cap_labels[ocap], num);
580 break;
581 }
582 }
583 csrc->index = idx;
584 spec->input_mux.num_items++;
585}
586
559/* 587/*
560 * parse input 588 * parse input
561 */ 589 */
@@ -576,28 +604,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 604 * if it reaches to a proper input PIN, add the path as the
577 * input path. 605 * input path.
578 */ 606 */
607 /* first, check the direct connections to PIN widgets */
579 for (i = 0; i < adc_node->nconns; i++) { 608 for (i = 0; i < adc_node->nconns; i++) {
580 node = hda_get_node(spec, adc_node->conn_list[i]); 609 node = hda_get_node(spec, adc_node->conn_list[i]);
581 if (! node) 610 if (node && node->type == AC_WID_PIN) {
582 continue; 611 err = parse_adc_sub_nodes(codec, spec, node);
583 err = parse_adc_sub_nodes(codec, spec, node); 612 if (err < 0)
584 if (err < 0) 613 return err;
585 return err; 614 else if (err > 0)
586 else if (err > 0) { 615 add_cap_src(spec, i);
587 struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items]; 616 }
588 char *buf = spec->cap_labels[spec->input_mux.num_items]; 617 }
589 int ocap; 618 /* ... then check the rests, more complicated connections */
590 for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) { 619 for (i = 0; i < adc_node->nconns; i++) {
591 if (! strcmp(buf, spec->cap_labels[ocap])) { 620 node = hda_get_node(spec, adc_node->conn_list[i]);
592 /* same label already exists, 621 if (node && node->type != AC_WID_PIN) {
593 * put the index number to be unique 622 err = parse_adc_sub_nodes(codec, spec, node);
594 */ 623 if (err < 0)
595 sprintf(buf, "%s %d", spec->cap_labels[ocap], 624 return err;
596 spec->input_mux.num_items); 625 else if (err > 0)
597 } 626 add_cap_src(spec, i);
598 }
599 csrc->index = i;
600 spec->input_mux.num_items++;
601 } 627 }
602 } 628 }
603 629
@@ -647,9 +673,6 @@ static int parse_input(struct hda_codec *codec)
647/* 673/*
648 * create mixer controls if possible 674 * create mixer controls if possible
649 */ 675 */
650#define DIR_OUT 0x1
651#define DIR_IN 0x2
652
653static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, 676static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
654 unsigned int index, const char *type, const char *dir_sfx) 677 unsigned int index, const char *type, const char *dir_sfx)
655{ 678{
@@ -743,28 +766,57 @@ static int build_input_controls(struct hda_codec *codec)
743{ 766{
744 struct hda_gspec *spec = codec->spec; 767 struct hda_gspec *spec = codec->spec;
745 struct hda_gnode *adc_node = spec->adc_node; 768 struct hda_gnode *adc_node = spec->adc_node;
746 int err; 769 int i, err;
747 770 static struct snd_kcontrol_new cap_sel = {
748 if (! adc_node) 771 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
772 .name = "Capture Source",
773 .info = capture_source_info,
774 .get = capture_source_get,
775 .put = capture_source_put,
776 };
777
778 if (! adc_node || ! spec->input_mux.num_items)
749 return 0; /* not found */ 779 return 0; /* not found */
750 780
781 spec->cur_cap_src = 0;
782 select_input_connection(codec, adc_node,
783 spec->input_mux.items[0].index);
784
751 /* create capture volume and switch controls if the ADC has an amp */ 785 /* create capture volume and switch controls if the ADC has an amp */
752 err = create_mixer(codec, adc_node, 0, NULL, "Capture"); 786 /* do we have only a single item? */
787 if (spec->input_mux.num_items == 1) {
788 err = create_mixer(codec, adc_node,
789 spec->input_mux.items[0].index,
790 NULL, "Capture");
791 if (err < 0)
792 return err;
793 return 0;
794 }
753 795
754 /* create input MUX if multiple sources are available */ 796 /* create input MUX if multiple sources are available */
755 if (spec->input_mux.num_items > 1) { 797 if ((err = snd_ctl_add(codec->bus->card,
756 static struct snd_kcontrol_new cap_sel = { 798 snd_ctl_new1(&cap_sel, codec))) < 0)
757 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 799 return err;
758 .name = "Capture Source", 800
759 .info = capture_source_info, 801 /* no volume control? */
760 .get = capture_source_get, 802 if (! (adc_node->wid_caps & AC_WCAP_IN_AMP) ||
761 .put = capture_source_put, 803 ! (adc_node->amp_in_caps & AC_AMPCAP_NUM_STEPS))
762 }; 804 return 0;
763 if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0) 805
806 for (i = 0; i < spec->input_mux.num_items; i++) {
807 struct snd_kcontrol_new knew;
808 char name[32];
809 sprintf(name, "%s Capture Volume",
810 spec->input_mux.items[i].label);
811 knew = (struct snd_kcontrol_new)
812 HDA_CODEC_VOLUME(name, adc_node->nid,
813 spec->input_mux.items[i].index,
814 HDA_INPUT);
815 if ((err = snd_ctl_add(codec->bus->card,
816 snd_ctl_new1(&knew, codec))) < 0)
764 return err; 817 return err;
765 spec->cur_cap_src = 0;
766 select_input_connection(codec, adc_node, spec->input_mux.items[0].index);
767 } 818 }
819
768 return 0; 820 return 0;
769} 821}
770 822