--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp	2017-03-20 17:17:49.000000000 +0100
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp	2017-04-07 12:25:01.000000000 +0200
@@ -1723,6 +1723,7 @@ void CAMLCodec::CloseDecoder()
   // return tsync to default so external apps work
   SysfsUtils::SetInt("/sys/class/tsync/enable", 1);
 
+  SetVideo3dMode(MODE_3D_DISABLE);
   ShowMainVideo(false);
 
   CloseAmlVideo();
@@ -2068,8 +2069,13 @@ void CAMLCodec::SetVideoSaturation(const
 
 void CAMLCodec::SetVideo3dMode(const int mode3d)
 {
+  static int old3dmode = MODE_3D_DISABLE;
+
+  if (mode3d == old3dmode)
+    return;
   CLog::Log(LOGDEBUG, "CAMLCodec::SetVideo3dMode:mode3d(0x%x)", mode3d);
   SysfsUtils::SetInt("/sys/class/ppmgr/ppmgr_3d_mode", mode3d);
+  old3dmode = mode3d;
 }
 
 std::string CAMLCodec::GetStereoMode()
@@ -2083,8 +2089,6 @@ std::string CAMLCodec::GetStereoMode()
     default:                                  stereo_mode = m_hints.stereo_mode; break;
   }
 
-  if(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_StereoInvert)
-    stereo_mode = RenderManager::GetStereoModeInvert(stereo_mode);
   return stereo_mode;
 }

 
--- a/xbmc/utils/AMLUtils.cpp	2017-03-20 17:17:49.000000000 +0100
+++ b/xbmc/utils/AMLUtils.cpp-neu	2017-04-07 18:36:03.924950912 +0200
@@ -25,14 +25,109 @@
 #include <fcntl.h>
 #include <string>
 
-#include "AMLUtils.h"
 #include "utils/CPUInfo.h"
+#include "rendering/RenderSystem.h"
+#include "settings/MediaSettings.h"
+#include "utils/AMLUtils.h"
 #include "utils/log.h"
 #include "utils/SysfsUtils.h"
 #include "utils/StringUtils.h"
 #include "guilib/gui3d.h"
 #include "utils/RegExp.h"
 
+#define MODE_HDMI3D_LR          "3dlr"
+#define MODE_HDMI3D_TB          "3dtb"
+#define MODE_HDMI3D_OFF         "3doff"
+
+static void aml_hdmi_3D_mode(const std::string mode3d)
+{
+  static std::string oldhdmi3dmode = MODE_HDMI3D_OFF;
+  static bool reset_disp_mode = false;
+
+  if (mode3d == oldhdmi3dmode)
+    return;
+
+  aml_set_sysfs_str("/sys/class/amhdmitx/amhdmitx0/config", mode3d.c_str());
+  oldhdmi3dmode = mode3d;
+
+  if (strstr(mode3d.c_str(), MODE_HDMI3D_OFF))
+  {
+    if (reset_disp_mode)
+    {
+      // Some 3D HDTVs will not exit from 3D mode with 3doff
+      char disp_mode[256] = {};
+      if (aml_get_sysfs_str("/sys/class/display/mode", disp_mode, 255) != -1)
+      {
+        aml_set_sysfs_int("/sys/class/graphics/fb0/blank", 1);
+        // Setting the same mode does not reset HDMI on M8
+        aml_set_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_mode", "720p");
+        aml_set_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_mode", disp_mode);
+        aml_set_sysfs_int("/sys/class/graphics/fb0/blank", 0);
+      }
+
+      reset_disp_mode = false;
+    }
+  }
+  else
+    reset_disp_mode = true;
+}
+
+
+int aml_set_sysfs_str(const char *path, const char *val)
+{
+  int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
+  if (fd >= 0)
+  {
+    write(fd, val, strlen(val));
+    close(fd);
+    return 0;
+  }
+  return -1;
+}
+
+int aml_get_sysfs_str(const char *path, char *valstr, const int size)
+{
+  int fd = open(path, O_RDONLY);
+  if (fd >= 0)
+  {
+    read(fd, valstr, size - 1);
+    valstr[strlen(valstr)] = '\0';
+    close(fd);
+    return 0;
+  }
+
+  sprintf(valstr, "%s", "fail");
+  return -1;
+}
+
+int aml_set_sysfs_int(const char *path, const int val)
+{
+  int fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
+  if (fd >= 0)
+  {
+    char bcmd[16];
+    sprintf(bcmd, "%d", val);
+    write(fd, bcmd, strlen(bcmd));
+    close(fd);
+    return 0;
+  }
+  return -1;
+}
+
+int aml_get_sysfs_int(const char *path)
+{
+  int val = -1;
+  int fd = open(path, O_RDONLY);
+  if (fd >= 0)
+  {
+    char bcmd[16];
+    read(fd, bcmd, sizeof(bcmd));
+    val = strtol(bcmd, NULL, 16);
+    close(fd);
+  }
+  return val;
+}
+
 bool aml_present()
 {
   static int has_aml = -1;
@@ -63,6 +158,80 @@ bool aml_hw3d_present()
   return has_hw3d == 1;
 }
 
