Mnemoc, is this confirmed/merged?

Olliver

On 01/27/14 18:54, Patrick Wood wrote:
The original modifications for this patch originate from some custom
changes made to the 3.3 Android kernel by huangxin at allwinnertech.com.

The A10/A20 DMA engine for HDMI audio only supports 16 or 32-bit
transfers. The documentation says 16, 20, and 24 bits, but I have not
been able to get 24-bit audio, ether 3-bytes (PCM_FMTBIT_24_3LE) or
4-bytes (PCM_FMTBIT_24_LE) to work.

This patch removes the non-working PCM formats, PCM_FMTBIT_S18_3LE
and PCM_FMTBIT_S20_3LE, and PCM_FMTBIT_S24_LE and adds suppor for
32-bit HDMI audio (PCM_FMTBIT_S32_LE).  It's possible that other 32-bit
formats, like PCM_FMTBIT_U32_LE or PCM_FMTBIT_FLOAT_LE might work, but
couldn't be tested.

This patch was tested with 24-bit and 32-bit .wav files and the ALSA
"plughw" plugin (for upconverting the 24-bit audio files to 23-bits)
with aplay -v to verify that the target format was S32_LE.

Signed-off-by: Patrick Wood <patrickhw...@gmail.com>
---
  drivers/video/sunxi/hdmi/drv_hdmi.c         |    6 ++++++
  drivers/video/sunxi/hdmi/hdmi_core.c        |   30 +++++++++++++++++++++------
  drivers/video/sunxi/hdmi/hdmi_core.h        |    1 +
  include/linux/drv_hdmi.h                    |    1 +
  sound/soc/sunxi/hdmiaudio/sndhdmi.c         |   16 +++++++++++++-
  sound/soc/sunxi/hdmiaudio/sunxi-hdmiaudio.c |    6 ++++--
  sound/soc/sunxi/hdmiaudio/sunxi-hdmipcm.c   |    3 ++-
  7 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/drivers/video/sunxi/hdmi/drv_hdmi.c 
b/drivers/video/sunxi/hdmi/drv_hdmi.c
index a8d3cef..283d2ae 100644
--- a/drivers/video/sunxi/hdmi/drv_hdmi.c
+++ b/drivers/video/sunxi/hdmi/drv_hdmi.c
@@ -208,6 +208,12 @@ static __s32 Hdmi_Set_Audio_Para(hdmi_audio_t *audio_para)
        if (!audio_para)
                return -1;

