提交 ea87d1c4 编写于 作者: A Anssi Hannula 提交者: Takashi Iwai

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: NAnssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 32c168c8
...@@ -364,6 +364,9 @@ enum { ...@@ -364,6 +364,9 @@ enum {
#define AC_DIG2_CC (0x7f<<0) #define AC_DIG2_CC (0x7f<<0)
/* Pin widget control - 8bit */ /* Pin widget control - 8bit */
#define AC_PINCTL_EPT (0x3<<0)
#define AC_PINCTL_EPT_NATIVE 0
#define AC_PINCTL_EPT_HBR 3
#define AC_PINCTL_VREFEN (0x7<<0) #define AC_PINCTL_VREFEN (0x7<<0)
#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */
#define AC_PINCTL_VREF_50 1 /* 50% */ #define AC_PINCTL_VREF_50 1 /* 50% */
......
...@@ -698,11 +698,48 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -698,11 +698,48 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
* Callbacks * Callbacks
*/ */
static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
u32 stream_tag, int format) u32 stream_tag, int format)
{ {
struct hdmi_spec *spec = codec->spec;
int tag; int tag;
int fmt; int fmt;
int pinctl;
int new_pinctl = 0;
int i;
for (i = 0; i < spec->num_pins; i++) {
if (spec->pin_cvt[i] != nid)
continue;
if (!(snd_hda_query_pin_caps(codec, spec->pin[i]) & AC_PINCAP_HBR))
continue;
pinctl = snd_hda_codec_read(codec, spec->pin[i], 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
new_pinctl = pinctl & ~AC_PINCTL_EPT;
/* Non-PCM, 8 channels */
if ((format & 0x8000) && (format & 0x0f) == 7)
new_pinctl |= AC_PINCTL_EPT_HBR;
else
new_pinctl |= AC_PINCTL_EPT_NATIVE;
snd_printdd("hdmi_setup_stream: "
"NID=0x%x, %spinctl=0x%x\n",
spec->pin[i],
pinctl == new_pinctl ? "" : "new-",
new_pinctl);
if (pinctl != new_pinctl)
snd_hda_codec_write(codec, spec->pin[i], 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
new_pinctl);
}
if ((format & 0x8000) && (format & 0x0f) == 7 && !new_pinctl) {
snd_printdd("hdmi_setup_stream: HBR is not supported\n");
return -EINVAL;
}
tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); 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,6 +759,7 @@ static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
if (fmt != format) if (fmt != format)
snd_hda_codec_write(codec, nid, 0, snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_STREAM_FORMAT, format); AC_VERB_SET_STREAM_FORMAT, format);
return 0;
} }
/* /*
......
...@@ -66,8 +66,7 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, ...@@ -66,8 +66,7 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
return 0;
} }
static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
......
...@@ -202,8 +202,7 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, ...@@ -202,8 +202,7 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
return 0;
} }
static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册