+bool aml_supports_stereo(const int mode)
+{
+  static int last_mode = -1;
+  static bool last_rtn = false;
+  if (last_mode == mode)
+    return last_rtn;
+
+  char disp_cap_3d[256] = {};
+  if (aml_get_sysfs_str("/sys/class/amhdmitx/amhdmitx0/disp_cap_3d", disp_cap_3d, 255) == -1)
+  {
+    last_rtn = false;
+    last_mode = -1;
+    return last_rtn;
+  }
+
+  if (mode == RENDER_STEREO_MODE_INTERLACED && strstr(disp_cap_3d,"FramePacking"))
+    last_rtn = true;
+  else if (mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && strstr(disp_cap_3d,"TopBottom"))
+    last_rtn = true;
+  else if (mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && strstr(disp_cap_3d,"SidebySide"))
+    last_rtn = true;
+
+  last_mode = mode;
+
+  return last_rtn;
+}
+void aml_set_stereo_mode(const int mode, const int view)
+{
+  static int last_mode = -1;
+  // do nothing if mode matches last time someone called us.
+  if (last_mode == mode)
+    return;
+
+  if (!aml_supports_stereo(mode))
+  {
+    last_mode = mode;
+    return;
+  }
+
+  switch(mode)
+  {
+    default:
+      aml_hdmi_3D_mode("3doff");
+      break;
+    case RENDER_STEREO_MODE_SPLIT_VERTICAL:
+      aml_hdmi_3D_mode("3dlr");
+      break;
+    case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
+      aml_hdmi_3D_mode("3dtb");
+      break;
+
+    case RENDER_STEREO_MODE_INTERLACED:
+      {
+        std::string  stereo_mode;
+        switch(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_StereoMode)
+        {
+          case RENDER_STEREO_MODE_SPLIT_VERTICAL:
+            aml_hdmi_3D_mode("3dlr");
+            break;
+          case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
+            aml_hdmi_3D_mode("3dtb");
+            break;
+          default:
+            aml_hdmi_3D_mode("3doff");
+            break;
+        }
+      }
+      break;
+  }
+
+  return;
+}
+
+
 bool aml_wired_present()
 {
   static int has_wired = -1;


--- a/xbmc/utils/AMLUtils.h	2017-03-20 17:17:49.000000000 +0100
+++ b/xbmc/utils/AMLUtils.h-neu	2017-04-07 18:37:48.176081886 +0200
@@ -49,9 +49,16 @@ enum AML_SUPPORT_H264_4K2K
   AML_HAS_H264_4K2K_SAME_PROFILE
 };
 
+int aml_set_sysfs_str(const char *path, const char *val);
+int aml_get_sysfs_str(const char *path, char *valstr, const int size);
+int aml_set_sysfs_int(const char *path, const int val);
+int aml_get_sysfs_int(const char *path);
+
 bool aml_present();
 bool aml_permissions();
 bool aml_hw3d_present();
+bool aml_supports_stereo(const int mode);
+void aml_set_stereo_mode(const int mode, const int view);
 bool aml_wired_present();
 bool aml_support_hevc();
 bool aml_support_hevc_4k2k();


