2010-08-03 10:38:09

by Anssi Hannula

[permalink] [raw]
Subject: [PATCH 0/2] ALSA: hda - support HDMI HBR passthrough

Hi all!

This patchset adds support for passing through IEC 61937 encapsulated
compressed audio at high bitrates (i.e. those over 6.144Mbps).
At least TrueHD and DTS-HD are such formats.

I've tested this using an NVIDIA hdmi codec and the following ffmpeg
patch which adds support for TrueHD in its IEC 61937 muxer:
http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2010-August/094317.html

One needs to set the AES0 & 0x02 (non-audio) bit during playback so that
the data is not transmitted as normal 8 channel PCM audio.

---
Anssi Hannula (2):
ALSA: hda - Set Stream Type in Stream Format according to AES0
ALSA: hda - Add support for HDMI HBR passthrough

sound/pci/hda/hda_codec.c | 6 ++++-
sound/pci/hda/hda_codec.h | 6 ++++-
sound/pci/hda/hda_intel.c | 3 +-
sound/pci/hda/patch_hdmi.c | 40 ++++++++++++++++++++++++++++++++++++++-
sound/pci/hda/patch_intelhdmi.c | 3 +-
sound/pci/hda/patch_nvhdmi.c | 3 +-
6 files changed, 53 insertions(+), 8 deletions(-)


2010-08-03 10:38:10

by Anssi Hannula

[permalink] [raw]
Subject: [PATCH 1/2] ALSA: hda - Set Stream Type in Stream Format according to AES0

Set bit 15 (Stream Type) of HDA Stream Format to 1 (Non-PCM) when IEC958
channel status bit 1 (AES0 & 0x02) is set to 1 (non-audio).

This is a prequisite for HDMI HBR passthrough.

Signed-off-by: Anssi Hannula <[email protected]>
---
sound/pci/hda/hda_codec.c | 6 +++++-
sound/pci/hda/hda_codec.h | 3 ++-
sound/pci/hda/hda_intel.c | 3 ++-
3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index d9d1c91..bd8d7a6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3051,7 +3051,8 @@ static struct hda_rate_tbl rate_bits[] = {
unsigned int snd_hda_calc_stream_format(unsigned int rate,
unsigned int channels,
unsigned int format,
- unsigned int maxbps)
+ unsigned int maxbps,
+ unsigned short spdif_ctls)
{
int i;
unsigned int val = 0;
@@ -3095,6 +3096,9 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
return 0;
}

+ if (spdif_ctls & AC_DIG1_NONAUDIO)
+ val |= 0x8000;
+
return val;
}
EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 5991d14..4797416 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -928,7 +928,8 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
unsigned int snd_hda_calc_stream_format(unsigned int rate,
unsigned int channels,
unsigned int format,
- unsigned int maxbps);
+ unsigned int maxbps,
+ unsigned short spdif_ctls);
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
unsigned int format);

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1df25cf..f8a2f5a 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1653,7 +1653,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
format_val = snd_hda_calc_stream_format(runtime->rate,
runtime->channels,
runtime->format,
- hinfo->maxbps);
+ hinfo->maxbps,
+ apcm->codec->spdif_ctls);
if (!format_val) {
snd_printk(KERN_ERR SFX
"invalid format_val, rate=%d, ch=%d, format=%d\n",
--
1.7.2

2010-08-03 10:38:07

by Anssi Hannula

[permalink] [raw]
Subject: [PATCH 2/2] 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 <[email protected]>
---
sound/pci/hda/hda_codec.h | 3 ++
sound/pci/hda/patch_hdmi.c | 40 ++++++++++++++++++++++++++++++++++++++-
sound/pci/hda/patch_intelhdmi.c | 3 +-
sound/pci/hda/patch_nvhdmi.c | 3 +-
4 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 4797416..48b3367 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -364,6 +364,9 @@ enum {
#define AC_DIG2_CC (0x7f<<0)

/* 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_VREF_HIZ 0 /* Hi-Z */
#define AC_PINCTL_VREF_50 1 /* 50% */
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 2fc5396..8534792 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)
* 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)
{
+ struct hdmi_spec *spec = codec->spec;
int tag;
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;
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,
if (fmt != format)
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_STREAM_FORMAT, format);
+ return 0;
}

