diff mbox

Question about Conversion to S24_LE from S24_3LE

Message ID 61B6C8BF61481342973655BC8AB0FF355AE2F4@PGSMSX101.gar.corp.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tan, Seng Kai April 18, 2016, 9:24 a.m. UTC
Hi Takashi,

I am facing similar problem like this issue, hope to get your advice.
http://mailman.alsa-project.org/pipermail/alsa-devel/2012-August/054241.html

I try to turn on S24_LE support for HDMI Audio using below patch. When I aplay S24_LE file it works fine.
The problem happen when I aplay S24_3LE file, I get and extremely low volume.

When I aplay S24_LE file, I get an left justified value in I2S, this is an expected result:
Front end S24_LE  :  0x12345600(in 4bytes, LSB 0 padding)
Back end  S24_3LE :  0x12345600(in 4bytes, LSB 0 padding)

When I aplay S24_3LE file, I get an extremely low output volume. 
Front end S24_3LE  :  0x123456(in 3bytes, No padding)
Back end  S24_LE :  0x00123456(in 4bytes, MSB 0 padding)

Can you advice how to tell the alsa plugin to pad in LSB instead of MSB?

Below are the patch I used to turn on S24_LE for HDA .

Regards,
Seng Kai




From 33f182fe1f6d1e49d0618559d1212b619ec902ce Mon Sep 17 00:00:00 2001
From: "SengKai,Tan" <seng.kai.tan@intel.com>
Date: Fri, 8 Apr 2016 17:34:51 +0800
Subject: [PATCH] ALSA: hda: S24_LE format support for HDA Audio

This patch is to add S24_LE support for  HDMI audio
and HDA codec.

Before this patch, HDMI and HDA codec audio only
supported S16_LE and S32_LE. Let's say if user would
like to play S24_LE file, it has to use plugin to
convert to either S16_LE or S32_LE which will
increase in processing and less efficient in utilize
the resources.

On the other side, let's say connected HDMI monitor
support S16_LE and S24_LE. Before this patch is applied
audio has to be converted to S16_LE. That will reduce
the audio quality.

Signed-off-by: Tan, Seng Kai <seng.kai.tan@intel.com>
---
 sound/pci/hda/hda_codec.c  | 6 ++++--
 sound/pci/hda/hda_eld.c    | 6 ++++--
 sound/pci/hda/patch_hdmi.c | 3 ++-
 3 files changed, 10 insertions(+), 5 deletions(-)

Comments

Clemens Ladisch April 18, 2016, 9:32 a.m. UTC | #1
Tan, Seng Kai wrote:
> I am facing similar problem like this issue, hope to get your advice.
> http://mailman.alsa-project.org/pipermail/alsa-devel/2012-August/054241.html

And the answer is the same.

> I try to turn on S24_LE support for HDMI Audio using below patch.

Your hardware does not support S24_LE.

