Fugu Audio HAL: set non-audio bit for compressed audio

Indicate that the SPDIF data is actually compressed audio
wrapped in a data burst and not PCM. This can prevent noise
on some devices.

Bug: 22576112
Change-Id: I5d14435625700bd24f4df63735363b0105c89f4e
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/libaudio/AudioHardwareOutput.cpp b/libaudio/AudioHardwareOutput.cpp
index d0365db..03fd958 100644
--- a/libaudio/AudioHardwareOutput.cpp
+++ b/libaudio/AudioHardwareOutput.cpp
@@ -15,7 +15,7 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "AudioHAL:AudioHardwareOutput"
+#define LOG_TAG "AudioHAL_AudioHardwareOutput"
 
 #include <utils/Log.h>
 
@@ -115,12 +115,13 @@
     AudioStreamOut** pp_out;
     AudioStreamOut* out;
 
+    bool isIec958NonAudio = (flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) != 0;
     if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
         pp_out = &mMainOutput;
-        out = new AudioStreamOut(*this, false);
+        out = new AudioStreamOut(*this, false, isIec958NonAudio);
     } else {
         pp_out = &mMCOutput;
-        out = new AudioStreamOut(*this, true);
+        out = new AudioStreamOut(*this, true, isIec958NonAudio);
     }
 
     if (out == NULL) {
diff --git a/libaudio/AudioStreamOut.cpp b/libaudio/AudioStreamOut.cpp
index d8c42f7..bb70bbd 100644
--- a/libaudio/AudioStreamOut.cpp
+++ b/libaudio/AudioStreamOut.cpp
@@ -37,7 +37,7 @@
 
 namespace android {
 
-AudioStreamOut::AudioStreamOut(AudioHardwareOutput& owner, bool mcOut)
+AudioStreamOut::AudioStreamOut(AudioHardwareOutput& owner, bool mcOut, bool isIec958NonAudio)
     : mRenderPosition(0)
     , mFramesPresented(0)
     , mLastPresentationPosition(0)
@@ -48,6 +48,7 @@
     , mAudioFlingerTgtDevices(0)
     , mIsMCOutput(mcOut)
     , mInStandby(false)
+    , mIsIec958NonAudio(isIec958NonAudio)
     , mReportedAvailFail(false)
 {
     assert(mLocalClock.initCheck());
diff --git a/libaudio/AudioStreamOut.h b/libaudio/AudioStreamOut.h
index 2cc84df..a33b91a 100644
--- a/libaudio/AudioStreamOut.h
+++ b/libaudio/AudioStreamOut.h
@@ -33,7 +33,7 @@
 
 class AudioStreamOut {
   public:
-    AudioStreamOut(AudioHardwareOutput& owner, bool mcOut);
+    AudioStreamOut(AudioHardwareOutput& owner, bool mcOut, bool isIec958NonAudio);
     ~AudioStreamOut();
 
     uint32_t            latency() const;
@@ -68,6 +68,8 @@
 
     ssize_t             write(const void* buffer, size_t bytes);
 
+    bool                isIec958NonAudio() const { return mIsIec958NonAudio; }
+
 protected:
     // Lock in this order to avoid deadlock.
     //    mRoutingLock
@@ -122,6 +124,8 @@
     bool            mIsMCOutput;
     // Is the stream on standby?
     bool            mInStandby;
+    // Is the stream compressed audio in SPDIF data bursts?
+    const bool      mIsIec958NonAudio;
 
     // reduce log spew
     bool            mReportedAvailFail;
diff --git a/libaudio/HDMIAudioOutput.cpp b/libaudio/HDMIAudioOutput.cpp
index c9cc36f..d79cb5e 100644
--- a/libaudio/HDMIAudioOutput.cpp
+++ b/libaudio/HDMIAudioOutput.cpp
@@ -15,11 +15,12 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "AudioHAL:HDMIAudioOutput"
+#define LOG_TAG "AudioHAL_HDMIAudioOutput"
 
 #include <utils/Log.h>
 
 #include <stdint.h>
+#include <sound/asound.h> // bionic
 
 #include "AudioHardwareOutput.h"
 #include "AudioStreamOut.h"
@@ -58,6 +59,8 @@
 
     setupInternal();
 
+    setChannelStatusToCompressed(stream.isIec958NonAudio());
+
     return initCheck();
 }
 
@@ -65,6 +68,52 @@
 {
 }
 
+#define IEC958_AES0_NONAUDIO      (1<<1)   /* 0 = audio, 1 = non-audio */
+
+void HDMIAudioOutput::setChannelStatusToCompressed(bool compressed)
+{
+    struct snd_aes_iec958  iec958;
+    struct mixer* mixer;
+    int err;
+    const size_t count = 1;
+
+    ALOGI("setChannelStatusToCompressed %d", compressed);
+
+    mixer = mixer_open(mALSACardID);
+    if (mixer == NULL) {
+        ALOGE("Couldn't open mixer on alsa id %d", mALSACardID);
+        return;
+    }
+
+    const char *ctlName = "IEC958 Playback Default";
+    struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, ctlName);
+    if (ctl == NULL) {
+        ALOGE("Couldn't get mixer ctl %s", ctlName);
+        goto finish;
+    }
+
+    // Set count to 1 so we get one complete iec958 structure.
+    err = mixer_ctl_get_array(ctl, &iec958, count);
+    if (err < 0) {
+        ALOGE("Channel Status bit get has failed\n");
+        goto finish;
+    }
+
+    if (compressed) {
+        iec958.status[0] |= IEC958_AES0_NONAUDIO;
+    } else {
+        iec958.status[0] &= ~IEC958_AES0_NONAUDIO;
+    }
+
+    err = mixer_ctl_set_array(ctl, &iec958, count);
+    if (err < 0) {
+        ALOGE("Channel Status bit set has failed\n");
+    }
+
+finish:
+    mixer_close(mixer);
+}
+
 void HDMIAudioOutput::dump(String8& result)
 {
     const size_t SIZE = 256;
diff --git a/libaudio/HDMIAudioOutput.h b/libaudio/HDMIAudioOutput.h
index f79afc5..9b8ba0e 100644
--- a/libaudio/HDMIAudioOutput.h
+++ b/libaudio/HDMIAudioOutput.h
@@ -38,6 +38,7 @@
 
 protected:
     virtual void        applyPendingVolParams();
+    void                setChannelStatusToCompressed(bool compressed);
 };
 
 }  // namespace android