/*
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index b81d23e..5972d5e 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -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_stream(codec, hinfo->nid, stream_tag, format);
- return 0;
+ return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
}

static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index b0652ac..a281836 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -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_stream(codec, hinfo->nid, stream_tag, format);
- return 0;
+ return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
}

static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
--
1.7.2

2010-08-03 10:59:13

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH 0/2] ALSA: hda - support HDMI HBR passthrough

At Tue, 3 Aug 2010 13:28:56 +0300,
Anssi Hannula wrote:
>
> Hi all!
>
> This patchset adds support for passing through IEC 61937 encapsulated
> compressed audio at high bitrates (i.e. those over 6.144Mbps).
> At least TrueHD and DTS-HD are such formats.
>
> I've tested this using an NVIDIA hdmi codec and the following ffmpeg
> patch which adds support for TrueHD in its IEC 61937 muxer:
> http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2010-August/094317.html
>
> One needs to set the AES0 & 0x02 (non-audio) bit during playback so that
> the data is not transmitted as normal 8 channel PCM audio.

Thanks, I applied both patches.

There are some magic numbers there like 0x8000, and I'm going to define
them...


Takashi

>
> ---
> Anssi Hannula (2):
> ALSA: hda - Set Stream Type in Stream Format according to AES0
> ALSA: hda - Add support for HDMI HBR passthrough
>
> sound/pci/hda/hda_codec.c | 6 ++++-
> sound/pci/hda/hda_codec.h | 6 ++++-
> sound/pci/hda/hda_intel.c | 3 +-
> sound/pci/hda/patch_hdmi.c | 40 ++++++++++++++++++++++++++++++++++++++-
> sound/pci/hda/patch_intelhdmi.c | 3 +-
> sound/pci/hda/patch_nvhdmi.c | 3 +-
> 6 files changed, 53 insertions(+), 8 deletions(-)
>

2010-08-03 11:04:48

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH 0/2] ALSA: hda - support HDMI HBR passthrough

At Tue, 3 Aug 2010 14:04:01 +0300,
Anssi Hannula wrote:
>
> Takashi Iwai kirjoitti tiistai, 3. elokuuta 2010 13:59:09:
> > At Tue, 3 Aug 2010 13:28:56 +0300,
> >
> > Anssi Hannula wrote:
> > > Hi all!
> > >
> > > This patchset adds support for passing through IEC 61937 encapsulated
> > > compressed audio at high bitrates (i.e. those over 6.144Mbps).
> > > At least TrueHD and DTS-HD are such formats.
> > >
> > > I've tested this using an NVIDIA hdmi codec and the following ffmpeg
> > > patch which adds support for TrueHD in its IEC 61937 muxer:
> > > http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2010-August/094317.html
> > >
> > > One needs to set the AES0 & 0x02 (non-audio) bit during playback so that
> > > the data is not transmitted as normal 8 channel PCM audio.
> >
> > Thanks, I applied both patches.
> >
> > There are some magic numbers there like 0x8000, and I'm going to define
> > them...
>
> Yeah, I guess all the Stream Format bits should be defined to get rid of all
> the existing magic numbers in snd_hda_calc_stream_format() as well.

Exactly.


Takashi

2010-08-03 11:13:05

by Anssi Hannula

[permalink] [raw]
Subject: Re: [PATCH 0/2] ALSA: hda - support HDMI HBR passthrough

Takashi Iwai kirjoitti tiistai, 3. elokuuta 2010 13:59:09:
> At Tue, 3 Aug 2010 13:28:56 +0300,
>
> Anssi Hannula wrote:
> > Hi all!
> >
> > This patchset adds support for passing through IEC 61937 encapsulated
> > compressed audio at high bitrates (i.e. those over 6.144Mbps).
> > At least TrueHD and DTS-HD are such formats.
> >
> > I've tested this using an NVIDIA hdmi codec and the following ffmpeg
> > patch which adds support for TrueHD in its IEC 61937 muxer:
> > http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2010-August/094317.html
> >
> > One needs to set the AES0 & 0x02 (non-audio) bit during playback so that
> > the data is not transmitted as normal 8 channel PCM audio.
>
> Thanks, I applied both patches.
>
> There are some magic numbers there like 0x8000, and I'm going to define
> them...

Yeah, I guess all the Stream Format bits should be defined to get rid of all
the existing magic numbers in snd_hda_calc_stream_format() as well.

>
> Takashi
>
> > ---
> >
> > Anssi Hannula (2):
> > ALSA: hda - Set Stream Type in Stream Format according to AES0
> > ALSA: hda - Add support for HDMI HBR passthrough
> >
> > sound/pci/hda/hda_codec.c | 6 ++++-
> > sound/pci/hda/hda_codec.h | 6 ++++-
> > sound/pci/hda/hda_intel.c | 3 +-
> > sound/pci/hda/patch_hdmi.c | 40
> > ++++++++++++++++++++++++++++++++++++++- sound/pci/hda/patch_intelhdmi.c
> > | 3 +-
> > sound/pci/hda/patch_nvhdmi.c | 3 +-
> > 6 files changed, 53 insertions(+), 8 deletions(-)

--
Anssi Hannula