--- a/xbmc/rendering/gles/RenderSystemGLES.cpp	2017-03-20 17:17:49.000000000 +0100
+++ b/xbmc/rendering/gles/RenderSystemGLES.cpp	2017-04-07 12:27:25.000000000 +0200
@@ -652,17 +652,17 @@ GLint CRenderSystemGLES::GUIShaderGetBri
   return -1;
 }
 
-bool CRenderSystemGLES::SupportsStereo(RENDER_STEREO_MODE mode) const
+void CRenderSystemGLES::SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view)
 {
-  switch(mode)
-  {
-    case RENDER_STEREO_MODE_INTERLACED:
-      if (g_sysinfo.HasHW3DInterlaced())
-        return true;
+  CRenderSystemBase::SetStereoMode(mode, view);
+
+  g_sysinfo.HWSetStereoMode(mode, view);
+}
 
-    default:
-      return CRenderSystemBase::SupportsStereo(mode);
-  }
+
+bool CRenderSystemGLES::SupportsStereo(RENDER_STEREO_MODE mode) const
+{
+  return CRenderSystemBase::SupportsStereo(mode);
 }
 
 GLint CRenderSystemGLES::GUIShaderGetModel()


--- a/xbmc/rendering/gles/RenderSystemGLES.h	2017-03-20 17:17:49.000000000 +0100
+++ b/xbmc/rendering/gles/RenderSystemGLES.h	2017-04-07 12:28:34.000000000 +0200
@@ -78,6 +78,8 @@ public:
 
   void ApplyHardwareTransform(const TransformMatrix &matrix) override;
   void RestoreHardwareTransform() override;
+  void SetStereoMode(RENDER_STEREO_MODE mode, RENDER_STEREO_VIEW view);
+
   bool SupportsStereo(RENDER_STEREO_MODE mode) const override;
 
   bool TestRender() override;


--- a/xbmc/utils/SystemInfo.cpp	2017-04-10 07:04:02.489108706 +0200
+++ b/xbmc/utils/SystemInfo.cpp-neu	2017-04-10 07:06:00.487892843 +0200
@@ -21,6 +21,7 @@
 #include <limits.h>
 
 #include "threads/SystemClock.h"
+#include "utils/AMLUtils.h"
 #include "system.h"
 #include "SystemInfo.h"
 #ifndef TARGET_POSIX
@@ -57,9 +58,6 @@
 #include "utils/XMLUtils.h"
 #if defined(TARGET_ANDROID)
 #include "platform/android/jni/Build.h"
-#if defined(HAS_LIBAMCODEC)
-#include "utils/AMLUtils.h"
-#endif
 #endif
 
 /* Platform identification */
@@ -881,6 +879,20 @@ bool CSysInfo::HasHW3DInterlaced()
   return false;
 }
 
+bool CSysInfo::HWSupportsStereo(const int mode)
+{
+  if (aml_present())
+    return aml_supports_stereo(mode);
+  return false;
+}
+
+void CSysInfo::HWSetStereoMode(const int mode, const int view)
+{
+  if (aml_present())
+    aml_set_stereo_mode(mode, view);
+}
+
+
 CSysInfo::WindowsVersion CSysInfo::m_WinVer = WindowsVersionUnknown;
 
 bool CSysInfo::IsWindowsVersion(WindowsVersion ver)


--- x/xbmc/utils/SystemInfo.h	2017-03-20 17:17:49.000000000 +0100
+++ b/xbmc/utils/SystemInfo.h	2017-04-07 12:38:36.000000000 +0200
@@ -118,6 +118,10 @@ public:
   bool HasVideoToolBoxDecoder();
   bool IsAeroDisabled();
   bool HasHW3DInterlaced();
+  bool HWSupportsStereo(const int mode);
+  void HWSetStereoMode(const int mode, const int view);
+
+
   static bool IsWindowsVersion(WindowsVersion ver);
   static bool IsWindowsVersionAtLeast(WindowsVersion ver);
   static WindowsVersion GetWindowsVersion();