+       if (audio_para->sample_bit != audio_info.sample_bit) {
+               if (hdmi_state >= HDMI_State_Audio_config)
+                       hdmi_state = HDMI_State_Audio_config;
+               audio_info.sample_bit = audio_para->sample_bit;
+       }
+
        if (audio_para->sample_rate != audio_info.sample_rate) {
                audio_info.sample_rate = audio_para->sample_rate;
                change = audio_info.audio_en;
diff --git a/drivers/video/sunxi/hdmi/hdmi_core.c 
b/drivers/video/sunxi/hdmi/hdmi_core.c
index c1c4c9c..a6dd01f 100644
--- a/drivers/video/sunxi/hdmi/hdmi_core.c
+++ b/drivers/video/sunxi/hdmi/hdmi_core.c
@@ -580,8 +580,14 @@ __s32 audio_config(void)
                return 0;

        if (audio_info.channel_num == 1) {
-               /* audio fifo rst and select ddma, 2 ch 16bit pcm */
-               writel(0x00000000, HDMI_AUDIO_UNKNOWN_0);
+               if (audio_info.sample_bit == 32) {
+                       /* audio fifo rst and select ddma, 2 ch 32bit pcm */
+                       writel(0x000e0000, HDMI_AUDIO_UNKNOWN_0);
+               } else {
+                       /* audio fifo rst and select ddma, 2 ch 16bit pcm */
+                       writel(0x00000000, HDMI_AUDIO_UNKNOWN_0);
+               }
+
                /* ddma,pcm layout0 1ch */
                writel(0x00000000, HDMI_AUDIO_LAYOUT);
                writel(0x76543200, HDMI_AUDIO_UNKNOWN_1);
@@ -592,8 +598,14 @@ __s32 audio_config(void)
                writel(0x00000000, HDMI_AUDIO_INFOFRAME + 8);
                writel(0x00000000, HDMI_AUDIO_INFOFRAME + 12);
        } else if (audio_info.channel_num == 2) {
-               /* audio fifo rst and select ddma, 2 ch 16bit pcm */
-               writel(0x00000000, HDMI_AUDIO_UNKNOWN_0);
+               if (audio_info.sample_bit == 32) {
+                       /* audio fifo rst and select ddma, 2 ch 32bit pcm */
+                       writel(0x000e0000, HDMI_AUDIO_UNKNOWN_0);
+               } else {
+                       /* audio fifo rst and select ddma, 2 ch 16bit pcm */
+                       writel(0x00000000, HDMI_AUDIO_UNKNOWN_0);
+               }
+
                /* ddma,pcm layout0 2ch */
                writel(0x00000001, HDMI_AUDIO_LAYOUT);
                writel(0x76543210, HDMI_AUDIO_UNKNOWN_1);
@@ -604,8 +616,14 @@ __s32 audio_config(void)
                writel(0x00000000, HDMI_AUDIO_INFOFRAME + 8);
                writel(0x00000000, HDMI_AUDIO_INFOFRAME + 12);
        } else if (audio_info.channel_num == 8) {
-               /* audio fifo rst and select ddma, 2 ch 16bit pcm */
-               writel(0x00000000, HDMI_AUDIO_UNKNOWN_0);
+               if (audio_info.sample_bit == 32) {
+                       /* audio fifo rst and select ddma, 2 ch 32bit pcm */
+                       writel(0x000e0000, HDMI_AUDIO_UNKNOWN_0);
+               } else {
+                       /* audio fifo rst and select ddma, 2 ch 16bit pcm */
+                       writel(0x00000000, HDMI_AUDIO_UNKNOWN_0);
+               }
+
                /* ddma,pcm layout1 8ch */
                writel(0x0000000f, HDMI_AUDIO_LAYOUT);
                writel(0x76543210, HDMI_AUDIO_UNKNOWN_1);
diff --git a/drivers/video/sunxi/hdmi/hdmi_core.h 
b/drivers/video/sunxi/hdmi/hdmi_core.h
index 50abbd1..7f11557 100644
--- a/drivers/video/sunxi/hdmi/hdmi_core.h
+++ b/drivers/video/sunxi/hdmi/hdmi_core.h
@@ -84,6 +84,7 @@ typedef struct audio_timing {
        __s32 ACR_N;
        __s32 CH_STATUS0;
        __s32 CH_STATUS1;
+       __u8  sample_bit;

  } HDMI_AUDIO_INFO;

diff --git a/include/linux/drv_hdmi.h b/include/linux/drv_hdmi.h
index ae0ae6d..e40180d 100644
--- a/include/linux/drv_hdmi.h
+++ b/include/linux/drv_hdmi.h
@@ -38,6 +38,7 @@ typedef struct
        __u8    ws_pol;
        __u8    just_pol;
        __u8    channel_num;
+       __u8    sample_bit;
  }hdmi_audio_t;

  typedef struct
diff --git a/sound/soc/sunxi/hdmiaudio/sndhdmi.c 
b/sound/soc/sunxi/hdmiaudio/sndhdmi.c
index d875c17..f291c4b 100644
--- a/sound/soc/sunxi/hdmiaudio/sndhdmi.c
+++ b/sound/soc/sunxi/hdmiaudio/sndhdmi.c
@@ -46,7 +46,7 @@ EXPORT_SYMBOL(audio_set_hdmi_func);

  #define SNDHDMI_RATES  (SNDRV_PCM_RATE_8000_192000|SNDRV_PCM_RATE_KNOT)
  #define SNDHDMI_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
-                                    SNDRV_PCM_FMTBIT_S18_3LE | 
SNDRV_PCM_FMTBIT_S20_3LE)
+                               SNDRV_PCM_FMTBIT_S32_LE)

  static int sndhdmi_mute(struct snd_soc_dai *dai, int mute)
  {
@@ -71,6 +71,20 @@ static int sndhdmi_hw_params(struct snd_pcm_substream 
*substream,
  {
        hdmi_para.sample_rate = params_rate(params);
        hdmi_para.channel_num = params_channels(params);
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               hdmi_para.sample_bit = 16;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               hdmi_para.sample_bit = 32;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (4 == hdmi_para.channel_num)
+               hdmi_para.channel_num = 2;
+
        g_hdmi_func.hdmi_set_audio_para(&hdmi_para);
        g_hdmi_func.hdmi_audio_enable(1, 1);

diff --git a/sound/soc/sunxi/hdmiaudio/sunxi-hdmiaudio.c 
b/sound/soc/sunxi/hdmiaudio/sunxi-hdmiaudio.c
index 4fdd848..5080f10 100644
--- a/sound/soc/sunxi/hdmiaudio/sunxi-hdmiaudio.c
+++ b/sound/soc/sunxi/hdmiaudio/sunxi-hdmiaudio.c
@@ -557,12 +557,14 @@ static struct snd_soc_dai_driver sunxi_hdmiaudio_dai = {
                .channels_min = 1,
                .channels_max = 2,
                .rates = SUNXI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | 
SNDRV_PCM_FMTBIT_S24_LE,},
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
+       },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
                .rates = SUNXI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | 
SNDRV_PCM_FMTBIT_S24_LE,},
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
+       },
        .symmetric_rates = 1,
        .ops = &sunxi_hdmiaudio_dai_ops,
  };
diff --git a/sound/soc/sunxi/hdmiaudio/sunxi-hdmipcm.c 
b/sound/soc/sunxi/hdmiaudio/sunxi-hdmipcm.c
index b62daea..08221d2 100644
--- a/sound/soc/sunxi/hdmiaudio/sunxi-hdmipcm.c
+++ b/sound/soc/sunxi/hdmiaudio/sunxi-hdmipcm.c
@@ -39,7 +39,8 @@ static const struct snd_pcm_hardware sunxi_pcm_hardware = {
        .info                   = SNDRV_PCM_INFO_INTERLEAVED | 
SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                      SNDRV_PCM_INFO_MMAP | 
SNDRV_PCM_INFO_MMAP_VALID |
                                      SNDRV_PCM_INFO_PAUSE | 
SNDRV_PCM_INFO_RESUME,
-       .formats                = SNDRV_PCM_FMTBIT_S16_LE | 
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE |
+                                     SNDRV_PCM_FMTBIT_S32_LE,
        .rates                  = SNDRV_PCM_RATE_8000_192000 | 
SNDRV_PCM_RATE_KNOT,
        .rate_min               = 8000,
        .rate_max               = 192000,


--
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to