diff options
author | Anssi Hannula <anssi.hannula@iki.fi> | 2010-08-03 06:28:58 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-08-03 06:53:36 -0400 |
commit | ea87d1c493aba9cf3f645eae0d6d9c0fd44d3189 (patch) | |
tree | aade327fe17501e0bd52bf4ae1dc02f84ccbe26f /sound/pci/hda/patch_hdmi.c | |
parent | 32c168c892e2c6936c714d1653ba5e19e07d5c26 (diff) |
ALSA: hda - Add support for HDMI HBR passthrough
Passing IEC 61937 encapsulated compressed audio at bitrates over 6.144
Mbps (i.e. more than a single 2-channel 16-bit 192kHz IEC 60958 link)
over HDMI requires the use of HBR Audio Stream Packets instead of Audio
Sample Packets.
Enable HBR mode when the stream has 8 channels and the Non-PCM bit is
set.
If the audio converter is not connected to any HBR-capable pins, return
-EINVAL in prepare().
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 2fc53961054e..8534792591fc 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -698,11 +698,48 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | |||
698 | * Callbacks | 698 | * Callbacks |
699 | */ | 699 | */ |
700 | 700 | ||
701 | static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | 701 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
702 | u32 stream_tag, int format) | 702 | u32 stream_tag, int format) |
703 | { | 703 | { |
704 | struct hdmi_spec *spec = codec->spec; | ||
704 | int tag; | 705 | int tag; |
705 | int fmt; | 706 | int fmt; |
707 | int pinctl; | ||
708 | int new_pinctl = 0; | ||
709 | int i; | ||
710 | |||
711 | for (i = 0; i < spec->num_pins; i++) { | ||
712 | if (spec->pin_cvt[i] != nid) | ||
713 | continue; | ||
714 | if (!(snd_hda_query_pin_caps(codec, spec->pin[i]) & AC_PINCAP_HBR)) | ||
715 | continue; | ||
716 | |||
717 | pinctl = snd_hda_codec_read(codec, spec->pin[i], 0, | ||
718 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
719 | |||
720 | new_pinctl = pinctl & ~AC_PINCTL_EPT; | ||
721 | /* Non-PCM, 8 channels */ | ||
722 | if ((format & 0x8000) && (format & 0x0f) == 7) | ||
723 | new_pinctl |= AC_PINCTL_EPT_HBR; | ||
724 | else | ||
725 | new_pinctl |= AC_PINCTL_EPT_NATIVE; | ||
726 | |||
727 | snd_printdd("hdmi_setup_stream: " | ||
728 | "NID=0x%x, %spinctl=0x%x\n", | ||
729 | spec->pin[i], | ||
730 | pinctl == new_pinctl ? "" : "new-", | ||
731 | new_pinctl); | ||
732 | |||
733 | if (pinctl != new_pinctl) | ||
734 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
735 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
736 | new_pinctl); | ||
737 | } | ||
738 | |||
739 | if ((format & 0x8000) && (format & 0x0f) == 7 && !new_pinctl) { | ||
740 | snd_printdd("hdmi_setup_stream: HBR is not supported\n"); | ||
741 | return -EINVAL; | ||
742 | } | ||
706 | 743 | ||
707 | tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; | 744 | tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; |
708 | fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); | 745 | fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); |
@@ -722,6 +759,7 @@ static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
722 | if (fmt != format) | 759 | if (fmt != format) |
723 | snd_hda_codec_write(codec, nid, 0, | 760 | snd_hda_codec_write(codec, nid, 0, |
724 | AC_VERB_SET_STREAM_FORMAT, format); | 761 | AC_VERB_SET_STREAM_FORMAT, format); |
762 | return 0; | ||
725 | } | 763 | } |
726 | 764 | ||
727 | /* | 765 | /* |