hal: Add support for TrueHD HDMI pass-through

Add TrueHD format for apq8098 compress pass-through.

Change-Id: Ica0e11aee535c6f7e21c26ab391e5e7bb71c6b02
diff --git a/hal/audio_extn/passthru.c b/hal/audio_extn/passthru.c
index eaa8c0a..dd4d4d4 100644
--- a/hal/audio_extn/passthru.c
+++ b/hal/audio_extn/passthru.c
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -46,7 +46,8 @@
     AUDIO_FORMAT_E_AC3,
     AUDIO_FORMAT_E_AC3_JOC,
     AUDIO_FORMAT_DTS,
-    AUDIO_FORMAT_DTS_HD
+    AUDIO_FORMAT_DTS_HD,
+    AUDIO_FORMAT_DOLBY_TRUEHD
 };
 
 /*
@@ -216,6 +217,8 @@
     bool passt = false;
     switch (out->format) {
     case AUDIO_FORMAT_E_AC3:
+    case AUDIO_FORMAT_DTS_HD:
+    case AUDIO_FORMAT_DOLBY_TRUEHD:
         if (platform_is_edid_supported_format(adev->platform, out->format)) {
             ALOGV("%s:PASSTHROUGH supported for format %x",
                    __func__, out->format);
@@ -249,13 +252,6 @@
             passt = true;
         }
         break;
-    case AUDIO_FORMAT_DTS_HD:
-        if (platform_is_edid_supported_format(adev->platform, out->format)) {
-            ALOGV("%s:PASSTHROUGH supported for format %x",
-                   __func__, out->format);
-            passt = true;
-        }
-        break;
     default:
         ALOGV("%s:Passthrough not supported", __func__);
     }
diff --git a/hal/audio_extn/qaf.c b/hal/audio_extn/qaf.c
index ed66934..caf64ee 100644
--- a/hal/audio_extn/qaf.c
+++ b/hal/audio_extn/qaf.c
@@ -351,7 +351,8 @@
                 case AUDIO_FORMAT_AC3:
                 case AUDIO_FORMAT_E_AC3:
                 case AUDIO_FORMAT_DTS:
-                case AUDIO_FORMAT_DTS_HD: {
+                case AUDIO_FORMAT_DTS_HD:
+                case AUDIO_FORMAT_DOLBY_TRUEHD: {
                     is_enabled = true;
                     break;
                 }
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index b8be7aa..27bbae8 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -70,6 +70,10 @@
 #define BASE_TABLE_SIZE 64
 #define MAX_BASEINDEX_LEN 256
 
+#ifndef SND_AUDIOCODEC_TRUEHD
+#define SND_AUDIOCODEC_TRUEHD 0x00000023
+#endif
+
 #ifdef AUDIO_EXTERNAL_HDMI_ENABLED
 #define PROFESSIONAL        (1<<0)      /* 0 = consumer, 1 = professional */
 #define NON_LPCM            (1<<1)      /* 0 = audio, 1 = non-audio */
@@ -130,6 +134,7 @@
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_DTS),
     STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
+    STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
 #ifdef AUDIO_EXTN_FORMATS_ENABLED
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
     STRING_TO_ENUM(AUDIO_FORMAT_WMA),
@@ -900,7 +905,8 @@
         app_type_cfg[len++] = app_type;
         app_type_cfg[len++] = acdb_dev_id;
         if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
-            (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
+            (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC) ||
+            (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD))
             && audio_extn_passthru_is_passthrough_stream(usecase->stream.out)) {
             app_type_cfg[len++] = sample_rate * 4;
         } else {
@@ -1246,6 +1252,9 @@
     case AUDIO_FORMAT_DTS_HD:
         id = SND_AUDIOCODEC_DTS;
         break;
+    case AUDIO_FORMAT_DOLBY_TRUEHD:
+        id = SND_AUDIOCODEC_TRUEHD;
+        break;
     case AUDIO_FORMAT_DSD:
         id = SND_AUDIOCODEC_DSD;
         break;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 68a552d..de8b388 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -293,6 +293,7 @@
     STRING_TO_ENUM(AUDIO_FORMAT_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
+    STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
     STRING_TO_ENUM(AUDIO_FORMAT_DTS),
     STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
 };
@@ -511,6 +512,7 @@
         format == AUDIO_FORMAT_PCM_16_BIT ||
         format == AUDIO_FORMAT_AC3 ||
         format == AUDIO_FORMAT_E_AC3 ||
+        format == AUDIO_FORMAT_DOLBY_TRUEHD ||
         format == AUDIO_FORMAT_DTS ||
         format == AUDIO_FORMAT_DTS_HD ||
         format == AUDIO_FORMAT_FLAC ||
@@ -1313,6 +1315,11 @@
         out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
     }
 