24-bit samples use the S32_LE format (unless you have very exotic
hardware, but HDA isn't).

> Back end  S24_LE :  0x00123456(in 4bytes, MSB 0 padding)

This is how S24_LE works.

> Can you advice how to tell the alsa plugin to pad in LSB instead of MSB?

Use S32_LE.


Regards,
Clemens
Tan, Seng Kai April 18, 2016, 9:54 a.m. UTC | #2
Thanks Clemens

Tan, Seng Kai wrote:
>> I am facing similar problem like this issue, hope to get your advice.
>> http://mailman.alsa-project.org/pipermail/alsa-devel/2012-August/05424
>> 1.html

>And the answer is the same.

>> I try to turn on S24_LE support for HDMI Audio using below patch.
>Your hardware does not support S24_LE.
>24-bit samples use the S32_LE format (unless you have very exotic hardware, but HDA isn't).
We have another I2S hardware which is able to support S24L_LE and S32_LE format, 
when I use -Dplughw to play S24_3LE format the same things happen. It pad the 0 in MSB
the whole data is shift to right and the audio volume is lower. Is this the problem for alsa plugins?

>> Back end  S24_LE :  0x00123456(in 4bytes, MSB 0 padding)
>This is how S24_LE works.
S24_LE in wav file supposed to be in format  0x00123456 ( 0 pad MSB) or
0x12345600 ( 0 pad LSB) which one is correct? I am a bit confuse here, because 
When I open file with 0x12345600 ( 0 pad LSB) using audacity, it is able to view the file
But not for 0x00123456 ( 0 pad MSB).

>> Can you advice how to tell the alsa plugin to pad in LSB instead of MSB?
>Use S32_LE.
Question: is all HDMI support 24 bit must have 32bit support? My concern is it don't
And we want to maximize the quality to 24bit. 

Regards,
Seng Kai
Clemens Ladisch April 18, 2016, 12:01 p.m. UTC | #3
Tan, Seng Kai wrote:
>> Your hardware does not support S24_LE.
>> 24-bit samples use the S32_LE format (unless you have very exotic hardware, but HDA isn't).
>
> We have another I2S hardware which is able to support S24L_LE and S32_LE format,

The format on the codec's bus has almost nothing to do with the ALSA
sample format.

The Sxx_xE format describes how the samples are formatted in memory,
i.e., how the DMA controller expects to read them.

> S24_LE in wav file

.wav files do no use ALSA sample formats.

Please describe the values of the header fields in this .wav file.

> Question: is all HDMI support 24 bit must have 32bit support?

That depends on the DMA controller.  Most use 32-bit alignment for
24-bit samples.


Regards,
Clemens
Tan, Seng Kai April 19, 2016, 12:57 a.m. UTC | #4
Tan, Seng Kai wrote:
>>> Your hardware does not support S24_LE.
>>> 24-bit samples use the S32_LE format (unless you have very exotic hardware, but HDA isn't).
>>
>> We have another I2S hardware which is able to support S24L_LE and 
>> S32_LE format,

>The format on the codec's bus has almost nothing to do with the ALSA sample format.

>The Sxx_xE format describes how the samples are formatted in memory, i.e., how the DMA controller expects to read them.

I think I get what you mean. 
The input to the driver should be 0x123456 (3 byte, no padding)
And the driver supposed to arrange it to 0x12345600 (4 byte, LSB padding for left justified)
That is because the driver do not support and the value get truncate

>> S24_LE in wav file

>.wav files do no use ALSA sample formats.

>Please describe the values of the header fields in this .wav file.

qwavheaderdump -F ~/Public/workspace/aud_file/Tones/2ch_48sine_S24_LE.wav
/home/ilab/Public/workspace/aud_file/Tones/2ch_48sine_S24_LE.wav (11520044 bytes):
        riff: 'RIFF'
        riff length: 11520036
        wave: 'WAVE'
        fmt: 'fmt '
        fmt length: 16
        format: 1
        channels: 2
        sample rate: 48000
        bytes/second: 384000
        bytes/sample: 8
                 bytes/sample field should be 1, 2 or 4
                don't know which value must be set...

        bits/sample: 24
        data: 'data'
        data length: 11520000

Regards,
Clemens
Clemens Ladisch April 19, 2016, 7:27 a.m. UTC | #5
Tan, Seng Kai wrote:
> The input to the driver should be 0x123456 (3 byte, no padding)
> And the driver supposed to arrange it to 0x12345600 (4 byte, LSB padding for left justified)

No, the kernel driver should never change sample data.

If the hardware supports only 32-bit-aligned samples, then the driver
must declare that.  Any needed conversions are then done in user space.

>>> S24_LE in wav file
>
> qwavheaderdump -F ~/Public/workspace/aud_file/Tones/2ch_48sine_S24_LE.wav
>         channels: 2
>         sample rate: 48000
>         bytes/second: 384000
>         bytes/sample: 8
>         bits/sample: 24

This is not correct according to the .wav specification; the
wBitsPerSamples field must be the container size, which is 32 here (as
shown by nChannels and nBlockAlign).

If the number of valid bits is less than the container size, the file
must use the wValidBitsPerSample field in the WAVEFORMATEXTENSIBLE
structure.

Anyway, .wav files cannot describe or use S24_LE samples, they use
either S32_LE (as in this file) or S24_3LE.


Regards,
Clemens
diff mbox

Patch

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 57197be..9e737bb 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3501,14 +3501,16 @@  int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 				if (val & AC_SUPPCM_BITS_32)
 					formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
 				if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
-					formats |= SNDRV_PCM_FMTBIT_S32_LE;
+					formats |= SNDRV_PCM_FMTBIT_S24_LE |
+						SNDRV_PCM_FMTBIT_S32_LE;
 				if (val & AC_SUPPCM_BITS_24)
 					bps = 24;
 				else if (val & AC_SUPPCM_BITS_20)
 					bps = 20;
 			} else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
 					  AC_SUPPCM_BITS_32)) {
-				formats |= SNDRV_PCM_FMTBIT_S32_LE;
+				formats |= SNDRV_PCM_FMTBIT_S24_LE |
+					SNDRV_PCM_FMTBIT_S32_LE;
 				if (val & AC_SUPPCM_BITS_32)
 					bps = 32;
 				else if (val & AC_SUPPCM_BITS_24)
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 0e6d753..65bfe10 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -613,12 +613,14 @@  void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
 			channels_max = a->channels;
 		if (a->format == AUDIO_CODING_TYPE_LPCM) {
 			if (a->sample_bits & AC_SUPPCM_BITS_20) {
-				formats |= SNDRV_PCM_FMTBIT_S32_LE;
+				formats |= SNDRV_PCM_FMTBIT_S24_LE |
+					SNDRV_PCM_FMTBIT_S32_LE;
 				if (maxbps < 20)
 					maxbps = 20;
 			}
 			if (a->sample_bits & AC_SUPPCM_BITS_24) {
-				formats |= SNDRV_PCM_FMTBIT_S32_LE;
+				formats |= SNDRV_PCM_FMTBIT_S24_LE |
+					SNDRV_PCM_FMTBIT_S32_LE;
 				if (maxbps < 24)
 					maxbps = 24;
 			}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index d02eccd..8cbde13 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -2489,7 +2489,8 @@  static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = {
 	 SNDRV_PCM_RATE_192000)
 #define SUPPORTED_MAXBPS	24
 #define SUPPORTED_FORMATS \
-	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
+	SNDRV_PCM_FMTBIT_S32_LE)
 #endif
 
 static int nvhdmi_7x_init_2ch(struct hda_codec *codec)