+    if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
+        ALOGV(":%s HDMI supports TRUE HD format", __func__);
+        out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
+    }
+
     if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
         ALOGV(":%s HDMI supports DTS format", __func__);
         out->supported_formats[i++] = AUDIO_FORMAT_DTS;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 935bae3..2ab9408 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -5457,12 +5457,20 @@
             channels = max_supported_channels;
 
     } else {
-        /*During pass through set default bit width and channels*/
-        channels = DEFAULT_HDMI_OUT_CHANNELS;
+        /*During pass through set default bit width */
+        if (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD)
+            channels = 8;
+        else
+            channels = DEFAULT_HDMI_OUT_CHANNELS;
+
         if ((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
-            (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
+            (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC) ||
+            (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD))
             sample_rate = sample_rate * 4 ;
 
+        if (!edid_is_supported_sr(edid_info, sample_rate))
+                sample_rate = edid_get_highest_supported_sr(edid_info);
+
         bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
         /* We force route so that the BE format can be set to Compr */
     }
@@ -6301,6 +6309,10 @@
         ALOGV("%s:E_AC3", __func__);
         format = DOLBY_DIGITAL_PLUS;
         break;
+    case AUDIO_FORMAT_DOLBY_TRUEHD:
+        ALOGV("%s:MAT", __func__);
+        format = MAT;
+        break;
     case AUDIO_FORMAT_DTS:
         ALOGV("%s:DTS", __func__);
         format = DTS;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 1d32409..8f7e125 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -5175,12 +5175,20 @@
             channels = max_supported_channels;
 
     } else {
-        /*During pass through set default bit width and channels*/
-        channels = DEFAULT_HDMI_OUT_CHANNELS;
+        /*During pass through set default bit width */
+        if (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD)
+            channels = 8;
+        else
+            channels = DEFAULT_HDMI_OUT_CHANNELS;
+
         if ((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
-            (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC))
+            (usecase->stream.out->format == AUDIO_FORMAT_E_AC3_JOC) ||
+            (usecase->stream.out->format == AUDIO_FORMAT_DOLBY_TRUEHD))
             sample_rate = sample_rate * 4 ;
 
+        if (!edid_is_supported_sr(edid_info, sample_rate))
+                sample_rate = edid_get_highest_supported_sr(edid_info);
+
         bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
         /* We force route so that the BE format can be set to Compr */
     }
@@ -5970,6 +5978,10 @@
         ALOGV("%s:E_AC3", __func__);
         format = DOLBY_DIGITAL_PLUS;
         break;
+    case AUDIO_FORMAT_DOLBY_TRUEHD:
+        ALOGV("%s:MAT", __func__);
+        format = MAT;
+        break;
     case AUDIO_FORMAT_DTS:
         ALOGV("%s:DTS", __func__);
         format = DTS;
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index 1f65368..9fe713d 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -77,7 +77,8 @@
     FILE_EAC3_JOC,
     FILE_DTS,
     FILE_MP2,
-    FILE_APTX
+    FILE_APTX,
+    FILE_TRUEHD
 };
 
 typedef enum {
@@ -962,6 +963,9 @@
         case FILE_APTX:
             stream_info->config.offload_info.format = AUDIO_FORMAT_APTX;
             break;
+        case FILE_TRUEHD:
+            stream_info->config.offload_info.format = AUDIO_FORMAT_DOLBY_TRUEHD;
+            break;
         default:
            fprintf(log_file, "Does not support given filetype\n");
            fprintf(stderr, "Does not support given filetype\n");