diff --git a/projects/imx6/kodi/advancedsettings.xml b/projects/imx6/kodi/advancedsettings.xml index e19d88653c..e29381ee2f 100644 --- a/projects/imx6/kodi/advancedsettings.xml +++ b/projects/imx6/kodi/advancedsettings.xml @@ -1,16 +1,21 @@ false - - - 30 + + 20971520 + 4.0 + + + 1000 + 1 + diff --git a/projects/imx6/patches/RTL8812AU/RTL8812AU-010-compile-3.14.patch b/projects/imx6/patches/RTL8812AU/RTL8812AU-010-compile-3.14.patch new file mode 100644 index 0000000000..b955621d8c --- /dev/null +++ b/projects/imx6/patches/RTL8812AU/RTL8812AU-010-compile-3.14.patch @@ -0,0 +1,36 @@ +--- a/os_dep/linux/ioctl_cfg80211.c 2016-10-04 15:18:32.405995229 +0200 ++++ b/os_dep/linux/ioctl_cfg80211.c 2016-10-04 15:18:37.653865585 +0200 +@@ -649,20 +649,16 @@ void rtw_cfg80211_ibss_indicate_connect( + struct wlan_network *cur_network = &(pmlmepriv->cur_network); + struct wireless_dev *pwdev = padapter->rtw_wdev; + struct cfg80211_bss *bss = NULL; +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + struct wiphy *wiphy = pwdev->wiphy; + int freq = 2412; + struct ieee80211_channel *notify_channel; +-#endif + + DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + freq = rtw_ch2freq(cur_network->network.Configuration.DSConfig); + + if (0) + DBG_871X("chan: %d, freq: %d\n", cur_network->network.Configuration.DSConfig, freq); +-#endif + + if (pwdev->iftype != NL80211_IFTYPE_ADHOC) + { +@@ -713,12 +709,8 @@ void rtw_cfg80211_ibss_indicate_connect( + DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter)); + } + //notify cfg80211 that device joined an IBSS +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) + notify_channel = ieee80211_get_channel(wiphy, freq); + cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, notify_channel, GFP_ATOMIC); +-#else +- cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, GFP_ATOMIC); +-#endif + } + + void rtw_cfg80211_indicate_connect(_adapter *padapter) diff --git a/projects/imx6/patches/kodi/kodi-050-from-openbricks.patch b/projects/imx6/patches/kodi/kodi-050-from-openbricks.patch new file mode 100644 index 0000000000..812ab1cd6f --- /dev/null +++ b/projects/imx6/patches/kodi/kodi-050-from-openbricks.patch @@ -0,0 +1,3711 @@ +https://github.com/OpenBricks/openbricks/tree/krypton-glibc +https://github.com/OpenBricks/openbricks/tree/krypton-glibc/packages/multimedia/kodi/patches +https://github.com/OpenBricks/openbricks/tree/32da31689ba04a94d1a08bfc04f69d6c1a3c848a/packages/multimedia/kodi/patches + +============================================================== +file 0010-IMX-add-Supports-ERENDERFEATURE.patch +============================================================== + +From 5d60b324b6297b0f3355000cd65c10015c18798a Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Thu, 25 Aug 2016 21:52:39 +0200 +Subject: [PATCH] [IMX] add Supports(ERENDERFEATURE) + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 3 ++- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 ++ + .../VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp | 12 ++++++++++++ + .../VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h | 1 + + 4 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 4aae4c3..6b31ca5 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1709,6 +1709,7 @@ void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CIMXBuffer *source_p, CIMXBuffer + bool CIMXContext::TileTask(IPUTaskPtr &ipu) + { + int pad = ipu->task.input.height == 1080 && ipu->current->iHeight>ipu->task.input.height ? 16*ipu->current->iWidth : 0; ++ m_zoomAllowed = true; + + if (ipu->current->iFormat != _4CC('T', 'N', 'V', 'F') && ipu->current->iFormat != _4CC('T', 'N', 'V', 'P')) + { +@@ -1725,13 +1726,13 @@ bool CIMXContext::TileTask(IPUTaskPtr &ipu) + // Use band mode directly to FB, as no transformations needed (eg cropping) + if (m_fps >= 49 && m_fbWidth == 1920 && ipu->task.input.width == 1920 && !ipu->task.input.deinterlace.enable) + { ++ m_zoomAllowed = false; + ipu->task.output.crop.pos.x = ipu->task.input.crop.pos.x = 0; + ipu->task.output.crop.pos.y = ipu->task.input.crop.pos.y = 0; + ipu->task.output.crop.h = ipu->task.input.height = ipu->task.input.crop.h = ipu->current->iHeight; + ipu->task.output.paddr += m_fbLineLength * (m_fbHeight - ipu->task.input.crop.h)/2; + return true; + } +- + // rasterize from tile (frame) + struct ipu_task vdoa; + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index bde21ac..9b9f068 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -116,6 +116,7 @@ public: + void SetVideoPixelFormat(CProcessInfo *m_pProcessInfo); + + void SetBlitRects(const CRect &srcRect, const CRect &dstRect); ++ bool IsZoomAllowed() const { return m_zoomAllowed; } + + // Blits a buffer to a particular page (-1 for auto page) + // source_p (previous buffer) is required for de-interlacing +@@ -212,6 +213,7 @@ private: + CEvent m_waitFlip; + CProcessInfo *m_processInfo; + ++ bool m_zoomAllowed; + CCriticalSection m_pageSwapLock; + public: + void *m_g2dHandle; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +index 73fc323..01272ff 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +@@ -80,6 +80,18 @@ bool CRendererIMX::IsGuiLayer() + return false; + } + ++bool CRendererIMX::Supports(ERENDERFEATURE feature) ++{ ++ if (!g_IMXContext.IsZoomAllowed()) ++ return false; ++ ++ if (feature == RENDERFEATURE_PIXEL_RATIO || ++ feature == RENDERFEATURE_ZOOM) ++ return true; ++ ++ return false; ++} ++ + bool CRendererIMX::Supports(EINTERLACEMETHOD method) + { + if(method == VS_INTERLACEMETHOD_AUTO) +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +index 440badb..e2582a6 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +@@ -44,6 +44,7 @@ public: + // Feature support + virtual bool Supports(EINTERLACEMETHOD method); + virtual bool Supports(ESCALINGMETHOD method); ++ virtual bool Supports(ERENDERFEATURE feature); + + virtual bool WantsDoublePass() override; + +-- +1.9.1 + + +============================================================== +file 0011-IMX-update-to-fps-detect.patch +============================================================== + +From e2ac3ebc6bebd2dfdf4ad7d3bea5d5c629e85189 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Fri, 26 Aug 2016 00:56:03 +0200 +Subject: [PATCH] [IMX] update to fps detect + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 27 +++++--- + xbmc/linux/imx/IMX.cpp | 80 ++++++++++------------ + xbmc/linux/imx/IMX.h | 16 ++--- + 3 files changed, 62 insertions(+), 61 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 6b31ca5..bfb9a3f 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -744,21 +744,23 @@ int CIMXCodec::Decode(BYTE *pData, int iSize, double dts, double pts) + int ret = 0; + if (!g_IMXCodec->IsRunning()) + { +- if ((!m_decInput.full() || !ptrn.Recalc()) && m_decInput.size() < 40) ++ if (!m_decInput.full()) + { +- if (m_decInput.full()) +- m_decInput.setquotasize(m_decInput.getquotasize()+1); +- +- if (dts != DVD_NOPTS_VALUE) +- ptrn.Add(dts); +- else if (pts != DVD_NOPTS_VALUE) ++ if (pts != DVD_NOPTS_VALUE) + ptrn.Add(pts); ++ else if (dts != DVD_NOPTS_VALUE) ++ ptrn.Add(dts); + + ret |= VC_BUFFER; + } + else + { +- m_fps = DVD_TIME_BASE / ptrn.GetFrameDuration(); ++ double fd = ptrn.GetFrameDuration(true); ++ if (!fd && m_hints.fpsscale) ++ m_fps = (double)m_hints.fpsrate / m_hints.fpsscale; ++ else if (fd) ++ m_fps = DVD_TIME_BASE / fd; ++ + m_decOpenParam.nMapType = 1; + + ptrn.Flush(); +@@ -940,9 +942,12 @@ void CIMXCodec::Process() + m_decOpenParam.nMapType = 0; + Dispose(); + VpuOpen(); +- m_fps /= 2; + continue; + } ++ ++ if (m_initInfo.nInterlace && m_fps <= 30) ++ m_fps *= 2; ++ + m_processInfo->SetVideoFps(m_fps); + + CLog::Log(LOGDEBUG, "%s - VPU Init Stream Info : %dx%d (interlaced : %d - Minframe : %d)"\ +@@ -1277,7 +1282,7 @@ bool CIMXContext::AdaptScreen(bool allocate) + m_fbVar.xoffset = 0; + m_fbVar.yoffset = 0; + +- if (!allocate && (fbVar.bits_per_pixel == 16 || m_currentFieldFmt || (m_fbHeight >= 1080 && m_fps >= 49))) ++ if (!allocate && (fbVar.bits_per_pixel == 16 || m_fps >= 49)) + { + m_fbVar.nonstd = _4CC('Y', 'U', 'Y', 'V'); + m_fbVar.bits_per_pixel = 16; +@@ -1724,7 +1729,7 @@ bool CIMXContext::TileTask(IPUTaskPtr &ipu) + } + + // Use band mode directly to FB, as no transformations needed (eg cropping) +- if (m_fps >= 49 && m_fbWidth == 1920 && ipu->task.input.width == 1920 && !ipu->task.input.deinterlace.enable) ++ if (m_fps > 51 && m_fbWidth == 1920 && ipu->task.input.width == 1920 && !ipu->task.input.deinterlace.enable) + { + m_zoomAllowed = false; + ipu->task.output.crop.pos.x = ipu->task.input.crop.pos.x = 0; +diff --git a/xbmc/linux/imx/IMX.cpp b/xbmc/linux/imx/IMX.cpp +index e4284ac..ee4e60a 100644 +--- a/xbmc/linux/imx/IMX.cpp ++++ b/xbmc/linux/imx/IMX.cpp +@@ -36,14 +36,10 @@ + #include "windowing/WindowingFactory.h" + #include "utils/log.h" + #include "guilib/GraphicContext.h" +-#include "utils/MathUtils.h" +-#include "DVDClock.h" + #include "cores/VideoPlayer/DVDCodecs/DVDCodecUtils.h" +- +-#include ++#include "utils/StringUtils.h" + + #define DCIC_DEVICE "/dev/mxc_dcic0" +-#define FB_DEVICE "/dev/fb0" + + CIMX::CIMX(void) : CThread("CIMX") + , m_change(true) +@@ -162,7 +158,6 @@ void CIMX::OnResetDisplay() + m_change = true; + } + +- + bool CIMXFps::Recalc() + { + double prev = DVD_NOPTS_VALUE; +@@ -175,54 +170,57 @@ bool CIMXFps::Recalc() + m_hgraph.clear(); + for (auto d : m_ts) + { +- if (d != 0.0 && prev != DVD_NOPTS_VALUE) +- m_hgraph[MathUtils::round_int(d - prev)]++; ++ if (prev != DVD_NOPTS_VALUE) ++ { ++ frameDuration = CDVDCodecUtils::NormalizeFrameduration((d - prev), &hasMatch); ++ if (fabs(frameDuration - rint(frameDuration)) < 0.01) ++ frameDuration = rint(frameDuration); ++ ++ m_hgraph[(unsigned long)(frameDuration * 100)]++; ++ } + prev = d; + } + +- unsigned int patternLength = 0; + for (auto it = m_hgraph.begin(); it != m_hgraph.end();) + { +- if (it->second > 1) ++ if (it->second > 2) + { +- count += it->second; +- frameDuration += it->first * it->second; ++ double duration = CDVDCodecUtils::NormalizeFrameduration((double)it->first / 100, &hasMatch); ++ + ++it; + } + else ++ { ++ for (auto iti = m_hgraph.begin(); it != iti; iti++) ++ { ++ if (!iti->first) ++ continue; ++ int dv = it->first / iti->first; ++ if (dv * iti->first == it->first) ++ { ++ m_hgraph[it->first] += dv; ++ break; ++ } ++ } + m_hgraph.erase(it++); ++ } + } + +- if (count) +- frameDuration /= count; +- +- double frameNorm = CDVDCodecUtils::NormalizeFrameduration(frameDuration, &hasMatch); +- +- if (hasMatch && !patternLength) +- m_patternLength = 1; +- else +- m_patternLength = patternLength; +- +- if (!m_hasPattern && hasMatch) +- m_frameDuration = frameNorm; +- +- if ((m_ts.size() == DIFFRINGSIZE && !m_hasPattern && hasMatch)) +- m_hasPattern = true; +- +- if (m_hasPattern) +- m_ptscorrection = (m_ts.size() - 1) * m_frameDuration + m_ts.front() - m_ts.back(); +- +- if (m_hasPattern && m_ts.size() == DIFFRINGSIZE && m_ptscorrection > m_frameDuration / 4) ++ frameDuration = 0.0; ++ for (auto h : m_hgraph) + { +- m_hasPattern = false; +- m_frameDuration = DVD_NOPTS_VALUE; ++ count += h.second; ++ frameDuration += h.first * h.second; + } + +- return m_hgraph.size() <= 2; +- bool ret = m_hgraph.size() <= 2; +- if (!m_hasPattern && ret) +- m_frameDuration = frameNorm; +- return ret; ++ if (count) ++ frameDuration /= (100 * count); ++ ++ frameDuration = CDVDCodecUtils::NormalizeFrameduration(frameDuration, &hasMatch); ++ ++ if (hasMatch) ++ m_frameDuration = frameDuration; ++ return true; + } + + void CIMXFps::Add(double tm) +@@ -235,8 +233,6 @@ void CIMXFps::Add(double tm) + + void CIMXFps::Flush() + { ++ m_frameDuration = DVD_NOPTS_VALUE; + m_ts.clear(); +- m_frameDuration = 0.0; +- m_ptscorrection = 0.0; +- m_hasPattern = false; + } +diff --git a/xbmc/linux/imx/IMX.h b/xbmc/linux/imx/IMX.h +index 1c5f15e..c0a13cd 100644 +--- a/xbmc/linux/imx/IMX.h ++++ b/xbmc/linux/imx/IMX.h +@@ -24,6 +24,7 @@ + #include "threads/Thread.h" + #include "guilib/DispResource.h" + #include "utils/log.h" ++#include "cores/VideoPlayer/DVDClock.h" + + #include + #include +@@ -32,9 +33,12 @@ + #include + #include + #include ++#include + + #define DIFFRINGSIZE 60 + ++#define FB_DEVICE "/dev/fb0" ++ + class CIMX; + extern CIMX g_IMX; + +@@ -189,19 +193,15 @@ protected: + class CIMXFps + { + public: +- CIMXFps() { Flush(); } ++ CIMXFps() { Flush(); } + void Add(double pts); + void Flush(); //flush the saved pattern and the ringbuffer +- +- double GetFrameDuration() { return m_frameDuration; } +- bool HasFullBuffer() { return m_ts.size() == DIFFRINGSIZE; } +- ++ double GetFrameDuration(bool raw = false) { return m_frameDuration; } + bool Recalc(); + + private: ++ std::string GetPatternStr(); ++ std::map m_hgraph; + std::deque m_ts; +- std::map m_hgraph; + double m_frameDuration; +- bool m_hasPattern; +- double m_ptscorrection; + }; +-- +1.9.1 + + +============================================================== +file 0012-IMX-fix-compile-error.patch +============================================================== + +From 0d8aced44f2e2a84abca210ced4c9ea7585ddfab Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Fri, 26 Aug 2016 07:41:39 +0200 +Subject: [PATCH] [IMX] fix compile error + +--- + xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +index 62631f6..d8c0983 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +@@ -29,6 +29,7 @@ + #include + #ifdef HAS_IMXVPU + #include ++#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h" + #endif + #include "utils/log.h" + #include "utils/RegExp.h" +-- +1.9.1 + + +============================================================== +file 0013-IMX-put-destination-rect-parameter-into-Blit-call-re.patch +============================================================== + +From feebd022dfdab5b1ede13eaad48c387a8bbd04c8 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Fri, 26 Aug 2016 07:53:08 +0200 +Subject: [PATCH] [IMX] put destination rect parameter into Blit() call, + refactor IPUTask prep + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 32 +++++++++------------- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 17 +++--------- + .../VideoRenderers/HwDecRender/RendererIMX.cpp | 4 +-- + 3 files changed, 18 insertions(+), 35 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index bfb9a3f..09e07bb 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1240,8 +1240,6 @@ CIMXContext::CIMXContext() + m_pageCrops = new CRectInt[m_fbPages]; + CLog::Log(LOGDEBUG, "iMX : Allocated %d render buffers\n", m_fbPages); + +- SetBlitRects(CRectInt(), CRectInt()); +- + g2dOpenDevices(); + } + +@@ -1470,12 +1468,6 @@ bool CIMXContext::SetVSync(bool enable) + return true; + } + +-void CIMXContext::SetBlitRects(const CRect &srcRect, const CRect &dstRect) +-{ +- m_srcRect = srcRect; +- m_dstRect = dstRect; +-} +- + inline + void CIMXContext::SetFieldData(uint8_t fieldFmt, double fps) + { +@@ -1529,7 +1521,8 @@ int setIPUMotion(bool hasPrev, EINTERLACEMETHOD imethod) + return HIGH_MOTION; + } + +-void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, uint8_t fieldFmt, int page) ++void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, const CRect &srcRect, ++ const CRect &dstRect, uint8_t fieldFmt, int page) + { + if (page == RENDER_TASK_AUTOPAGE) + page = m_pg; +@@ -1542,12 +1535,20 @@ void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, uint8_t fieldFm + ipu->page = page; + + SetFieldData(fieldFmt, source->m_fps); +- PrepareTask(ipu, source_p, source); ++ PrepareTask(ipu, srcRect, dstRect); + + #ifdef IMX_PROFILE_BUFFERS + unsigned long long before = XbmcThreads::SystemClockMillis(); + #endif +- DoTask(ipu); ++ SetFieldData(fieldFmt, source->m_fps); ++ PrepareTask(ipu, srcRect, dstRect); ++ ++ if (!DoTask(ipu)) ++ return; ++ ++ m_flip = ipu->page | checkIPUStrideOffset(&ipu->task.input.deinterlace) << 4; ++ m_pingFlip.Set(); ++ + #ifdef IMX_PROFILE_BUFFERS + unsigned long long after = XbmcThreads::SystemClockMillis(); + CLog::Log(LOGDEBUG, "+P 0x%x@%d %d\n", ((CDVDVideoCodecIMXBuffer*)ipu->current)->GetIdx(), ipu->page, (int)(after-before)); +@@ -1640,15 +1641,8 @@ void CIMXContext::Clear(int page) + SetVideoPixelFormat(m_processInfo); + } + +-void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CIMXBuffer *source_p, CIMXBuffer *source) ++void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect) + { +- // Fill with zeros +- ipu->Zero(); +- ipu->Assign(source_p, source); +- +- CRect srcRect = m_srcRect; +- CRect dstRect = m_dstRect; +- + CRectInt iSrcRect, iDstRect; + + float srcWidth = srcRect.Width(); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 9b9f068..5a9d634 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -115,13 +115,12 @@ public: + bool IsDoubleRate() const { return m_currentFieldFmt & IPU_DEINTERLACE_RATE_EN; } + void SetVideoPixelFormat(CProcessInfo *m_pProcessInfo); + +- void SetBlitRects(const CRect &srcRect, const CRect &dstRect); + bool IsZoomAllowed() const { return m_zoomAllowed; } + + // Blits a buffer to a particular page (-1 for auto page) + // source_p (previous buffer) is required for de-interlacing + // modes LOW_MOTION and MED_MOTION. +- void Blit(CIMXBuffer *source_p, CIMXBuffer *source, ++ void Blit(CIMXBuffer *source_p, CIMXBuffer *source, const CRect &srcRect, const CRect &dstRect, + uint8_t fieldFmt = 0, int targetPage = RENDER_TASK_AUTOPAGE); + + // Shows a page vsynced +@@ -145,15 +144,9 @@ public: + private: + struct IPUTask + { +- void Assign(CIMXBuffer *buffer_p, CIMXBuffer *buffer) ++ IPUTask(CIMXBuffer *buffer_p, CIMXBuffer *buffer, int p = 0) ++ : previous(buffer_p), current(buffer), page(p) + { +- previous = buffer_p; +- current = buffer; +- } +- +- void Zero() +- { +- current = previous = NULL; + memset(&task, 0, sizeof(task)); + } + +@@ -172,7 +165,7 @@ private: + + bool GetFBInfo(const std::string &fbdev, struct fb_var_screeninfo *fbVar); + +- void PrepareTask(IPUTaskPtr &ipu, CIMXBuffer *source_p, CIMXBuffer *source); ++ void PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect); + bool DoTask(IPUTaskPtr &ipu, CRect *dest = nullptr); + bool TileTask(IPUTaskPtr &ipu); + +@@ -204,8 +197,6 @@ private: + int m_ipuHandle; + uint8_t m_currentFieldFmt; + bool m_vsync; +- CRect m_srcRect; +- CRect m_dstRect; + CRectInt *m_pageCrops; + bool m_bFbIsConfigured; + CEvent m_waitVSync; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +index 01272ff..64d88f8 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +@@ -199,8 +199,6 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + } + + //CLog::Log(LOGDEBUG, "BLIT RECTS: source x1 %f x2 %f y1 %f y2 %f dest x1 %f x2 %f y1 %f y2 %f", srcRect.x1, srcRect.x2, srcRect.y1, srcRect.y2, dstRect.x1, dstRect.x2, dstRect.y1, dstRect.y2); +- g_IMXContext.SetBlitRects(srcRect, dstRect); +- + uint8_t fieldFmt = flags & RENDER_FLAG_FIELDMASK; + + if (!g_graphicsContext.IsFullScreenVideo()) +@@ -220,7 +218,7 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + } + + CDVDVideoCodecIMXBuffer *buffer_p = m_bufHistory.front(); +- g_IMXContext.Blit(buffer_p == buffer ? nullptr : buffer_p, buffer, fieldFmt); ++ g_IMXContext.Blit(buffer_p == buffer ? nullptr : buffer_p, buffer, srcRect, dstRect, fieldFmt); + } + + #if 0 +-- +1.9.1 + + +============================================================== +file 0014-IMX-disable-profiling-logs-by-default.patch +============================================================== + +From 78508bc853fbdd3d2067cb4b1ecb02c757c504ca Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Fri, 26 Aug 2016 07:59:17 +0200 +Subject: [PATCH] [IMX] disable profiling logs by default + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 5a9d634..eadceb2 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -55,9 +55,8 @@ + // priorities to those subsystems can result in a very different user + // experience. With that setting enabled we can build some statistics, + // as numbers are always better than "feelings" +-#define IMX_PROFILE_BUFFERS +- +-#define IMX_PROFILE ++//#define IMX_PROFILE_BUFFERS ++//#define IMX_PROFILE + //#define TRACE_FRAMES + + #define RENDER_USE_G2D 0 +-- +1.9.1 + + +============================================================== +file 0015-IMXCodec-refactor-g2dOpenDevices-g2dCloseDevices.patch +============================================================== + +From d5c93e2ccd7dcfde674fc133b6720fa85a24b83c Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Tue, 30 Aug 2016 22:23:20 +0200 +Subject: [PATCH] [IMXCodec] refactor g2dOpenDevices/g2dCloseDevices + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 27 +++++++--------------- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 -- + 2 files changed, 8 insertions(+), 21 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 09e07bb..f371f9d 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1239,8 +1239,6 @@ CIMXContext::CIMXContext() + m_flip.resize(m_fbPages); + m_pageCrops = new CRectInt[m_fbPages]; + CLog::Log(LOGDEBUG, "iMX : Allocated %d render buffers\n", m_fbPages); +- +- g2dOpenDevices(); + } + + CIMXContext::~CIMXContext() +@@ -1248,7 +1246,6 @@ CIMXContext::~CIMXContext() + Stop(false); + Dispose(); + CloseDevices(); +- g2dCloseDevices(); + } + + bool CIMXContext::AdaptScreen(bool allocate) +@@ -1412,22 +1409,6 @@ bool CIMXContext::OpenDevices() + return m_fbHandle > 0; + } + +-void CIMXContext::g2dOpenDevices() +-{ +- // open g2d here to ensure all g2d fucntions are called from the same thread +- if (!g2d_open(&m_g2dHandle)) +- return; +- +- m_g2dHandle = NULL; +- CLog::Log(LOGERROR, "%s - Error while trying open G2D\n", __FUNCTION__); +-} +- +-void CIMXContext::g2dCloseDevices() +-{ +- if (m_g2dHandle && !g2d_close(m_g2dHandle)) +- m_g2dHandle = NULL; +-} +- + void CIMXContext::CloseDevices() + { + CLog::Log(LOGINFO, "iMX : Closing devices\n"); +@@ -1860,6 +1841,12 @@ bool CIMXContext::CaptureDisplay(unsigned char *&buffer, int iWidth, int iHeight + else if (blend) + std::memcpy(m_bufferCapture->buf_vaddr, buffer, m_bufferCapture->buf_size); + ++ if (g2d_open(&m_g2dHandle)) ++ { ++ CLog::Log(LOGERROR, "%s : Error while trying open G2D\n", __FUNCTION__); ++ return false; ++ } ++ + if (m_bufferCapture && buffer) + { + struct g2d_surface src, dst; +@@ -1912,6 +1899,8 @@ bool CIMXContext::CaptureDisplay(unsigned char *&buffer, int iWidth, int iHeight + if (m_bufferCapture && g2d_free(m_bufferCapture)) + CLog::Log(LOGERROR, "iMX : Error while freeing capture buuffer\n"); + ++ if (m_g2dHandle && !g2d_close(m_g2dHandle)) ++ m_g2dHandle = NULL; + return true; + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index eadceb2..066adb9 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -102,8 +102,6 @@ public: + bool AdaptScreen(bool allocate = false); + bool TaskRestart(); + void CloseDevices(); +- void g2dCloseDevices(); +- void g2dOpenDevices(); + bool OpenDevices(); + + bool Blank(); +-- +1.9.1 + + +============================================================== +file 0016-IMXRenderer-skip-rendering-same-frame.patch +============================================================== + +From b4086e7c8fb8dc2aec408cac53917a620cb23d6e Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Tue, 30 Aug 2016 22:25:34 +0200 +Subject: [PATCH] [IMXRenderer] skip rendering same frame + +--- + .../cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +index 64d88f8..4262970 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +@@ -150,6 +150,7 @@ bool CRendererIMX::RenderHook(int index) + + bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + { ++ static DWORD flagsPrev; + #if 0 + static unsigned long long previous = 0; + unsigned long long current = XbmcThreads::SystemClockMillis(); +@@ -164,6 +165,14 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + buffer->Lock(); + m_bufHistory.push_back(buffer); + } ++ else if (!m_bufHistory.empty() && m_bufHistory.back() == buffer && flagsPrev == flags) ++ { ++ g_IMX.WaitVsync(); ++ return true; ++ } ++ ++ flagsPrev = flags; ++ + if (m_bufHistory.size() > 2) + { + m_bufHistory.front()->Release(); +-- +1.9.1 + + +============================================================== +file 0017-IMXCodec-simplify-the-render-pipeline.patch +============================================================== + +From dbf5c69707b589308a168291030e25360398e783 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Thu, 1 Sep 2016 04:00:43 +0200 +Subject: [PATCH] [IMXCodec] simplify the render pipeline + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 22 +++++++++++++++------- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 12 +++++++----- + 2 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index f371f9d..c96b91b 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1228,6 +1228,7 @@ CIMXContext::CIMXContext() + , m_vsync(true) + , m_pageCrops(NULL) + , m_bFbIsConfigured(false) ++ , m_processThread(this, "iMX BLK") + , m_g2dHandle(NULL) + , m_bufferCapture(NULL) + , m_deviceName("/dev/fb1") +@@ -1235,8 +1236,6 @@ CIMXContext::CIMXContext() + m_waitVSync.Reset(); + m_onStartup.Reset(); + m_waitFlip.Reset(); +- m_flip.clear(); +- m_flip.resize(m_fbPages); + m_pageCrops = new CRectInt[m_fbPages]; + CLog::Log(LOGDEBUG, "iMX : Allocated %d render buffers\n", m_fbPages); + } +@@ -1312,10 +1311,11 @@ bool CIMXContext::AdaptScreen(bool allocate) + + MemMap(&fb_fix); + +- if (m_fbVar.bits_per_pixel == 16 || !RENDER_USE_G2D) +- m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); ++ m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); + + Unblank(); ++ if (!allocate) ++ m_processThread.Create(false); + + return true; + +@@ -1434,13 +1434,21 @@ bool CIMXContext::Blank() + return ioctl(m_fbHandle, FBIOBLANK, 1) == 0; + } + ++void CIMXContext::Run() ++{ ++ unsigned long curBlank = FB_BLANK_NORMAL; ++ while (curBlank && ++ !ioctl(open(FB_DEVICE, O_RDONLY, 0), MXCFB_GET_FB_BLANK, &curBlank)) ++ Sleep(10); ++ ++ m_bFbIsConfigured = !curBlank; ++} ++ + bool CIMXContext::Unblank() + { + if (!m_fbHandle) return false; + +- int ret = ioctl(m_fbHandle, FBIOBLANK, FB_BLANK_UNBLANK); +- m_bFbIsConfigured = true; +- return ret == 0; ++ return ioctl(m_fbHandle, FBIOBLANK, FB_BLANK_UNBLANK) == 0; + } + + bool CIMXContext::SetVSync(bool enable) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 066adb9..a550adc 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -93,7 +93,7 @@ enum RENDER_TASK + + // iMX context class that handles all iMX hardware + // related stuff +-class CIMXContext : private CThread, IDispResource ++class CIMXContext : private CThread, IDispResource, public IRunnable + { + public: + CIMXContext(); +@@ -175,14 +175,13 @@ private: + virtual void OnStartup(); + virtual void OnExit(); + virtual void Process(); ++ virtual void Run() override; + + private: +- lkFIFO m_input; +- std::vector m_flip; ++ unsigned char m_flip; + + int m_fbHandle; +- std::atomic m_fbCurrentPage; +- int m_pg; ++ int m_fbCurrentPage; + int m_fbWidth; + int m_fbHeight; + int m_fbLineLength; +@@ -203,6 +202,9 @@ private: + + bool m_zoomAllowed; + CCriticalSection m_pageSwapLock; ++ ++ CThread m_processThread; ++ + public: + void *m_g2dHandle; + struct g2d_buf *m_bufferCapture; +-- +1.9.1 + + +============================================================== +file 0018-IMXCodec-cleanups.patch +============================================================== + +From b766982e4b521454ba3566576dda08ee45409b39 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Thu, 1 Sep 2016 04:09:49 +0200 +Subject: [PATCH] [IMXCodec] cleanups + +--- + .../cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 14 +++++++------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 3 --- + 2 files changed, 7 insertions(+), 10 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index c96b91b..a33caa4 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -796,8 +796,8 @@ int CIMXCodec::Decode(BYTE *pData, int iSize, double dts, double pts) + __FUNCTION__, iSize, recalcPts(dts), recalcPts(pts), (uint)pData, ret, m_decInput.size(), m_decOutput.size()); + #endif + +- if (!ret || m_drainMode) +- Sleep(3); ++ if (!(ret & VC_PICTURE) || !ret || m_drainMode) ++ Sleep(10); + + return ret; + } +@@ -958,7 +958,9 @@ void CIMXCodec::Process() + + m_decInput.setquotasize(m_initInfo.nMinFrameBufferCount*7); + +- if (m_decOpenParam.CodecFormat != VPU_V_MPEG2 && !(m_decOpenParam.CodecFormat == VPU_V_AVC && m_converter)) ++ bool getFrame = m_decOpenParam.CodecFormat != VPU_V_AVC || !m_converter; ++ getFrame &= m_decOpenParam.CodecFormat != VPU_V_MPEG2; ++ if (getFrame || m_decRet & VPU_DEC_RESOLUTION_CHANGED) + { + SetDrainMode((VpuDecInputType)IN_DECODER_SET); + inData = dummy; +@@ -1237,7 +1239,6 @@ CIMXContext::CIMXContext() + m_onStartup.Reset(); + m_waitFlip.Reset(); + m_pageCrops = new CRectInt[m_fbPages]; +- CLog::Log(LOGDEBUG, "iMX : Allocated %d render buffers\n", m_fbPages); + } + + CIMXContext::~CIMXContext() +@@ -1310,6 +1311,7 @@ bool CIMXContext::AdaptScreen(bool allocate) + } + + MemMap(&fb_fix); ++ CLog::Log(LOGVIDEO, "iMX : Allocated %d render buffers\n", m_fbPages); + + m_ipuHandle = open("/dev/mxc_ipu", O_RDWR, 0); + +@@ -1356,8 +1358,6 @@ void CIMXContext::MemMap(struct fb_fix_screeninfo *fb_fix) + m_fbPageSize = m_fbLineLength * m_fbVar.yres_virtual / m_fbPages; + m_fbPhysAddr = fb_fix->smem_start; + m_fbVirtAddr = (uint8_t*)mmap(0, m_fbPhysSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fbHandle, 0); +- m_fbCurrentPage = 0; +- Clear(); + } + } + +@@ -1594,7 +1594,7 @@ void CIMXContext::SetVideoPixelFormat(CProcessInfo *m_pProcessInfo) + if (m_processInfo && m_fbVar.bits_per_pixel == 16) + m_processInfo->SetVideoPixelFormat("YUV 4:2:2"); + else if (m_processInfo) +- m_processInfo->SetVideoPixelFormat("RGB 32"); ++ m_processInfo->SetVideoPixelFormat("RGBA8888"); + } + + void CIMXContext::Clear(int page) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index a550adc..483b120 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -59,8 +59,6 @@ + //#define IMX_PROFILE + //#define TRACE_FRAMES + +-#define RENDER_USE_G2D 0 +- + // If uncommented a file "stream.dump" will be created in the current + // directory whenever a new stream is started. This is only for debugging + // and performance tests. This define must never be active in distributions. +@@ -210,7 +208,6 @@ public: + struct g2d_buf *m_bufferCapture; + + std::string m_deviceName; +- int m_speed; + + double m_fps; + }; +-- +1.9.1 + + +============================================================== +file 0019-IMXCodec-update-fix-stream-changes-of-same-parameter.patch +============================================================== + +From 64a685da10fcf9de9608d7690297dcf0d3dd1af7 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Thu, 1 Sep 2016 04:41:17 +0200 +Subject: [PATCH] [IMXCodec] update/fix stream changes of same parameters (eg + liveTV) + +--- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index a33caa4..181730d 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -431,7 +431,7 @@ CIMXCodec::CIMXCodec() + m_skipMode = VPU_DEC_SKIPNONE; + + m_decOutput.setquotasize(1); +- m_decInput.setquotasize(25); ++ m_decInput.setquotasize(60); + m_loaded.Reset(); + } + +@@ -498,7 +498,6 @@ bool CIMXCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::stri + { + StopThread(false); + ProcessSignals(SIGNAL_FLUSH); +- m_dropped = 0; + } + + m_hints = hints; +@@ -849,6 +848,9 @@ void CIMXCodec::Process() + m_pts.clear(); + m_loaded.Set(); + ++ m_dropped = 0; ++ m_lastPTS = DVD_NOPTS_VALUE; ++ + memset(&dummy, 0, sizeof(dummy)); + AddExtraData(&dummy, (m_decOpenParam.CodecFormat == VPU_V_AVC && m_hints.extrasize)); + inData = dummy; +@@ -956,7 +958,7 @@ void CIMXCodec::Process() + m_initInfo.nAddressAlignment, m_initInfo.PicCropRect.nLeft, m_initInfo.PicCropRect.nTop, + m_initInfo.PicCropRect.nRight, m_initInfo.PicCropRect.nBottom, m_initInfo.nQ16ShiftWidthDivHeightRatio, m_fps); + +- m_decInput.setquotasize(m_initInfo.nMinFrameBufferCount*7); ++ m_decInput.setquotasize(m_fps); + + bool getFrame = m_decOpenParam.CodecFormat != VPU_V_AVC || !m_converter; + getFrame &= m_decOpenParam.CodecFormat != VPU_V_MPEG2; +@@ -1110,13 +1112,7 @@ bool CIMXCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture) + previous = current; + #endif + +- if (m_dropRequest) +- { +- pDvdVideoPicture->iFlags = DVP_FLAG_DROPPED; +- ++m_dropped; +- } +- else +- pDvdVideoPicture->iFlags = pDvdVideoPicture->IMXBuffer->GetFlags(); ++ pDvdVideoPicture->iFlags = m_dropRequest ? DVP_FLAG_DROPPED : pDvdVideoPicture->IMXBuffer->GetFlags(); + + if (m_initInfo.nInterlace) + { +@@ -1149,7 +1145,7 @@ bool CIMXCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture) + + void CIMXCodec::SetDropState(bool bDrop) + { +- m_dropRequest = bDrop ? m_decOutput.size() > m_decOutput.getquotasize() / 3 && !m_burst : false; ++ m_dropRequest = bDrop; + } + + bool CIMXCodec::IsCurrentThread() const +-- +1.9.1 + + +============================================================== +file 0020-IMXCodec-change-backbuffer-showpage-handling.patch +============================================================== + +From 673999b3e038c920f885b32527766935789fbd31 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Sun, 4 Sep 2016 16:33:26 +0200 +Subject: [PATCH] [IMXCodec] change backbuffer/showpage handling + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 40 +++++++++++----------- + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 181730d..13d4072 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1354,6 +1354,7 @@ void CIMXContext::MemMap(struct fb_fix_screeninfo *fb_fix) + m_fbPageSize = m_fbLineLength * m_fbVar.yres_virtual / m_fbPages; + m_fbPhysAddr = fb_fix->smem_start; + m_fbVirtAddr = (uint8_t*)mmap(0, m_fbPhysSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fbHandle, 0); ++ Clear(); + } + } + +@@ -1433,6 +1434,8 @@ bool CIMXContext::Blank() + void CIMXContext::Run() + { + unsigned long curBlank = FB_BLANK_NORMAL; ++ ++ CSingleLock lk(m_pageSwapLock); + while (curBlank && + !ioctl(open(FB_DEVICE, O_RDONLY, 0), MXCFB_GET_FB_BLANK, &curBlank)) + Sleep(10); +@@ -1456,7 +1459,7 @@ bool CIMXContext::SetVSync(bool enable) + inline + void CIMXContext::SetFieldData(uint8_t fieldFmt, double fps) + { +- if (m_bStop || !IsRunning()) ++ if (m_bStop || !IsRunning() || !m_bFbIsConfigured) + return; + + bool dr = IsDoubleRate(); +@@ -1552,33 +1555,28 @@ void CIMXContext::WaitVSync() + + bool CIMXContext::ShowPage() + { ++ { ++ CSingleLock lk(m_pageSwapLock); ++ if (!m_fbHandle || !m_bFbIsConfigured) ++ return false; ++ } ++ + m_waitFlip.Wait(); +- int page = m_fbCurrentPage.load(); + +- CSingleLock lk(m_pageSwapLock); +- if (!m_fbHandle || !m_bFbIsConfigured) return false; +- // Protect page swapping from screen capturing that does read the current +- // front buffer. This is actually not done very frequently so the lock +- // does not hurt. +- bool ret = true; ++ bool off = m_flip >> 4; ++ m_fbCurrentPage = m_flip & 0xf; + + m_fbVar.activate = FB_ACTIVATE_VBL; +- m_fbVar.yoffset = (m_fbVar.yres + 1) * page + !m_flip[page]; ++ m_fbVar.yoffset = (m_fbVar.yres + 1) * m_fbCurrentPage + !off; + if (ioctl(m_fbHandle, FBIOPAN_DISPLAY, &m_fbVar) < 0) + { + CLog::Log(LOGWARNING, "Panning failed: %s\n", strerror(errno)); +- ret = false; ++ return false; + } + + m_waitVSync.Set(); + +- // Wait for flip +- if (ret && m_vsync && ioctl(m_fbHandle, FBIO_WAITFORVSYNC, 0) < 0) +- { +- CLog::Log(LOGWARNING, "Vsync failed: %s\n", strerror(errno)); +- ret = false; +- } +- return ret; ++ return true; + } + + void CIMXContext::SetVideoPixelFormat(CProcessInfo *m_pProcessInfo) +@@ -1851,6 +1849,7 @@ bool CIMXContext::CaptureDisplay(unsigned char *&buffer, int iWidth, int iHeight + return false; + } + ++ CSingleLock lk(m_pageSwapLock); + if (m_bufferCapture && buffer) + { + struct g2d_surface src, dst; +@@ -1858,7 +1857,7 @@ bool CIMXContext::CaptureDisplay(unsigned char *&buffer, int iWidth, int iHeight + memset(&dst, 0, sizeof(dst)); + + { +- src.planes[0] = m_fbPhysAddr + m_fbCurrentPage.load() * m_fbPageSize; ++ src.planes[0] = m_fbPhysAddr + m_fbCurrentPage * m_fbPageSize; + dst.planes[0] = m_bufferCapture->buf_paddr; + if (m_fbVar.bits_per_pixel == 16) + { +@@ -1896,9 +1895,7 @@ bool CIMXContext::CaptureDisplay(unsigned char *&buffer, int iWidth, int iHeight + std::memcpy(buffer, m_bufferCapture->buf_vaddr, m_bufferCapture->buf_size); + } + else +- { + CLog::Log(LOGERROR, "iMX : Error allocating capture buffer\n"); +- } + + if (m_bufferCapture && g2d_free(m_bufferCapture)) + CLog::Log(LOGERROR, "iMX : Error while freeing capture buuffer\n"); +@@ -1943,5 +1940,8 @@ void CIMXContext::Stop(bool bWait /*= true*/) + void CIMXContext::Process() + { + while (!m_bStop) ++ { + ShowPage(); ++ std::this_thread::yield(); ++ } + } +-- +1.9.1 + + +============================================================== +file 0021-IMXCodec-use-only-1-extra-buffer.patch +============================================================== + +From 0b2ff9727391d0aad97c4f746722dd78c35d1beb Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Sun, 4 Sep 2016 21:53:10 +0200 +Subject: [PATCH] [IMXCodec] use only 1 extra buffer + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 13d4072..e66b110 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -71,7 +71,7 @@ std::list m_recycleBuffers; + const int CIMXContext::m_fbPages = 3; + + // Experiments show that we need at least one more (+1) VPU buffer than the min value returned by the VPU +-const unsigned int CIMXCodec::m_extraVpuBuffers = 2 + CIMXContext::m_fbPages + RENDER_QUEUE_SIZE; ++const unsigned int CIMXCodec::m_extraVpuBuffers = 1 + CIMXContext::m_fbPages + RENDER_QUEUE_SIZE; + + CDVDVideoCodecIMX::~CDVDVideoCodecIMX() + { +-- +1.9.1 + + +============================================================== +file 0022-IMXCodec-delay-VPU-memory-reinit.patch +============================================================== + +From 761856c6efc70f5e459195b1b5c6685f7b77a58c Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Sun, 4 Sep 2016 23:22:50 +0200 +Subject: [PATCH] [IMXCodec] delay VPU memory reinit + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 13 +++++++++---- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 1 + + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index e66b110..0c5bf68 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -422,6 +422,8 @@ CIMXCodec::CIMXCodec() + , m_fps(-1) + , m_burst(0) + { ++ m_nrOut.store(0); ++ + m_vpuHandle = 0; + m_converter = NULL; + #ifdef DUMP_STREAM +@@ -813,6 +815,7 @@ void CIMXCodec::RecycleFrameBuffers() + m_pts[m_recycleBuffers.front()] = DVD_NOPTS_VALUE; + VPU_DecOutFrameDisplayed(m_vpuHandle, m_recycleBuffers.front()); + m_recycleBuffers.pop_front(); ++ --m_nrOut; + } + } + +@@ -925,12 +928,13 @@ void CIMXCodec::Process() + if (m_decRet & VPU_DEC_INIT_OK || m_decRet & VPU_DEC_RESOLUTION_CHANGED) + // VPU decoding init OK : We can retrieve stream info + { +- m_decOutput.setquotasize(1); +- if (m_decRet & VPU_DEC_RESOLUTION_CHANGED && m_decOutput.size()) ++ if (m_decRet & VPU_DEC_RESOLUTION_CHANGED) + { +- unsigned int returning = m_decOutput.size() + RENDER_QUEUE_SIZE; +- while (m_recycleBuffers.size() < returning && !m_bStop) ++ while (m_nrOut > 3 && !m_bStop) ++ { ++ RecycleFrameBuffers(); + std::this_thread::yield(); ++ } + } + + if (VPU_DecGetInitialInfo(m_vpuHandle, &m_initInfo) != VPU_DEC_RET_SUCCESS) +@@ -980,6 +984,7 @@ void CIMXCodec::Process() + m_frameInfo.pExtInfo->nFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); + m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); + ++ ++m_nrOut; + CDVDVideoCodecIMXBuffer *buffer = new CDVDVideoCodecIMXBuffer(&m_frameInfo, m_fps, m_decOpenParam.nMapType); + + /* quick & dirty fix to get proper timestamping for VP8 codec */ +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 483b120..d40482b 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -417,6 +417,7 @@ private: + bool IsCurrentThread() const; + + CCriticalSection m_openLock; ++ std::atomic m_nrOut; + }; + + +-- +1.9.1 + + +============================================================== +file 0023-IMXCodec-simplify-Blit.patch +============================================================== + +From 1b9e693c75206d14d8a71d3fadcb2f19583af5ee Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Sun, 4 Sep 2016 23:23:35 +0200 +Subject: [PATCH] [IMXCodec] simplify Blit() + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 22 +++++++--------------- + 1 file changed, 7 insertions(+), 15 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 0c5bf68..a4cde09 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1517,18 +1517,15 @@ int setIPUMotion(bool hasPrev, EINTERLACEMETHOD imethod) + void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, const CRect &srcRect, + const CRect &dstRect, uint8_t fieldFmt, int page) + { ++ static unsigned char pg; ++ + if (page == RENDER_TASK_AUTOPAGE) +- page = m_pg; ++ page = pg; + else if (page < 0 && page >= m_fbPages) + return; + +- m_pg = ++m_pg % m_fbPages; +- +- IPUTaskPtr ipu(new IPUTask); +- ipu->page = page; +- +- SetFieldData(fieldFmt, source->m_fps); +- PrepareTask(ipu, srcRect, dstRect); ++ IPUTaskPtr ipu(new IPUTask(source_p, source, page)); ++ pg = ++pg % m_fbPages; + + #ifdef IMX_PROFILE_BUFFERS + unsigned long long before = XbmcThreads::SystemClockMillis(); +@@ -1540,22 +1537,17 @@ void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, const CRect &sr + return; + + m_flip = ipu->page | checkIPUStrideOffset(&ipu->task.input.deinterlace) << 4; +- m_pingFlip.Set(); ++ m_waitFlip.Set(); + + #ifdef IMX_PROFILE_BUFFERS + unsigned long long after = XbmcThreads::SystemClockMillis(); + CLog::Log(LOGDEBUG, "+P 0x%x@%d %d\n", ((CDVDVideoCodecIMXBuffer*)ipu->current)->GetIdx(), ipu->page, (int)(after-before)); + #endif +- +- m_fbCurrentPage.store(ipu->page); +- m_waitFlip.Set(); +- +- m_flip[ipu->page] = checkIPUStrideOffset(&ipu->task.input.deinterlace); + } + + void CIMXContext::WaitVSync() + { +- m_waitVSync.WaitMSec(1000 / g_graphicsContext.GetFPS()); ++ m_waitVSync.WaitMSec(1300 / g_graphicsContext.GetFPS()); + } + + bool CIMXContext::ShowPage() +-- +1.9.1 + + +============================================================== +file 0024-IMXCodec-align-code-with-EINTERLACEMETHOD-refactorin.patch +============================================================== + +From 2b55e487fe160692a190c86e90a8e927a5228c04 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Mon, 5 Sep 2016 00:44:58 +0200 +Subject: [PATCH] [IMXCodec] align code with EINTERLACEMETHOD refactoring + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 52 ++++++++++++++++------ + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 5 ++- + .../VideoRenderers/HwDecRender/RendererIMX.cpp | 19 -------- + .../VideoRenderers/HwDecRender/RendererIMX.h | 2 - + 4 files changed, 42 insertions(+), 36 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index a4cde09..02e829b 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -33,6 +33,8 @@ + #include "linux/imx/IMX.h" + #include "libavcodec/avcodec.h" + ++#include "guilib/LocalizeStrings.h" ++ + #include + #include + #include +@@ -439,7 +441,7 @@ CIMXCodec::CIMXCodec() + + CIMXCodec::~CIMXCodec() + { +- g_IMXContext.SetVideoPixelFormat(nullptr); ++ g_IMXContext.SetProcessInfo(nullptr); + StopThread(false); + ProcessSignals(SIGNAL_SIGNAL); + SetDrainMode(VPU_DEC_IN_DRAIN); +@@ -623,11 +625,18 @@ bool CIMXCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::stri + return false; + } + ++ std::list deintMethods({ EINTERLACEMETHOD::VS_INTERLACEMETHOD_AUTO, ++ EINTERLACEMETHOD::VS_INTERLACEMETHOD_RENDER_BOB }); ++ ++ for(int i = EINTERLACEMETHOD::VS_INTERLACEMETHOD_IMX_FASTMOTION; i <= EINTERLACEMETHOD::VS_INTERLACEMETHOD_IMX_ADVMOTION_HALF; ++i) ++ deintMethods.push_back(static_cast(i)); ++ + m_processInfo = m_pProcessInfo; + m_processInfo->SetVideoDecoderName(m_pFormatName, true); + m_processInfo->SetVideoDimensions(m_hints.width, m_hints.height); +- m_processInfo->SetVideoDeintMethod("hardware"); +- g_IMXContext.SetVideoPixelFormat(m_processInfo); ++ m_processInfo->SetVideoDeintMethod("none"); ++ m_processInfo->UpdateDeinterlacingMethods(deintMethods); ++ g_IMXContext.SetProcessInfo(m_processInfo); + + return true; + } +@@ -1480,6 +1489,10 @@ void CIMXContext::SetFieldData(uint8_t fieldFmt, double fps) + return; + + m_fps = fps; ++ ++ std::string strMotion; ++ m_motion = SetIPUMotion(strMotion); ++ m_processInfo->SetVideoDeintMethod(strMotion); + CLog::Log(LOGDEBUG, "iMX : Output parameters changed - deinterlace %s%s, fps: %.3f\n", !!fieldFmt ? "active" : "not active", IsDoubleRate() ? " DR" : "", m_fps); + + CSingleLock lk(m_pageSwapLock); +@@ -1503,15 +1516,28 @@ bool checkIPUStrideOffset(struct ipu_deinterlace *d) + } + } + +-inline +-int setIPUMotion(bool hasPrev, EINTERLACEMETHOD imethod) ++ipu_motion_sel CIMXContext::SetIPUMotion(std::string &strImethod) + { +- if (hasPrev && imethod == VS_INTERLACEMETHOD_IMX_ADVMOTION) ++ EINTERLACEMETHOD imethod = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod; ++ switch (imethod) ++ { ++ case VS_INTERLACEMETHOD_IMX_ADVMOTION: ++ strImethod = g_localizeStrings.Get(16336); + return MED_MOTION; +- else if (hasPrev && (imethod == VS_INTERLACEMETHOD_IMX_ADVMOTION_HALF || imethod == VS_INTERLACEMETHOD_AUTO)) ++ ++ case VS_INTERLACEMETHOD_IMX_ADVMOTION_HALF: ++ case VS_INTERLACEMETHOD_AUTO: ++ strImethod = g_localizeStrings.Get(16335); + return MED_MOTION; + +- return HIGH_MOTION; ++ case VS_INTERLACEMETHOD_IMX_FASTMOTION: ++ strImethod = g_localizeStrings.Get(16334); ++ return HIGH_MOTION; ++ ++ default: ++ strImethod = g_localizeStrings.Get(16021); ++ return HIGH_MOTION; ++ } + } + + void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, const CRect &srcRect, +@@ -1576,15 +1602,15 @@ bool CIMXContext::ShowPage() + return true; + } + +-void CIMXContext::SetVideoPixelFormat(CProcessInfo *m_pProcessInfo) ++void CIMXContext::SetProcessInfo(CProcessInfo *m_pProcessInfo) + { + m_processInfo = m_pProcessInfo; + if (!m_processInfo) + return; + +- if (m_processInfo && m_fbVar.bits_per_pixel == 16) ++ if (m_fbVar.bits_per_pixel == 16) + m_processInfo->SetVideoPixelFormat("YUV 4:2:2"); +- else if (m_processInfo) ++ else + m_processInfo->SetVideoPixelFormat("RGBA8888"); + } + +@@ -1618,7 +1644,7 @@ void CIMXContext::Clear(int page) + else + CLog::Log(LOGERROR, "iMX Clear fb error : Unexpected format"); + +- SetVideoPixelFormat(m_processInfo); ++ SetProcessInfo(m_processInfo); + } + + void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect) +@@ -1680,7 +1706,7 @@ void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect) + if (m_currentFieldFmt) + { + ipu->task.input.deinterlace.enable = 1; +- ipu->task.input.deinterlace.motion = setIPUMotion(ipu->previous, CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod); ++ ipu->task.input.deinterlace.motion = m_motion; + ipu->task.input.deinterlace.field_fmt = m_currentFieldFmt; + } + } +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index d40482b..6a4f638 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -108,10 +108,10 @@ public: + + // Blitter configuration + bool IsDoubleRate() const { return m_currentFieldFmt & IPU_DEINTERLACE_RATE_EN; } +- void SetVideoPixelFormat(CProcessInfo *m_pProcessInfo); +- ++ void SetProcessInfo(CProcessInfo *m_pProcessInfo); + bool IsZoomAllowed() const { return m_zoomAllowed; } + ++ ipu_motion_sel SetIPUMotion(std::string &strImethod); + // Blits a buffer to a particular page (-1 for auto page) + // source_p (previous buffer) is required for de-interlacing + // modes LOW_MOTION and MED_MOTION. +@@ -197,6 +197,7 @@ private: + CEvent m_onStartup; + CEvent m_waitFlip; + CProcessInfo *m_processInfo; ++ ipu_motion_sel m_motion; + + bool m_zoomAllowed; + CCriticalSection m_pageSwapLock; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +index 4262970..aeef073 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +@@ -92,30 +92,11 @@ bool CRendererIMX::Supports(ERENDERFEATURE feature) + return false; + } + +-bool CRendererIMX::Supports(EINTERLACEMETHOD method) +-{ +- if(method == VS_INTERLACEMETHOD_AUTO) +- return true; +- +- if(method == VS_INTERLACEMETHOD_IMX_ADVMOTION +- || method == VS_INTERLACEMETHOD_IMX_ADVMOTION_HALF +- || method == VS_INTERLACEMETHOD_IMX_FASTMOTION +- || method == VS_INTERLACEMETHOD_RENDER_BOB) +- return true; +- else +- return false; +-} +- + bool CRendererIMX::Supports(ESCALINGMETHOD method) + { + return method == VS_SCALINGMETHOD_AUTO; + } + +-EINTERLACEMETHOD CRendererIMX::AutoInterlaceMethod() +-{ +- return VS_INTERLACEMETHOD_IMX_ADVMOTION_HALF; +-} +- + bool CRendererIMX::WantsDoublePass() + { + if (CMediaSettings::GetInstance().GetCurrentVideoSettings().m_InterlaceMethod == +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +index e2582a6..fc71e89 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +@@ -42,13 +42,11 @@ public: + virtual bool IsGuiLayer(); + + // Feature support +- virtual bool Supports(EINTERLACEMETHOD method); + virtual bool Supports(ESCALINGMETHOD method); + virtual bool Supports(ERENDERFEATURE feature); + + virtual bool WantsDoublePass() override; + +- virtual EINTERLACEMETHOD AutoInterlaceMethod(); + virtual CRenderInfo GetRenderInfo(); + + protected: +-- +1.9.1 + + +============================================================== +file 0025-IMXCodec-refactor-IsBlank-as-utility-CIMX-static-fun.patch +============================================================== + +From dfe6f8f3a6f494d204d89ead77390a72257094cb Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Mon, 5 Sep 2016 04:57:23 +0200 +Subject: [PATCH] [IMXCodec] refactor IsBlank() as utility(CIMX) static func + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 7 ++----- + xbmc/linux/imx/IMX.cpp | 9 +++++++++ + xbmc/linux/imx/IMX.h | 2 ++ + 3 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 02e829b..5d05b64 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1447,14 +1447,11 @@ bool CIMXContext::Blank() + + void CIMXContext::Run() + { +- unsigned long curBlank = FB_BLANK_NORMAL; +- + CSingleLock lk(m_pageSwapLock); +- while (curBlank && +- !ioctl(open(FB_DEVICE, O_RDONLY, 0), MXCFB_GET_FB_BLANK, &curBlank)) ++ while (CIMX::IsBlank()) + Sleep(10); + +- m_bFbIsConfigured = !curBlank; ++ m_bFbIsConfigured = true; + } + + bool CIMXContext::Unblank() +diff --git a/xbmc/linux/imx/IMX.cpp b/xbmc/linux/imx/IMX.cpp +index ee4e60a..4087406 100644 +--- a/xbmc/linux/imx/IMX.cpp ++++ b/xbmc/linux/imx/IMX.cpp +@@ -158,6 +158,15 @@ void CIMX::OnResetDisplay() + m_change = true; + } + ++bool CIMX::IsBlank() ++{ ++ unsigned long curBlank; ++ int fd = open(FB_DEVICE, O_RDONLY | O_NONBLOCK); ++ bool ret = ioctl(fd, MXCFB_GET_FB_BLANK, &curBlank) || curBlank != FB_BLANK_UNBLANK; ++ close(fd); ++ return ret; ++} ++ + bool CIMXFps::Recalc() + { + double prev = DVD_NOPTS_VALUE; +diff --git a/xbmc/linux/imx/IMX.h b/xbmc/linux/imx/IMX.h +index c0a13cd..8d13333 100644 +--- a/xbmc/linux/imx/IMX.h ++++ b/xbmc/linux/imx/IMX.h +@@ -54,6 +54,8 @@ public: + int WaitVsync(); + virtual void OnResetDisplay(); + ++ static bool IsBlank(); ++ + private: + virtual void Process(); + bool UpdateDCIC(); +-- +1.9.1 + + +============================================================== +file 0026-IMXCodec-check-for-req-ipu-previous-at-single-point-.patch +============================================================== + +From 7ec6c3658f2c4f68a51235933126af02c653110b Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Mon, 5 Sep 2016 05:00:21 +0200 +Subject: [PATCH] [IMXCodec] check for req ipu(previous) at single point (of + interlacing setup) + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 5d05b64..a083de5 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1700,7 +1700,7 @@ void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect) + ipu->task.output.crop.h = iDstRect.Height(); + + // Setup deinterlacing if enabled +- if (m_currentFieldFmt) ++ if (m_currentFieldFmt && ipu->previous) + { + ipu->task.input.deinterlace.enable = 1; + ipu->task.input.deinterlace.motion = m_motion; +@@ -1715,7 +1715,7 @@ bool CIMXContext::TileTask(IPUTaskPtr &ipu) + + if (ipu->current->iFormat != _4CC('T', 'N', 'V', 'F') && ipu->current->iFormat != _4CC('T', 'N', 'V', 'P')) + { +- if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION && ipu->previous) ++ if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION) + { + ipu->task.input.paddr_n = ipu->task.input.paddr; + ipu->task.input.paddr = ipu->previous->pPhysAddr + pad; +@@ -1726,7 +1726,7 @@ bool CIMXContext::TileTask(IPUTaskPtr &ipu) + } + + // Use band mode directly to FB, as no transformations needed (eg cropping) +- if (m_fps > 51 && m_fbWidth == 1920 && ipu->task.input.width == 1920 && !ipu->task.input.deinterlace.enable) ++ if (m_fps >= 49 && m_fbWidth == 1920 && ipu->task.input.width == 1920 && !ipu->task.input.deinterlace.enable) + { + m_zoomAllowed = false; + ipu->task.output.crop.pos.x = ipu->task.input.crop.pos.x = 0; +@@ -1773,7 +1773,7 @@ bool CIMXContext::TileTask(IPUTaskPtr &ipu) + + ipu->task.input.paddr = vdoa.output.paddr + pad; + ipu->task.input.format = vdoa.output.format; +- if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION && ipu->previous) ++ if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION) + { + ipu->task.input.paddr_n = ipu->task.input.paddr; + ipu->task.input.paddr = ipu->previous->pPhysAddr + pad; +-- +1.9.1 + + +============================================================== +file 0027-stop-resume-streams-on-OnLostDisplay-OnResetDisplay.patch +============================================================== + +From ef590549752c0b7daccb12c28d34feb5e7ed2171 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Mon, 18 Jul 2016 23:34:51 +0200 +Subject: [PATCH] stop/resume streams on OnLostDisplay/OnResetDisplay + +--- + xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +index 4f55b37..4aad146 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +@@ -2843,6 +2843,11 @@ AEAudioFormat CActiveAE::GetCurrentSinkFormat() + void CActiveAE::OnLostDisplay() + { + Message *reply; ++ for(auto &&stream : m_streams) ++ m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::PAUSESTREAM, ++ &reply, 1000, ++ &stream, sizeof(CActiveAEStream*)); ++ + if (m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::DISPLAYLOST, + &reply, + 5000)) +@@ -2862,7 +2867,12 @@ void CActiveAE::OnLostDisplay() + + void CActiveAE::OnResetDisplay() + { +- m_controlPort.SendOutMessage(CActiveAEControlProtocol::DISPLAYRESET); ++ Message *reply; ++ m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::DISPLAYRESET, &reply, 1000); ++ for(auto &&stream : m_streams) ++ m_controlPort.SendOutMessageSync(CActiveAEControlProtocol::RESUMESTREAM, ++ &reply, 1000, ++ &stream, sizeof(CActiveAEStream*)); + } + + void CActiveAE::OnAppFocusChange(bool focus) +-- +1.9.1 + + +============================================================== +file 0028-stuck-on-Quit-fix.patch +============================================================== + +From 9229bf8355eb0ad5bea9c96988dd3c6f6e2451cc Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Mon, 5 Sep 2016 02:24:25 +0200 +Subject: [PATCH] stuck on Quit fix + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index a083de5..2fff95d 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1952,6 +1952,7 @@ void CIMXContext::Stop(bool bWait /*= true*/) + return; + + CThread::StopThread(false); ++ m_waitFlip.Set(); + Blank(); + if (bWait && IsRunning()) + CThread::StopThread(true); +-- +1.9.1 + + +============================================================== +file 0029-Remove-asynchronous-stop-pause-as-its-timing-is-comp.patch +============================================================== + +From 5bdb78a5fb6b01d0c41a4ecf62aa237350e2a460 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Mon, 5 Sep 2016 02:27:06 +0200 +Subject: [PATCH] Remove asynchronous stop/pause as its timing is completely + not where needed + +--- + xbmc/cores/VideoPlayer/VideoPlayer.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp +index 39b67da..7ba01a7 100644 +--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp ++++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp +@@ -5158,17 +5158,21 @@ void CVideoPlayer::UpdateClockSync(bool enabled) + void CVideoPlayer::OnLostDisplay() + { + CLog::Log(LOGNOTICE, "VideoPlayer: OnLostDisplay received"); ++ m_clock.Pause(true); ++#ifndef HAS_IMXVPU + m_VideoPlayerAudio->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, true), 1); + m_VideoPlayerVideo->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, true), 1); +- m_clock.Pause(true); ++#endif + m_displayLost = true; + } + + void CVideoPlayer::OnResetDisplay() + { + CLog::Log(LOGNOTICE, "VideoPlayer: OnResetDisplay received"); ++ m_clock.Pause(false); ++#ifndef HAS_IMXVPU + m_VideoPlayerAudio->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, false), 1); + m_VideoPlayerVideo->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, false), 1); +- m_clock.Pause(false); ++#endif + m_displayLost = false; + } +-- +1.9.1 + + +============================================================== +file 0030-prevent-audio-init-during-egl-init-when-being-blanke.patch +============================================================== + +From 021323daae52363a8c62bbded00c45ebff373208 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Mon, 5 Sep 2016 03:05:21 +0200 +Subject: [PATCH] prevent audio init during egl init (when being blanked) + +--- + xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 3 +++ + xbmc/windowing/egl/WinSystemEGL.cpp | 33 ++++++++++++++++++--------------- + xbmc/windowing/egl/WinSystemEGL.h | 4 ++++ + 3 files changed, 25 insertions(+), 15 deletions(-) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +index d8c0983..4098f63 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +@@ -97,6 +97,7 @@ void CEGLNativeTypeIMX::Initialize() + } + } + ++ g_Windowing.old(); + ShowWindow(false); + + fd = open("/dev/fb0",O_RDWR); +@@ -132,6 +133,8 @@ void CEGLNativeTypeIMX::Initialize() + m_sar = GetMonitorSAR(); + g_IMXContext.create(); + ShowWindow(true); ++ ++ g_Windowing.ord(); + #endif + return; + } +diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp +index 852f337..e76737b 100644 +--- a/xbmc/windowing/egl/WinSystemEGL.cpp ++++ b/xbmc/windowing/egl/WinSystemEGL.cpp +@@ -264,6 +264,21 @@ bool CWinSystemEGL::DestroyWindowSystem() + return true; + } + ++void CWinSystemEGL::old() ++{ ++ CSingleLock lock(m_resourceSection); ++ for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) ++ (*i)->OnLostDisplay(); ++} ++ ++void CWinSystemEGL::ord() ++{ ++ CSingleLock lock(m_resourceSection); ++ // tell any shared resources ++ for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) ++ (*i)->OnResetDisplay(); ++} ++ + bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) + { + RESOLUTION_INFO current_resolution; +@@ -294,11 +309,7 @@ bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RE + m_dispResetTimer.Set(delay * 100); + } + +- { +- CSingleLock lock(m_resourceSection); +- for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) +- (*i)->OnLostDisplay(); +- } ++ old(); + + m_stereo_mode = stereo_mode; + m_bFullScreen = fullScreen; +@@ -315,12 +326,7 @@ bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RE + } + + if (!m_delayDispReset) +- { +- CSingleLock lock(m_resourceSection); +- // tell any shared resources +- for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) +- (*i)->OnResetDisplay(); +- } ++ ord(); + + Show(); + return true; +@@ -457,10 +463,7 @@ void CWinSystemEGL::PresentRenderImpl(bool rendered) + if (m_delayDispReset && m_dispResetTimer.IsTimePast()) + { + m_delayDispReset = false; +- CSingleLock lock(m_resourceSection); +- // tell any shared resources +- for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) +- (*i)->OnResetDisplay(); ++ ord(); + } + if (!rendered) + return; +diff --git a/xbmc/windowing/egl/WinSystemEGL.h b/xbmc/windowing/egl/WinSystemEGL.h +index c24bb35..910b156 100644 +--- a/xbmc/windowing/egl/WinSystemEGL.h ++++ b/xbmc/windowing/egl/WinSystemEGL.h +@@ -69,6 +69,10 @@ public: + + EGLDisplay GetEGLDisplay(); + EGLContext GetEGLContext(); ++ ++ void old(); ++ void ord(); ++ + protected: + virtual void PresentRenderImpl(bool rendered); + virtual void SetVSyncImpl(bool enable); +-- +1.9.1 + + +============================================================== +file 0031-IMXEGL-call-UNBLANK-FB-before-WinSystem-calls-OnRese.patch +============================================================== + +From 7c7d9bf2cd57e4abdd923ead898c210590dfbcb9 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Fri, 9 Sep 2016 19:04:09 +0200 +Subject: [PATCH] [IMXEGL] call UNBLANK FB before WinSystem calls + OnResetDisplay + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 3 ++- + xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 2 ++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 2fff95d..f692482 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1381,7 +1381,8 @@ void CIMXContext::OnLostDisplay() + void CIMXContext::OnResetDisplay() + { + CSingleLock lk(m_pageSwapLock); +- m_bFbIsConfigured = false; ++ if (m_bFbIsConfigured) ++ return; + + CLog::Log(LOGDEBUG, "iMX : %s - going to change screen parameters\n", __FUNCTION__); + AdaptScreen(); +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +index 4098f63..c6f856e 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +@@ -266,6 +266,8 @@ bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) + CreateNativeDisplay(); + CreateNativeWindow(); + ++ g_IMXContext.OnResetDisplay(); ++ ShowWindow(true); + CLog::Log(LOGDEBUG, "%s: %s",__FUNCTION__, res.strId.c_str()); + + return true; +-- +1.9.1 + + +============================================================== +file 0032-Revert-021323daae52363a8c62bbded00c45ebff373208.patch +============================================================== + +From 77c6349f5b0316f1bcd9b8556499b8086b3f6d64 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 24 Sep 2016 15:33:00 +0200 +Subject: [PATCH] Revert 021323daae52363a8c62bbded00c45ebff373208 + +--- + xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 3 --- + xbmc/windowing/egl/WinSystemEGL.cpp | 33 +++++++++++++++------------------ + xbmc/windowing/egl/WinSystemEGL.h | 4 ---- + 3 files changed, 15 insertions(+), 25 deletions(-) + +diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +index c6f856e..0948032 100644 +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +@@ -97,7 +97,6 @@ void CEGLNativeTypeIMX::Initialize() + } + } + +- g_Windowing.old(); + ShowWindow(false); + + fd = open("/dev/fb0",O_RDWR); +@@ -133,8 +132,6 @@ void CEGLNativeTypeIMX::Initialize() + m_sar = GetMonitorSAR(); + g_IMXContext.create(); + ShowWindow(true); +- +- g_Windowing.ord(); + #endif + return; + } +diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp +index e76737b..852f337 100644 +--- a/xbmc/windowing/egl/WinSystemEGL.cpp ++++ b/xbmc/windowing/egl/WinSystemEGL.cpp +@@ -264,21 +264,6 @@ bool CWinSystemEGL::DestroyWindowSystem() + return true; + } + +-void CWinSystemEGL::old() +-{ +- CSingleLock lock(m_resourceSection); +- for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) +- (*i)->OnLostDisplay(); +-} +- +-void CWinSystemEGL::ord() +-{ +- CSingleLock lock(m_resourceSection); +- // tell any shared resources +- for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) +- (*i)->OnResetDisplay(); +-} +- + bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RESOLUTION_INFO& res, PHANDLE_EVENT_FUNC userFunction) + { + RESOLUTION_INFO current_resolution; +@@ -309,7 +294,11 @@ bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RE + m_dispResetTimer.Set(delay * 100); + } + +- old(); ++ { ++ CSingleLock lock(m_resourceSection); ++ for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) ++ (*i)->OnLostDisplay(); ++ } + + m_stereo_mode = stereo_mode; + m_bFullScreen = fullScreen; +@@ -326,7 +315,12 @@ bool CWinSystemEGL::CreateNewWindow(const std::string& name, bool fullScreen, RE + } + + if (!m_delayDispReset) +- ord(); ++ { ++ CSingleLock lock(m_resourceSection); ++ // tell any shared resources ++ for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) ++ (*i)->OnResetDisplay(); ++ } + + Show(); + return true; +@@ -463,7 +457,10 @@ void CWinSystemEGL::PresentRenderImpl(bool rendered) + if (m_delayDispReset && m_dispResetTimer.IsTimePast()) + { + m_delayDispReset = false; +- ord(); ++ CSingleLock lock(m_resourceSection); ++ // tell any shared resources ++ for (std::vector::iterator i = m_resources.begin(); i != m_resources.end(); ++i) ++ (*i)->OnResetDisplay(); + } + if (!rendered) + return; +diff --git a/xbmc/windowing/egl/WinSystemEGL.h b/xbmc/windowing/egl/WinSystemEGL.h +index 910b156..c24bb35 100644 +--- a/xbmc/windowing/egl/WinSystemEGL.h ++++ b/xbmc/windowing/egl/WinSystemEGL.h +@@ -69,10 +69,6 @@ public: + + EGLDisplay GetEGLDisplay(); + EGLContext GetEGLContext(); +- +- void old(); +- void ord(); +- + protected: + virtual void PresentRenderImpl(bool rendered); + virtual void SetVSyncImpl(bool enable); +-- +1.9.1 + + +============================================================== +file 0033-Initialize-first-two-VPU-frame-buffers-DivX-logo-iss.patch +============================================================== + +From d6f6155a060e0a5b94e3257f7c5d75fa1a8be321 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 24 Sep 2016 15:33:46 +0200 +Subject: [PATCH] Initialize first two VPU frame buffers (DivX logo issue) + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 39 +++++++++++----------- + 1 file changed, 19 insertions(+), 20 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index f692482..e3fa72e 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -371,37 +371,36 @@ bool CIMXCodec::VpuAllocFrameBuffers() + ptrVirt = (unsigned char*)Align(ptrVirt,nAlign); + } + +- VpuFrameBuffer vpuFrameBuffer; +- m_vpuFrameBuffers.push_back(vpuFrameBuffer); ++ VpuFrameBuffer vpuFrameBuffer = {}; + + // fill stride info +- m_vpuFrameBuffers[i].nStrideY = yStride; +- m_vpuFrameBuffers[i].nStrideC = uvStride; ++ vpuFrameBuffer.nStrideY = yStride; ++ vpuFrameBuffer.nStrideC = uvStride; + + // fill phy addr +- m_vpuFrameBuffers[i].pbufY = ptr; +- m_vpuFrameBuffers[i].pbufCb = ptr + ySize; ++ vpuFrameBuffer.pbufY = ptr; ++ vpuFrameBuffer.pbufCb = ptr + ySize; + #ifdef IMX_INPUT_FORMAT_I420 +- m_vpuFrameBuffers[i].pbufCr = ptr + ySize + uSize; +-#else +- m_vpuFrameBuffers[i].pbufCr = 0; ++ vpuFrameBuffer.pbufCr = ptr + ySize + uSize; + #endif +- m_vpuFrameBuffers[i].pbufMvCol = ptr + ySize + uSize + vSize; ++ vpuFrameBuffer.pbufMvCol = ptr + ySize + uSize + vSize; + + // fill virt addr +- m_vpuFrameBuffers[i].pbufVirtY = ptrVirt; +- m_vpuFrameBuffers[i].pbufVirtCb = ptrVirt + ySize; ++ vpuFrameBuffer.pbufVirtY = ptrVirt; ++ vpuFrameBuffer.pbufVirtCb = ptrVirt + ySize; + #ifdef IMX_INPUT_FORMAT_I420 +- m_vpuFrameBuffers[i].pbufVirtCr = ptrVirt + ySize + uSize; +-#else +- m_vpuFrameBuffers[i].pbufVirtCr = 0; ++ vpuFrameBuffer.pbufVirtCr = ptrVirt + ySize + uSize; + #endif +- m_vpuFrameBuffers[i].pbufVirtMvCol = ptrVirt + ySize + uSize + vSize; ++ vpuFrameBuffer.pbufVirtMvCol = ptrVirt + ySize + uSize + vSize; + +- m_vpuFrameBuffers[i].pbufY_tilebot = 0; +- m_vpuFrameBuffers[i].pbufCb_tilebot = 0; +- m_vpuFrameBuffers[i].pbufVirtY_tilebot = 0; +- m_vpuFrameBuffers[i].pbufVirtCb_tilebot = 0; ++ if (i < 2) ++ { ++ memset(vpuFrameBuffer.pbufVirtY, 16, ySize); ++ memset(vpuFrameBuffer.pbufVirtCb, 128, uSize + vSize); ++ memset(vpuFrameBuffer.pbufVirtMvCol, 0, mvSize); ++ } ++ ++ m_vpuFrameBuffers.push_back(vpuFrameBuffer); + } + + if (VPU_DEC_RET_SUCCESS != VPU_DecRegisterFrameBuffer(m_vpuHandle, &m_vpuFrameBuffers[0], m_vpuFrameBuffers.size())) +-- +1.9.1 + + +============================================================== +file 0034-Use-uint32_t-for-physical-addresses.patch +============================================================== + +From fc99366e9fb1d9f8c83875cdb604bf707d0cfd29 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 24 Sep 2016 15:36:23 +0200 +Subject: [PATCH] Use uint32_t for physical addresses + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 2 +- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 2 +- + xbmc/linux/imx/IMX.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index e3fa72e..d55a6b7 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1180,7 +1180,7 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, + iWidth = frameInfo->pExtInfo->nFrmWidth; + iHeight = frameInfo->pExtInfo->nFrmHeight; + pVirtAddr = m_frameBuffer->pbufVirtY; +- pPhysAddr = (int)m_frameBuffer->pbufY; ++ pPhysAddr = (uint32_t)m_frameBuffer->pbufY; + + #ifdef IMX_INPUT_FORMAT_I420 + iFormat = _4CC('I', '4', '2', '0'); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 6a4f638..69a74fe 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -185,7 +185,7 @@ private: + int m_fbLineLength; + int m_fbPageSize; + int m_fbPhysSize; +- int m_fbPhysAddr; ++ uint32_t m_fbPhysAddr; + uint8_t *m_fbVirtAddr; + struct fb_var_screeninfo m_fbVar; + int m_ipuHandle; +diff --git a/xbmc/linux/imx/IMX.h b/xbmc/linux/imx/IMX.h +index 8d13333..7363409 100644 +--- a/xbmc/linux/imx/IMX.h ++++ b/xbmc/linux/imx/IMX.h +@@ -183,7 +183,7 @@ public: + public: + uint32_t iWidth; + uint32_t iHeight; +- int pPhysAddr; ++ uint32_t pPhysAddr; + uint8_t *pVirtAddr; + int iFormat; + double m_fps; +-- +1.9.1 + + +============================================================== +file 0035-Fix-page-counting-avoid-compiler-warning.patch +============================================================== + +From 3c339bb9e574621d08c7d203582b3130211aff5a Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 24 Sep 2016 15:39:38 +0200 +Subject: [PATCH] Fix page counting, avoid compiler warning + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index d55a6b7..1ea4922 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1540,15 +1540,15 @@ ipu_motion_sel CIMXContext::SetIPUMotion(std::string &strImethod) + void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, const CRect &srcRect, + const CRect &dstRect, uint8_t fieldFmt, int page) + { +- static unsigned char pg; ++ static int pg = 0; + + if (page == RENDER_TASK_AUTOPAGE) + page = pg; +- else if (page < 0 && page >= m_fbPages) ++ else if (page < 0 || page >= m_fbPages) + return; + + IPUTaskPtr ipu(new IPUTask(source_p, source, page)); +- pg = ++pg % m_fbPages; ++ pg = (page + 1) % m_fbPages; + + #ifdef IMX_PROFILE_BUFFERS + unsigned long long before = XbmcThreads::SystemClockMillis(); +-- +1.9.1 + + +============================================================== +file 0036-Refactor-IPUTask-for-better-readability-and-performa.patch +============================================================== + +From 3c7ee4e10ab3bab6fc3dd0ad8f375b9112d9093f Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 24 Sep 2016 16:13:51 +0200 +Subject: [PATCH] Refactor IPUTask for better readability and performance + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 144 ++++++++++----------- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 26 ++-- + 2 files changed, 82 insertions(+), 88 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 1ea4922..3535c09 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1547,24 +1547,24 @@ void CIMXContext::Blit(CIMXBuffer *source_p, CIMXBuffer *source, const CRect &sr + else if (page < 0 || page >= m_fbPages) + return; + +- IPUTaskPtr ipu(new IPUTask(source_p, source, page)); ++ IPUTask task(source_p, source, page); + pg = (page + 1) % m_fbPages; + + #ifdef IMX_PROFILE_BUFFERS + unsigned long long before = XbmcThreads::SystemClockMillis(); + #endif + SetFieldData(fieldFmt, source->m_fps); +- PrepareTask(ipu, srcRect, dstRect); ++ PrepareTask(task, srcRect, dstRect); + +- if (!DoTask(ipu)) ++ if (!DoTask(task)) + return; + +- m_flip = ipu->page | checkIPUStrideOffset(&ipu->task.input.deinterlace) << 4; ++ m_flip = task.targetPage | checkIPUStrideOffset(&task.input.deinterlace) << 4; + m_waitFlip.Set(); + + #ifdef IMX_PROFILE_BUFFERS + unsigned long long after = XbmcThreads::SystemClockMillis(); +- CLog::Log(LOGDEBUG, "+P 0x%x@%d %d\n", ((CDVDVideoCodecIMXBuffer*)ipu->current)->GetIdx(), ipu->page, (int)(after-before)); ++ CLog::Log(LOGDEBUG, "+P 0x%x@%d %d\n", ((CDVDVideoCodecIMXBuffer*)task.currBuf)->GetIdx(), task.targetPage, (int)(after-before)); + #endif + } + +@@ -1644,7 +1644,7 @@ void CIMXContext::Clear(int page) + SetProcessInfo(m_processInfo); + } + +-void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect) ++void CIMXContext::PrepareTask(IPUTask &task, CRect srcRect, CRect dstRect) + { + CRectInt iSrcRect, iDstRect; + +@@ -1689,78 +1689,78 @@ void CIMXContext::PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect) + iDstRect.x2 = Align2((int)dstRect.x2,8); + iDstRect.y2 = Align2((int)dstRect.y2,8); + +- ipu->task.input.crop.pos.x = iSrcRect.x1; +- ipu->task.input.crop.pos.y = iSrcRect.y1; +- ipu->task.input.crop.w = iSrcRect.Width(); +- ipu->task.input.crop.h = iSrcRect.Height(); ++ task.input.crop.pos.x = iSrcRect.x1; ++ task.input.crop.pos.y = iSrcRect.y1; ++ task.input.crop.w = iSrcRect.Width(); ++ task.input.crop.h = iSrcRect.Height(); + +- ipu->task.output.crop.pos.x = iDstRect.x1; +- ipu->task.output.crop.pos.y = iDstRect.y1; +- ipu->task.output.crop.w = iDstRect.Width(); +- ipu->task.output.crop.h = iDstRect.Height(); ++ task.output.crop.pos.x = iDstRect.x1; ++ task.output.crop.pos.y = iDstRect.y1; ++ task.output.crop.w = iDstRect.Width(); ++ task.output.crop.h = iDstRect.Height(); + + // Setup deinterlacing if enabled +- if (m_currentFieldFmt && ipu->previous) ++ if (m_currentFieldFmt && task.prevBuf) + { +- ipu->task.input.deinterlace.enable = 1; +- ipu->task.input.deinterlace.motion = m_motion; +- ipu->task.input.deinterlace.field_fmt = m_currentFieldFmt; ++ task.input.deinterlace.enable = 1; ++ task.input.deinterlace.motion = m_motion; ++ task.input.deinterlace.field_fmt = m_currentFieldFmt; + } + } + +-bool CIMXContext::TileTask(IPUTaskPtr &ipu) ++bool CIMXContext::TileTask(IPUTask &task) + { +- int pad = ipu->task.input.height == 1080 && ipu->current->iHeight>ipu->task.input.height ? 16*ipu->current->iWidth : 0; ++ int pad = task.input.height == 1080 && task.currBuf->iHeight>task.input.height ? 16*task.currBuf->iWidth : 0; + m_zoomAllowed = true; + +- if (ipu->current->iFormat != _4CC('T', 'N', 'V', 'F') && ipu->current->iFormat != _4CC('T', 'N', 'V', 'P')) ++ if (task.currBuf->iFormat != _4CC('T', 'N', 'V', 'F') && task.currBuf->iFormat != _4CC('T', 'N', 'V', 'P')) + { +- if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION) ++ if (task.input.deinterlace.enable && task.input.deinterlace.motion != HIGH_MOTION) + { +- ipu->task.input.paddr_n = ipu->task.input.paddr; +- ipu->task.input.paddr = ipu->previous->pPhysAddr + pad; ++ task.input.paddr_n = task.input.paddr; ++ task.input.paddr = task.prevBuf->pPhysAddr + pad; + } + else +- ipu->task.input.paddr += pad; ++ task.input.paddr += pad; + return true; + } + + // Use band mode directly to FB, as no transformations needed (eg cropping) +- if (m_fps >= 49 && m_fbWidth == 1920 && ipu->task.input.width == 1920 && !ipu->task.input.deinterlace.enable) ++ if (m_fps >= 49 && m_fbWidth == 1920 && task.input.width == 1920 && !task.input.deinterlace.enable) + { + m_zoomAllowed = false; +- ipu->task.output.crop.pos.x = ipu->task.input.crop.pos.x = 0; +- ipu->task.output.crop.pos.y = ipu->task.input.crop.pos.y = 0; +- ipu->task.output.crop.h = ipu->task.input.height = ipu->task.input.crop.h = ipu->current->iHeight; +- ipu->task.output.paddr += m_fbLineLength * (m_fbHeight - ipu->task.input.crop.h)/2; ++ task.output.crop.pos.x = task.input.crop.pos.x = 0; ++ task.output.crop.pos.y = task.input.crop.pos.y = 0; ++ task.output.crop.h = task.input.height = task.input.crop.h = task.currBuf->iHeight; ++ task.output.paddr += m_fbLineLength * (m_fbHeight - task.input.crop.h)/2; + return true; + } + // rasterize from tile (frame) + struct ipu_task vdoa; + +- memset(&vdoa, 0, sizeof(ipu->task)); +- vdoa.input.width = vdoa.output.width = ipu->current->iWidth; +- vdoa.input.height = vdoa.output.height = ipu->current->iHeight; +- vdoa.input.format = ipu->current->iFormat; ++ memset(&vdoa, 0, sizeof(vdoa)); ++ vdoa.input.width = vdoa.output.width = task.currBuf->iWidth; ++ vdoa.input.height = vdoa.output.height = task.currBuf->iHeight; ++ vdoa.input.format = task.currBuf->iFormat; + + // check for 3-field deinterlace (no HIGH_MOTION allowed) from tile field format +- if (ipu->previous && ipu->current->iFormat == _4CC('T', 'N', 'V', 'F')) ++ if (task.prevBuf && task.currBuf->iFormat == _4CC('T', 'N', 'V', 'F')) + { +- memcpy(&vdoa.input.deinterlace, &ipu->task.input.deinterlace, sizeof(ipu->task.input.deinterlace)); +- memset(&ipu->task.input.deinterlace, 0, sizeof(ipu->task.input.deinterlace)); +- vdoa.input.paddr_n = ipu->current->pPhysAddr; ++ memcpy(&vdoa.input.deinterlace, &task.input.deinterlace, sizeof(task.input.deinterlace)); ++ memset(&task.input.deinterlace, 0, sizeof(task.input.deinterlace)); ++ vdoa.input.paddr_n = task.currBuf->pPhysAddr; + } + +- struct g2d_buf *conv = g2d_alloc(ipu->current->iWidth *ipu->current->iHeight * 3, 0); ++ struct g2d_buf *conv = g2d_alloc(task.currBuf->iWidth * task.currBuf->iHeight * 3, 0); + if (!conv) + { + CLog::Log(LOGERROR, "iMX: can't allocate crop buffer"); + return false; + } + +- ((CDVDVideoCodecIMXBuffer*)ipu->current)->m_convBuffer = conv; ++ ((CDVDVideoCodecIMXBuffer*)task.currBuf)->m_convBuffer = conv; + +- vdoa.input.paddr = vdoa.input.paddr_n ? ipu->previous->pPhysAddr : ipu->current->pPhysAddr; ++ vdoa.input.paddr = vdoa.input.paddr_n ? task.prevBuf->pPhysAddr : task.currBuf->pPhysAddr; + vdoa.output.format = m_fbVar.bits_per_pixel == 16 ? _4CC('Y', 'U', 'Y', 'V') : _4CC('N', 'V', '1', '2'); + vdoa.output.paddr = conv->buf_paddr; + +@@ -1771,70 +1771,70 @@ bool CIMXContext::TileTask(IPUTaskPtr &ipu) + return false; + } + +- ipu->task.input.paddr = vdoa.output.paddr + pad; +- ipu->task.input.format = vdoa.output.format; +- if (ipu->task.input.deinterlace.enable && ipu->task.input.deinterlace.motion != HIGH_MOTION) ++ task.input.paddr = vdoa.output.paddr + pad; ++ task.input.format = vdoa.output.format; ++ if (task.input.deinterlace.enable && task.input.deinterlace.motion != HIGH_MOTION) + { +- ipu->task.input.paddr_n = ipu->task.input.paddr; +- ipu->task.input.paddr = ipu->previous->pPhysAddr + pad; ++ task.input.paddr_n = task.input.paddr; ++ task.input.paddr = task.prevBuf->pPhysAddr + pad; + } +- ipu->current->iFormat = vdoa.output.format; +- ipu->current->pPhysAddr = vdoa.output.paddr; ++ task.currBuf->iFormat = vdoa.output.format; ++ task.currBuf->pPhysAddr = vdoa.output.paddr; + + return true; + } + +-bool CIMXContext::DoTask(IPUTaskPtr &ipu, CRect *dest) ++bool CIMXContext::DoTask(IPUTask &task, CRect *dest) + { + // Clear page if cropping changes +- CRectInt dstRect(ipu->task.output.crop.pos.x, ipu->task.output.crop.pos.y, +- ipu->task.output.crop.pos.x + ipu->task.output.crop.w, +- ipu->task.output.crop.pos.y + ipu->task.output.crop.h); ++ CRectInt dstRect(task.output.crop.pos.x, task.output.crop.pos.y, ++ task.output.crop.pos.x + task.output.crop.w, ++ task.output.crop.pos.y + task.output.crop.h); + + // Populate input block +- ipu->task.input.width = ipu->current->iWidth; +- ipu->task.input.height = std::min(ipu->current->iHeight, (unsigned int)1080); +- ipu->task.input.format = ipu->current->iFormat; +- ipu->task.input.paddr = ipu->current->pPhysAddr; ++ task.input.width = task.currBuf->iWidth; ++ task.input.height = std::min(task.currBuf->iHeight, (unsigned int)1080); ++ task.input.format = task.currBuf->iFormat; ++ task.input.paddr = task.currBuf->pPhysAddr; + +- ipu->task.output.width = m_fbWidth; +- ipu->task.output.height = m_fbHeight; +- ipu->task.output.format = m_fbVar.nonstd; +- ipu->task.output.paddr = m_fbPhysAddr + ipu->page*m_fbPageSize; ++ task.output.width = m_fbWidth; ++ task.output.height = m_fbHeight; ++ task.output.format = m_fbVar.nonstd; ++ task.output.paddr = m_fbPhysAddr + task.targetPage * m_fbPageSize; + +- if (m_pageCrops[ipu->page] != dstRect) ++ if (m_pageCrops[task.targetPage] != dstRect) + { +- m_pageCrops[ipu->page] = dstRect; +- Clear(ipu->page); ++ m_pageCrops[task.targetPage] = dstRect; ++ Clear(task.targetPage); + } + +- if ((ipu->task.input.crop.w <= 0) || (ipu->task.input.crop.h <= 0) +- || (ipu->task.output.crop.w <= 0) || (ipu->task.output.crop.h <= 0)) ++ if ((task.input.crop.w <= 0) || (task.input.crop.h <= 0) ++ || (task.output.crop.w <= 0) || (task.output.crop.h <= 0)) + return false; + +- int ret = !TileTask(ipu); ++ int ret = !TileTask(task); + if (!ret) + { + //We really use IPU only if we have to deinterlace (using VDIC) + ret = IPU_CHECK_ERR_INPUT_CROP; + while (ret > IPU_CHECK_ERR_MIN) + { +- ret = ioctl(m_ipuHandle, IPU_CHECK_TASK, &ipu->task); ++ ret = ioctl(m_ipuHandle, IPU_CHECK_TASK, &task); + switch (ret) + { + case IPU_CHECK_OK: + break; + case IPU_CHECK_ERR_SPLIT_INPUTW_OVER: +- ipu->task.input.crop.w -= 8; ++ task.input.crop.w -= 8; + break; + case IPU_CHECK_ERR_SPLIT_INPUTH_OVER: +- ipu->task.input.crop.h -= 8; ++ task.input.crop.h -= 8; + break; + case IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER: +- ipu->task.output.crop.w -= 8; ++ task.output.crop.w -= 8; + break; + case IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER: +- ipu->task.output.crop.h -= 8; ++ task.output.crop.h -= 8; + break; + // deinterlacing setup changing, m_ipuHandle is closed + case -1: +@@ -1845,7 +1845,7 @@ bool CIMXContext::DoTask(IPUTaskPtr &ipu, CRect *dest) + } + } + +- ret = ioctl(m_ipuHandle, IPU_QUEUE_TASK, &ipu->task); ++ ret = ioctl(m_ipuHandle, IPU_QUEUE_TASK, &task); + if (ret < 0) + CLog::Log(LOGERROR, "IPU task failed: %s at #%d\n", strerror(errno), __LINE__); + } +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 69a74fe..88aa06f 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -137,32 +137,26 @@ public: + static const int m_fbPages; + + private: +- struct IPUTask ++ struct IPUTask : public ipu_task + { +- IPUTask(CIMXBuffer *buffer_p, CIMXBuffer *buffer, int p = 0) +- : previous(buffer_p), current(buffer), page(p) ++ IPUTask(CIMXBuffer *buffer_p, CIMXBuffer *buffer, int page) ++ : prevBuf(buffer_p), currBuf(buffer), targetPage(page) + { +- memset(&task, 0, sizeof(task)); ++ memset(this, 0, sizeof(ipu_task)); + } + + // Kept for reference +- CIMXBuffer *previous; +- CIMXBuffer *current; ++ CIMXBuffer *prevBuf; ++ CIMXBuffer *currBuf; + +- // The actual task +- struct ipu_task task; +- +- unsigned int page; +- int shift = true; ++ int targetPage; + }; + +- typedef std::shared_ptr IPUTaskPtr; +- + bool GetFBInfo(const std::string &fbdev, struct fb_var_screeninfo *fbVar); + +- void PrepareTask(IPUTaskPtr &ipu, CRect srcRect, CRect dstRect); +- bool DoTask(IPUTaskPtr &ipu, CRect *dest = nullptr); +- bool TileTask(IPUTaskPtr &ipu); ++ void PrepareTask(IPUTask &task, CRect srcRect, CRect dstRect); ++ bool DoTask(IPUTask &task, CRect *dest = nullptr); ++ bool TileTask(IPUTask &task); + + void SetFieldData(uint8_t fieldFmt, double fps); + +-- +1.9.1 + + +============================================================== +file 0037-Refactor-RendererIMX-for-better-readability-and-perf.patch +============================================================== + +From 1ba2204a33647b1b81ebc69e7744857a07b1dc23 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 24 Sep 2016 16:53:42 +0200 +Subject: [PATCH] Refactor RendererIMX for better readability and performance + +--- + .../VideoRenderers/HwDecRender/RendererIMX.cpp | 24 ++++++++-------------- + .../VideoRenderers/HwDecRender/RendererIMX.h | 4 ++-- + 2 files changed, 11 insertions(+), 17 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +index aeef073..8569c72 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +@@ -34,14 +34,15 @@ + + CRendererIMX::CRendererIMX() + { +- m_bufHistory.clear(); ++ m_bufHistory[0] = m_bufHistory[1] = nullptr; + g_IMXContext.Clear(); + } + + CRendererIMX::~CRendererIMX() + { + UnInit(); +- std::for_each(m_bufHistory.begin(), m_bufHistory.end(), Release); ++ SAFE_RELEASE(m_bufHistory[1]); ++ SAFE_RELEASE(m_bufHistory[0]); + g_IMXContext.Clear(); + g_IMX.Deinitialize(); + } +@@ -141,24 +142,18 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + CDVDVideoCodecIMXBuffer *buffer = static_cast(m_buffers[m_iYV12RenderBuffer].hwDec); + if (buffer) + { +- if (!m_bufHistory.empty() && m_bufHistory.back() != buffer || m_bufHistory.empty()) +- { +- buffer->Lock(); +- m_bufHistory.push_back(buffer); +- } +- else if (!m_bufHistory.empty() && m_bufHistory.back() == buffer && flagsPrev == flags) ++ if (buffer == m_bufHistory[0] && flagsPrev == flags) + { + g_IMX.WaitVsync(); + return true; + } + + flagsPrev = flags; ++ buffer->Lock(); + +- if (m_bufHistory.size() > 2) +- { +- m_bufHistory.front()->Release(); +- m_bufHistory.pop_front(); +- } ++ SAFE_RELEASE(m_bufHistory[1]); ++ m_bufHistory[1] = m_bufHistory[0]; ++ m_bufHistory[0] = buffer; + + // this hack is needed to get the 2D mode of a 3D movie going + RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode(); +@@ -207,8 +202,7 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + } + } + +- CDVDVideoCodecIMXBuffer *buffer_p = m_bufHistory.front(); +- g_IMXContext.Blit(buffer_p == buffer ? nullptr : buffer_p, buffer, srcRect, dstRect, fieldFmt); ++ g_IMXContext.Blit(m_bufHistory[1], m_bufHistory[0], srcRect, dstRect, fieldFmt); + } + + #if 0 +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +index fc71e89..830b556 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.h +@@ -62,8 +62,8 @@ protected: + virtual int GetImageHook(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); + virtual bool RenderUpdateVideoHook(bool clear, DWORD flags = 0, DWORD alpha = 255); + +- std::deque m_bufHistory; +- static void Release(CDVDVideoCodecIMXBuffer *&t) { if (t) t->Release(); } ++private: ++ CDVDVideoCodecIMXBuffer *m_bufHistory[2]; + }; + + #endif +-- +1.9.1 + + +============================================================== +file 0038-Cleanup-CDVDVideoCodecIMXBuffer.patch +============================================================== + +From 31b9656b805995e8d03b4dc66cc6961423d23942 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sun, 2 Oct 2016 17:18:30 +0200 +Subject: [PATCH] Cleanup CDVDVideoCodecIMXBuffer + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 35 ++++++++++++---------- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 12 ++++---- + xbmc/linux/imx/IMX.h | 2 -- + 3 files changed, 26 insertions(+), 23 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 3535c09..a3d993b 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -1111,48 +1111,49 @@ void CIMXCodec::ExitError(const char *msg, ...) + + bool CIMXCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture) + { +- pDvdVideoPicture->IMXBuffer = m_decOutput.pop(); +- assert(pDvdVideoPicture->IMXBuffer); ++ CDVDVideoCodecIMXBuffer *pIMXBuffer = m_decOutput.pop(); ++ assert(pIMXBuffer); + + #ifdef IMX_PROFILE + static unsigned int previous = 0; + unsigned int current; + + current = XbmcThreads::SystemClockMillis(); +- CLog::Log(LOGDEBUG, "+G 0x%x %f/%f tm:%03d : Interlaced 0x%x\n", pDvdVideoPicture->IMXBuffer->GetIdx(), +- recalcPts(pDvdVideoPicture->IMXBuffer->GetDts()), recalcPts(pDvdVideoPicture->IMXBuffer->GetPts()), current - previous, +- m_initInfo.nInterlace ? pDvdVideoPicture->IMXBuffer->GetFieldType() : 0); ++ CLog::Log(LOGDEBUG, "+G 0x%x %f/%f tm:%03d : Interlaced 0x%x\n", pIMXBuffer->GetIdx(), ++ recalcPts(pIMXBuffer->GetDts()), recalcPts(pIMXBuffer->GetPts()), current - previous, ++ m_initInfo.nInterlace ? pIMXBuffer->GetFieldType() : 0); + previous = current; + #endif + +- pDvdVideoPicture->iFlags = m_dropRequest ? DVP_FLAG_DROPPED : pDvdVideoPicture->IMXBuffer->GetFlags(); ++ pDvdVideoPicture->iFlags = m_dropRequest ? DVP_FLAG_DROPPED : pIMXBuffer->GetFlags(); + + if (m_initInfo.nInterlace) + { +- if (pDvdVideoPicture->IMXBuffer->GetFieldType() == VPU_FIELD_NONE && m_warnOnce) ++ if (pIMXBuffer->GetFieldType() == VPU_FIELD_NONE && m_warnOnce) + { + m_warnOnce = false; + CLog::Log(LOGWARNING, "Interlaced content reported by VPU, but full frames detected - Please turn off deinterlacing manually."); + } +- else if (pDvdVideoPicture->IMXBuffer->GetFieldType() == VPU_FIELD_TB || pDvdVideoPicture->IMXBuffer->GetFieldType() == VPU_FIELD_TOP) ++ else if (pIMXBuffer->GetFieldType() == VPU_FIELD_TB || pIMXBuffer->GetFieldType() == VPU_FIELD_TOP) + pDvdVideoPicture->iFlags |= DVP_FLAG_TOP_FIELD_FIRST; + + pDvdVideoPicture->iFlags |= DVP_FLAG_INTERLACED; + } + + pDvdVideoPicture->format = RENDER_FMT_IMXMAP; +- pDvdVideoPicture->iWidth = pDvdVideoPicture->IMXBuffer->m_pctWidth; +- pDvdVideoPicture->iHeight = pDvdVideoPicture->IMXBuffer->m_pctHeight; ++ pDvdVideoPicture->iWidth = pIMXBuffer->GetPictureWidth(); ++ pDvdVideoPicture->iHeight = pIMXBuffer->GetPictureHeight(); + + pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; + pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; + +- pDvdVideoPicture->pts = pDvdVideoPicture->IMXBuffer->GetPts(); +- pDvdVideoPicture->dts = pDvdVideoPicture->IMXBuffer->GetDts(); ++ pDvdVideoPicture->pts = pIMXBuffer->GetPts(); ++ pDvdVideoPicture->dts = pIMXBuffer->GetDts(); + + if (pDvdVideoPicture->iFlags & DVP_FLAG_DROPPED) +- SAFE_RELEASE(pDvdVideoPicture->IMXBuffer); ++ SAFE_RELEASE(pIMXBuffer); + ++ pDvdVideoPicture->IMXBuffer = pIMXBuffer; + return true; + } + +@@ -1198,15 +1199,18 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, + + void CDVDVideoCodecIMXBuffer::Lock() + { +- long count = ++m_iRefs; + #ifdef TRACE_FRAMES ++ long count = ++m_iRefs; + CLog::Log(LOGDEBUG, "R+ 0x%x - ref : %ld (VPU)\n", m_idx, count); ++#else ++ ++m_iRefs; + #endif + } + + long CDVDVideoCodecIMXBuffer::Release() + { + long count = --m_iRefs; ++ + #ifdef TRACE_FRAMES + CLog::Log(LOGDEBUG, "R- 0x%x - ref : %ld (VPU)\n", m_idx, count); + #endif +@@ -1215,6 +1219,7 @@ long CDVDVideoCodecIMXBuffer::Release() + return count; + + CIMXCodec::ReleaseFramebuffer(m_frameBuffer); ++ + if (m_convBuffer) + g2d_free(m_convBuffer); + +@@ -1758,7 +1763,7 @@ bool CIMXContext::TileTask(IPUTask &task) + return false; + } + +- ((CDVDVideoCodecIMXBuffer*)task.currBuf)->m_convBuffer = conv; ++ ((CDVDVideoCodecIMXBuffer*)task.currBuf)->SetConvBuffer(conv); + + vdoa.input.paddr = vdoa.input.paddr_n ? task.prevBuf->pPhysAddr : task.currBuf->pPhysAddr; + vdoa.output.format = m_fbVar.bits_per_pixel == 16 ? _4CC('Y', 'U', 'Y', 'V') : _4CC('N', 'V', '1', '2'); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 88aa06f..5165e4a 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -237,8 +237,6 @@ public: + // Base class of IMXVPU and IMXIPU buffer + class CDVDVideoCodecIMXBuffer : public CIMXBuffer + { +-friend class CIMXCodec; +-friend class CIMXContext; + public: + CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, double fps, int map); + virtual ~CDVDVideoCodecIMXBuffer(); +@@ -261,11 +259,15 @@ public: + #endif + VpuFieldType GetFieldType() const { return m_fieldType; } + +-protected: ++ unsigned int GetPictureWidth() { return m_pctWidth; } ++ unsigned int GetPictureHeight() { return m_pctHeight; } ++ ++ void SetConvBuffer(struct g2d_buf *b) { m_convBuffer = b; } ++ ++private: + unsigned int m_pctWidth; + unsigned int m_pctHeight; + +-private: + double m_pts; + double m_dts; + VpuFieldType m_fieldType; +@@ -275,8 +277,6 @@ private: + unsigned char m_idx; + static unsigned char i; + #endif +- +-public: + struct g2d_buf *m_convBuffer; + }; + +diff --git a/xbmc/linux/imx/IMX.h b/xbmc/linux/imx/IMX.h +index 7363409..c548633 100644 +--- a/xbmc/linux/imx/IMX.h ++++ b/xbmc/linux/imx/IMX.h +@@ -178,8 +178,6 @@ public: + virtual void Lock() = 0; + virtual long Release() = 0; + +- int GetFormat() { return iFormat; } +- + public: + uint32_t iWidth; + uint32_t iHeight; +-- +1.9.1 + + +============================================================== +file 0039-Prevent-lkFIFO-from-returning-uninitialized-data.patch +============================================================== + +From 5dee77ae7dc1233ba2ff87ee25277a7643640a61 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sun, 2 Oct 2016 18:43:52 +0200 +Subject: [PATCH] Prevent lkFIFO from returning uninitialized data + +--- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 17 +++++++++++++---- + xbmc/linux/imx/IMX.h | 16 ++++++++-------- + 2 files changed, 21 insertions(+), 12 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index a3d993b..717b5ce 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -872,7 +872,7 @@ void CIMXCodec::Process() + { + RecycleFrameBuffers(); + SAFE_DELETE(task); +- if (!(task = m_decInput.pop())) ++ if (!m_decInput.pop(task)) + task = new VPUTask(); + + #if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) +@@ -1035,7 +1035,11 @@ void CIMXCodec::Process() + + if (m_decRet & VPU_DEC_NO_ENOUGH_BUF && m_decOutput.size()) + { +- m_decOutput.pop()->Release(); ++ CDVDVideoCodecIMXBuffer *buffer; ++ ++ if (m_decOutput.pop(buffer)) ++ buffer->Release(); ++ + FlushVPU(); + continue; + } +@@ -1111,8 +1115,13 @@ void CIMXCodec::ExitError(const char *msg, ...) + + bool CIMXCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture) + { +- CDVDVideoCodecIMXBuffer *pIMXBuffer = m_decOutput.pop(); +- assert(pIMXBuffer); ++ CDVDVideoCodecIMXBuffer *pIMXBuffer; ++ ++ if( !m_decOutput.pop(pIMXBuffer)) ++ { ++ memset(pDvdVideoPicture, 0, sizeof(*pDvdVideoPicture)); ++ return false; ++ } + + #ifdef IMX_PROFILE + static unsigned int previous = 0; +diff --git a/xbmc/linux/imx/IMX.h b/xbmc/linux/imx/IMX.h +index c548633..24a380c 100644 +--- a/xbmc/linux/imx/IMX.h ++++ b/xbmc/linux/imx/IMX.h +@@ -80,23 +80,22 @@ public: + lkFIFO() { m_size = queue.max_size(); queue.clear(); m_abort = false; } + + public: +- T pop() ++ bool pop(T &item) + { + std::unique_lock m_lock(lkqueue); + m_abort = false; + while (!queue.size() && !m_abort) + read.wait(m_lock); + +- T val; +- if (!queue.empty()) +- { +- val = queue.front(); +- queue.pop_front(); +- } ++ if (queue.empty()) ++ return false; ++ ++ item = queue.front(); ++ queue.pop_front(); + + m_lock.unlock(); + write.notify_one(); +- return val; ++ return true; + } + + bool push(const T& item) +@@ -110,6 +109,7 @@ public: + return false; + + queue.push_back(item); ++ + m_lock.unlock(); + read.notify_one(); + return true; +-- +1.9.1 + + +============================================================== +file 0040-Add-symbolic-constant-for-VPU-map-type.patch +============================================================== + +From f5d8542171f75399371c601a8bf2596fbc265bd5 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Mon, 3 Oct 2016 09:12:15 +0200 +Subject: [PATCH] Add symbolic constant for VPU map type + +--- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 15 ++++++++------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 9 ++++++++- + 2 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 717b5ce..0327e90 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -770,7 +770,7 @@ int CIMXCodec::Decode(BYTE *pData, int iSize, double dts, double pts) + else if (fd) + m_fps = DVD_TIME_BASE / fd; + +- m_decOpenParam.nMapType = 1; ++ m_decOpenParam.nMapType = MAPTYPE_TILED_FRAME; + + ptrn.Flush(); + g_IMXCodec->Create(); +@@ -951,9 +951,10 @@ void CIMXCodec::Process() + if (!VpuFreeBuffers(false) || !VpuAllocFrameBuffers()) + ExitError("VPU error while registering frame buffers"); + +- if (m_initInfo.nInterlace && m_fps >= 49 && !m_converter && m_decOpenParam.nMapType == 1) ++ if (m_initInfo.nInterlace && m_fps >= 49 && ++ !m_converter && m_decOpenParam.nMapType == MAPTYPE_TILED_FRAME) + { +- m_decOpenParam.nMapType = 0; ++ m_decOpenParam.nMapType = MAPTYPE_LINEAR_FRAME; + Dispose(); + VpuOpen(); + continue; +@@ -1177,7 +1178,7 @@ bool CIMXCodec::IsCurrentThread() const + } + + /*******************************************/ +-CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, double fps, int map) ++CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, double fps, int mapType) + : m_dts(DVD_NOPTS_VALUE) + , m_fieldType(frameInfo->eFieldType) + , m_frameBuffer(frameInfo->pDisplayFrameBuf) +@@ -1195,9 +1196,9 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, + #ifdef IMX_INPUT_FORMAT_I420 + iFormat = _4CC('I', '4', '2', '0'); + #else +- iFormat = map == 1 ? _4CC('T', 'N', 'V', 'P'): +- map == 0 ? _4CC('N', 'V', '1', '2'): +- _4CC('T', 'N', 'V', 'F'); ++ iFormat = mapType == MAPTYPE_TILED_FRAME ? _4CC('T', 'N', 'V', 'P'): ++ mapType == MAPTYPE_LINEAR_FRAME ? _4CC('N', 'V', '1', '2'): ++ _4CC('T', 'N', 'V', 'F'); + #endif + m_fps = fps; + #if defined(IMX_PROFILE) || defined(IMX_PROFILE_BUFFERS) || defined(TRACE_FRAMES) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 5165e4a..2168e00 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -84,6 +84,13 @@ enum RENDER_TASK + RENDER_TASK_CAPTURE = -2, + }; + ++enum VPU_MAPTYPE ++{ ++ MAPTYPE_LINEAR_FRAME = 0, ++ MAPTYPE_TILED_FRAME = 1, ++ MAPTYPE_TILED_FIELD = 2, ++}; ++ + #define CLASS_PICTURE (VPU_DEC_OUTPUT_DIS | VPU_DEC_OUTPUT_MOSAIC_DIS) + #define CLASS_NOBUF (VPU_DEC_OUTPUT_NODIS | VPU_DEC_NO_ENOUGH_BUF | VPU_DEC_OUTPUT_REPEAT) + #define CLASS_FORCEBUF (VPU_DEC_OUTPUT_EOS | VPU_DEC_NO_ENOUGH_INBUF) +@@ -238,7 +245,7 @@ public: + class CDVDVideoCodecIMXBuffer : public CIMXBuffer + { + public: +- CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, double fps, int map); ++ CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, double fps, int mapType); + virtual ~CDVDVideoCodecIMXBuffer(); + + // reference counting +-- +1.9.1 + + +============================================================== +file 0041-Remove-m_frameInfo-member-variable-from-CIMXCodec-cl.patch +============================================================== + +From bf74debf19cafddb572033b232bed0cc99541eea Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Mon, 3 Oct 2016 09:47:38 +0200 +Subject: [PATCH] Remove m_frameInfo member variable from CIMXCodec class + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 27 +++++++++++----------- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 3 ++- + 2 files changed, 16 insertions(+), 14 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 0327e90..74f4ae4 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -842,6 +842,7 @@ void CIMXCodec::AddExtraData(VpuBufferNode *bn, bool force) + void CIMXCodec::Process() + { + VpuDecFrameLengthInfo frameLengthInfo; ++ VpuDecOutFrameInfo frameInfo; + VpuBufferNode inData; + VpuBufferNode dummy; + VpuDecRetCode ret; +@@ -987,20 +988,20 @@ void CIMXCodec::Process() + if (!VPU_DecGetConsumedFrameInfo(m_vpuHandle, &frameLengthInfo) && frameLengthInfo.pFrame) + m_pts[frameLengthInfo.pFrame] = task->demux.pts; + +- if (m_decRet & CLASS_PICTURE && getOutputFrame(&m_frameInfo)) ++ if (m_decRet & CLASS_PICTURE && getOutputFrame(&frameInfo)) + { + // Some codecs (VC1?) lie about their frame size (mod 16). Adjust... +- m_frameInfo.pExtInfo->nFrmWidth = (((m_frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); +- m_frameInfo.pExtInfo->nFrmHeight = (((m_frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); ++ frameInfo.pExtInfo->nFrmWidth = (((frameInfo.pExtInfo->nFrmWidth) + 15) & ~15); ++ frameInfo.pExtInfo->nFrmHeight = (((frameInfo.pExtInfo->nFrmHeight) + 15) & ~15); + + ++m_nrOut; +- CDVDVideoCodecIMXBuffer *buffer = new CDVDVideoCodecIMXBuffer(&m_frameInfo, m_fps, m_decOpenParam.nMapType); ++ CDVDVideoCodecIMXBuffer *buffer = new CDVDVideoCodecIMXBuffer(&frameInfo, m_fps, m_decOpenParam.nMapType); + + /* quick & dirty fix to get proper timestamping for VP8 codec */ + if (m_decOpenParam.CodecFormat == VPU_V_VP8) + buffer->SetPts(task->demux.pts); + else +- buffer->SetPts(m_pts[m_frameInfo.pDisplayFrameBuf]); ++ buffer->SetPts(m_pts[frameInfo.pDisplayFrameBuf]); + + buffer->SetDts(task->demux.dts); + +@@ -1154,7 +1155,7 @@ bool CIMXCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->iWidth = pIMXBuffer->GetPictureWidth(); + pDvdVideoPicture->iHeight = pIMXBuffer->GetPictureHeight(); + +- pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * m_frameInfo.pExtInfo->nQ16ShiftWidthDivHeightRatio) + 32767) >> 16; ++ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * pIMXBuffer->GetWidthHeightRatio()) + 32767) >> 16; + pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; + + pDvdVideoPicture->pts = pIMXBuffer->GetPts(); +@@ -1185,13 +1186,13 @@ CDVDVideoCodecIMXBuffer::CDVDVideoCodecIMXBuffer(VpuDecOutFrameInfo *frameInfo, + , m_iFlags(DVP_FLAG_DROPPED) + , m_convBuffer(nullptr) + { +- +- m_pctWidth = frameInfo->pExtInfo->FrmCropRect.nRight - frameInfo->pExtInfo->FrmCropRect.nLeft; +- m_pctHeight = frameInfo->pExtInfo->FrmCropRect.nBottom - frameInfo->pExtInfo->FrmCropRect.nTop; +- iWidth = frameInfo->pExtInfo->nFrmWidth; +- iHeight = frameInfo->pExtInfo->nFrmHeight; +- pVirtAddr = m_frameBuffer->pbufVirtY; +- pPhysAddr = (uint32_t)m_frameBuffer->pbufY; ++ m_pctWidth = frameInfo->pExtInfo->FrmCropRect.nRight - frameInfo->pExtInfo->FrmCropRect.nLeft; ++ m_pctHeight = frameInfo->pExtInfo->FrmCropRect.nBottom - frameInfo->pExtInfo->FrmCropRect.nTop; ++ m_widthHeightRatio = frameInfo->pExtInfo->nQ16ShiftWidthDivHeightRatio; ++ iWidth = frameInfo->pExtInfo->nFrmWidth; ++ iHeight = frameInfo->pExtInfo->nFrmHeight; ++ pVirtAddr = m_frameBuffer->pbufVirtY; ++ pPhysAddr = (uint32_t)m_frameBuffer->pbufY; + + #ifdef IMX_INPUT_FORMAT_I420 + iFormat = _4CC('I', '4', '2', '0'); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 2168e00..22b34d7 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -268,12 +268,14 @@ public: + + unsigned int GetPictureWidth() { return m_pctWidth; } + unsigned int GetPictureHeight() { return m_pctHeight; } ++ int GetWidthHeightRatio() { return m_widthHeightRatio; } + + void SetConvBuffer(struct g2d_buf *b) { m_convBuffer = b; } + + private: + unsigned int m_pctWidth; + unsigned int m_pctHeight; ++ int m_widthHeightRatio; + + double m_pts; + double m_dts; +@@ -378,7 +380,6 @@ protected: + std::unordered_map + m_pts; + double m_lastPTS; +- VpuDecOutFrameInfo m_frameInfo; // Store last VPU output frame info + CBitstreamConverter *m_converter; // H264 annex B converter + bool m_warnOnce; // Track warning messages to only warn once + int m_codecControlFlags; +-- +1.9.1 + + +============================================================== +file 0050-Change-mediainfo-logging.patch +============================================================== + +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2016-10-02 11:49:42.415297936 +0200 ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2016-10-02 11:50:57.875301018 +0200 +@@ -504,8 +504,6 @@ + } + + m_hints = hints; +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "Let's decode with iMX VPU\n"); + + int param = 0; + SetVPUParams(VPU_DEC_CONF_INPUTTYPE, ¶m); +@@ -514,32 +512,31 @@ + #ifdef MEDIAINFO + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: fpsrate %d / fpsscale %d\n", m_hints.fpsrate, m_hints.fpsscale); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: CodecID %d \n", m_hints.codec); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: StreamType %d \n", m_hints.type); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Level %d \n", m_hints.level); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Profile %d \n", m_hints.profile); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: PTS_invalid %d \n", m_hints.ptsinvalid); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Tag %d \n", m_hints.codec_tag); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: %dx%d \n", m_hints.width, m_hints.height); +- } +- { char str_tag[128]; av_get_codec_tag_string(str_tag, sizeof(str_tag), m_hints.codec_tag); +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: Tag fourcc %s\n", str_tag); +- } +- if (m_hints.extrasize) +- { +- char buf[4096]; ++ CLog::Log(LOGNOTICE, "MEDIAINFO: fpsrate %d / fpsscale %d\n", m_hints.fpsrate, m_hints.fpsscale); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: CodecID %d\n", m_hints.codec); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: StreamType %d\n", m_hints.type); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: Level %d\n", m_hints.level); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: Profile %d\n", m_hints.profile); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: PTS_invalid %d\n", m_hints.ptsinvalid); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: Tag %d\n", m_hints.codec_tag); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: %dx%d\n", m_hints.width, m_hints.height); ++ ++ char str_tag[128]; ++ av_get_codec_tag_string(str_tag, sizeof(str_tag), m_hints.codec_tag); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: Tag fourcc %s\n", str_tag); ++ ++ if (m_hints.extrasize) ++ { ++ char buf[4096]; + +- for (unsigned int i=0; i < m_hints.extrasize; i++) +- sprintf(buf+i*2, "%02x", ((uint8_t*)m_hints.extradata)[i]); ++ for (unsigned int i=0; i < m_hints.extrasize; i++) ++ sprintf(buf+i*2, "%02x", ((uint8_t*)m_hints.extradata)[i]); + +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: %s extradata %d %s\n", *(char*)m_hints.extradata == 1 ? "AnnexB" : "avcC", m_hints.extrasize, buf); +- } +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- { +- CLog::Log(LOGDEBUG, "Decode: MEDIAINFO: %d / %d \n", m_hints.width, m_hints.height); +- CLog::Log(LOGDEBUG, "Decode: aspect %f - forced aspect %d\n", m_hints.aspect, m_hints.forced_aspect); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: %s extradata %d %s\n", *(char*)m_hints.extradata == 1 ? "AnnexB" : "avcC", m_hints.extrasize, buf); ++ } ++ ++ CLog::Log(LOGNOTICE, "MEDIAINFO: %d / %d\n", m_hints.width, m_hints.height); ++ CLog::Log(LOGNOTICE, "MEDIAINFO: aspect %f - forced_aspect %d\n", m_hints.aspect, m_hints.forced_aspect); + } + #endif + +@@ -624,6 +621,9 @@ + return false; + } + ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGNOTICE, "Let's decode with iMX VPU\n"); ++ + std::list deintMethods({ EINTERLACEMETHOD::VS_INTERLACEMETHOD_AUTO, + EINTERLACEMETHOD::VS_INTERLACEMETHOD_RENDER_BOB }); + + +============================================================== +file 400-Boost-Center-Audio-Channel-on-Downmixing.patch +============================================================== + +commit a509bdf1ed001423cad530c2f230937825ff2254 +Author: WRXTASY +Date: Tue Aug 18 09:40:19 2015 +0800 + + Boost Center Audio Channel on Downmixing + +diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po +index faf423c..cf123fe 100644 +--- a/addons/resource.language.en_gb/resources/strings.po ++++ b/addons/resource.language.en_gb/resources/strings.po +@@ -18893,6 +18893,21 @@ msgstr "" + + #empty strings from id 37046 to 38009 + ++#: system/settings/settings.xml ++msgctxt "#38007" ++msgid "Boost centre channel when downmixing" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38008" ++msgid "Increase this value to make the dialogue louder compared to background sounds when downmixing multichannel audio" ++msgstr "" ++ ++#: system/settings/settings.xml ++msgctxt "#38009" ++msgid "%i dB" ++msgstr "" ++ + #: system/settings/rbp.xml + msgctxt "#38010" + msgid "GPU accelerated" +diff --git a/system/settings/settings.xml b/system/settings/settings.xml +index 3ef33e0..44a9036 100644 +--- a/system/settings/settings.xml ++++ b/system/settings/settings.xml +@@ -2040,6 +2040,18 @@ + + + ++ ++ 2 ++ 0 ++ ++ 0 ++ 1 ++ 30 ++ ++ ++ 38009 ++ ++ + + HAS_AE_QUALITY_LEVELS + 2 +diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +index e4ddf9e..34d0152 100644 +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +@@ -20,6 +20,7 @@ + + #include "cores/AudioEngine/Utils/AEUtil.h" + #include "ActiveAEResampleFFMPEG.h" ++#include "settings/Settings.h" + #include "utils/log.h" + + extern "C" { +@@ -104,6 +105,12 @@ bool CActiveAEResampleFFMPEG::Init(uint64_t dst_chan_layout, int dst_channels, i + { + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0); + } ++ int boost_center = CSettings::GetInstance().GetInt("audiooutput.boostcenter"); ++ if (boost_center) ++ { ++ float gain = pow(10.0f, ((float)(-3 + boost_center))/20.0f); ++ av_opt_set_double(m_pContext, "center_mix_level", gain, 0); ++ } + + if (remapLayout) + { + +============================================================== +file 52-imx-enable-forced-aspect-ratio.patch +============================================================== + +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2016-08-15 21:22:26.222137237 +0200 ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2016-08-15 21:22:26.246137238 +0200 +@@ -385,6 +385,7 @@ + int m_speed; + CCriticalSection m_signalLock; + CCriticalSection m_queuesLock; ++ int m_forcedWidthDivHeightRatio; + #ifdef DUMP_STREAM + FILE *m_dump; + #endif +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2016-08-15 21:27:17.166149119 +0200 ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp 2016-08-15 21:27:17.190149120 +0200 +@@ -541,6 +541,8 @@ + #endif + + m_warnOnce = true; ++ m_forcedWidthDivHeightRatio = m_hints.forced_aspect ? (65536 * m_hints.aspect) : 0; ++ + switch(m_hints.codec) + { + case AV_CODEC_ID_MPEG1VIDEO: +@@ -1154,7 +1156,9 @@ + pDvdVideoPicture->iWidth = pIMXBuffer->GetPictureWidth(); + pDvdVideoPicture->iHeight = pIMXBuffer->GetPictureHeight(); + +- pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * pIMXBuffer->GetWidthHeightRatio()) + 32767) >> 16; ++ int ratio = m_forcedWidthDivHeightRatio ? m_forcedWidthDivHeightRatio : pIMXBuffer->GetWidthHeightRatio(); ++ ++ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * ratio) + 32767) >> 16; + pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; + + pDvdVideoPicture->pts = pIMXBuffer->GetPts(); + +============================================================== +file 53-imx-fix-edid-readout.patch +============================================================== + +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2016-09-25 15:18:47.780677140 +0200 ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2016-09-25 15:18:47.808677141 +0200 +@@ -336,67 +336,55 @@ + float CEGLNativeTypeIMX::GetMonitorSAR() + { + FILE *f_edid; +- char *str = NULL; +- unsigned char p; +- size_t n; +- int done = 0; ++ int len; + + // kernels <= 3.18 use ./soc0/soc.1 in official imx kernel + // kernels > 3.18 use ./soc0/soc + f_edid = fopen("/sys/devices/soc0/soc/20e0000.hdmi_video/edid", "r"); + if(!f_edid) + f_edid = fopen("/sys/devices/soc0/soc.1/20e0000.hdmi_video/edid", "r"); ++ if(!f_edid) ++ f_edid = fopen("/sys/devices/soc0/soc.0/20e0000.hdmi_video/edid", "r"); + + if(!f_edid) + return 0; + ++ len = fread(m_edid, 1, EDID_MAXSIZE, f_edid); ++ if (len < 128) ++ { ++ fclose(f_edid); ++ return 0; ++ } ++ + // first check if EDID is in binary format by reading 512bytes, compare 1st 8bytes + // against EDID 1.4 identificator [0x0,0xff,0xff,0xff,0xff,0xff,0xff,0x0] + // if no match, seek to 0 input file and continue with previous method. +- if (((done = fread(m_edid, 1, EDID_MAXSIZE, f_edid)) % 128) == 0 && done) +- if (!memcmp(m_edid, EDID_HEADER, EDID_HEADERSIZE)) +- { +- fclose(f_edid); +- return true; +- } +- +- done = 0; +- memset(m_edid, 0, EDID_MAXSIZE); +- fseek(f_edid, 0L, SEEK_SET); +- // we need to convert mxc_hdmi output format to binary array +- // mxc_hdmi provides the EDID as space delimited 1bytes blocks +- // exported as text with format specifier %x eg: +- // 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x4C 0x2D 0x7A 0x0A 0x00 0x00 0x00 0x00 +- // +- // this translates into the inner cycle where we move pointer first +- // with +2 to skip '0x', +- // we sscanf actual data (eg FF) into a byte, +- // we move over the FF and delimiting space with +3 +- // +- // this parses whole 512 byte long info into internal binary array for future +- // reference and use. current use is only to grab screen's physical params +- // at EGL init. +- while(getline(&str, &n, f_edid) > 0) ++ if (memcmp(m_edid, EDID_HEADER, EDID_HEADERSIZE) != 0) + { +- char *c = str; +- while(*c != '\n' && done < EDID_MAXSIZE) +- { +- c += 2; +- sscanf(c, "%hhx", &p); +- m_edid[done++] = p; +- c += 3; +- } +- if (str) +- free(str); +- str = NULL; ++ // we need to convert mxc_hdmi output format to binary array ++ // mxc_hdmi provides the EDID as space delimited 1bytes blocks ++ // exported as text with format specifier %x eg: ++ // 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x4C 0x2D 0x7A 0x0A 0x00 0x00 0x00 0x00 ++ // ++ // this parses whole 512 byte long info into internal binary array for future ++ // reference and use. current use is only to grab screen's physical params ++ // at EGL init. ++ len = 0; ++ fseek(f_edid, 0, SEEK_SET); ++ while (len < EDID_MAXSIZE && fscanf(f_edid, " 0x%2hhx", m_edid + len) == 1) ++ len++; + } ++ ++ if (len < EDID_MAXSIZE) ++ memset(m_edid + len, 0, EDID_MAXSIZE - len); ++ + fclose(f_edid); + + // info related to 'Basic display parameters.' is at offset 0x14-0x18. + // where W is 2nd byte, H 3rd. +- int cmWidth = (int)*(m_edid +EDID_STRUCT_DISPLAY +1); +- int cmHeight = (int)*(m_edid +EDID_STRUCT_DISPLAY +2); +- if (cmHeight > 0) ++ int cmWidth = m_edid[EDID_STRUCT_DISPLAY + 1]; ++ int cmHeight = m_edid[EDID_STRUCT_DISPLAY + 2]; ++ if (cmHeight > 0 && cmWidth > 0) + { + float t_sar = (float) cmWidth / cmHeight; + if (t_sar >= 0.33 && t_sar <= 3.0) + +============================================================== +file 55-cec-power-button.diff +============================================================== + +--- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp 2015-10-17 10:00:03.704969969 +0200 ++++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp 2015-10-17 10:00:03.724969970 +0200 +@@ -908,8 +908,14 @@ + case CEC_USER_CONTROL_CODE_POWER: + case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION: + case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION: +- xbmcKey.iButton = XINPUT_IR_REMOTE_POWER; +- PushCecKeypress(xbmcKey); ++ // Instead of translating to XINPUT_IR_REMOTE_POWER key, we simulate ++ // CEC_OPCODE_STANDBY to avoid unconditional shutdown with some TVs. ++ { ++ cec_command command; ++ command.opcode = CEC_OPCODE_STANDBY; ++ command.initiator = CECDEVICE_TV; ++ CecCommand(this, command); ++ } + break; + case CEC_USER_CONTROL_CODE_VOLUME_UP: + xbmcKey.iButton = XINPUT_IR_REMOTE_VOLUME_PLUS; + +============================================================== +file 58-kodi-fractional-rates.diff +============================================================== + +--- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2015-12-21 17:45:47.575690959 +0100 ++++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2015-12-21 17:45:47.615712478 +0100 +@@ -434,7 +434,12 @@ + res->iHeight= h; + res->iScreenWidth = w; + res->iScreenHeight= h; +- res->fRefreshRate = r; ++ ++ if(r == 23 || (r % 10) == 9) ++ res->fRefreshRate = (float)((r + 1) * 1000) / 1001; ++ else ++ res->fRefreshRate = r; ++ + res->dwFlags = p[0] == 'p' ? D3DPRESENTFLAG_PROGRESSIVE : D3DPRESENTFLAG_INTERLACED; + + res->iScreen = 0; + +============================================================== +file 59-kodi-cache-embedded-thumbnails.diff +============================================================== + +--- a/xbmc/music/MusicThumbLoader.cpp 2016-01-31 15:03:34.251330287 +0100 ++++ b/xbmc/music/MusicThumbLoader.cpp 2016-01-31 15:03:34.275330288 +0100 +@@ -153,8 +153,11 @@ + + if (!pItem->HasArt("thumb")) + { ++ EmbeddedArt ea; ++ + // Look for embedded art +- if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetCoverArtInfo().empty()) ++ if (pItem->HasMusicInfoTag() && ++ (!pItem->GetMusicInfoTag()->GetCoverArtInfo().empty() || GetEmbeddedThumb(pItem->GetPath(), ea))) + { + // The item has got embedded art but user thumbs overrule, so check for those first + if (!FillThumb(*pItem, false)) // Check for user thumbs but ignore folder thumbs +@@ -162,6 +165,7 @@ + // No user thumb, use embedded art + std::string thumb = CTextureUtils::GetWrappedImageURL(pItem->GetPath(), "music"); + pItem->SetArt("thumb", thumb); ++ SetCachedImage(*pItem, "thumb", thumb); + } + } + else + +============================================================== +file 60-kodi-accumulate-data-for-visualisation.diff +============================================================== + +--- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp 2015-10-19 08:31:15.000000000 +0200 ++++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp 2016-02-07 18:32:00.431735589 +0100 +@@ -1315,15 +1315,19 @@ + if (!m_vizBuffers && !m_audioCallback.empty()) + { + AEAudioFormat vizFormat = m_internalFormat; +- vizFormat.m_channelLayout = AE_CH_LAYOUT_2_0; +- vizFormat.m_dataFormat = AE_FMT_FLOAT; +- vizFormat.m_sampleRate = 44100; ++ ++ // accumulate samples for the visualization addon ++ if (vizFormat.m_frames < 1536) ++ vizFormat.m_frames = 1536; + + // input buffers +- m_vizBuffersInput = new CActiveAEBufferPool(m_internalFormat); ++ m_vizBuffersInput = new CActiveAEBufferPool(vizFormat); + m_vizBuffersInput->Create(2000); + + // resample buffers ++ vizFormat.m_channelLayout = AE_CH_LAYOUT_2_0; ++ vizFormat.m_dataFormat = AE_FMT_FLOAT; ++ vizFormat.m_sampleRate = 44100; + m_vizBuffers = new CActiveAEBufferPoolResample(m_internalFormat, vizFormat, m_settings.resampleQuality); + //! @todo use cache of sync + water level + m_vizBuffers->Create(2000, false, false); +@@ -2147,18 +2151,33 @@ + m_vizInitialized = true; + } + ++ const int vizNumSamples = 512; // !!! Hack: This should be AUDIO_BUFFER_SIZE (addons/Visualization.h) + if (!m_vizBuffersInput->m_freeSamples.empty()) + { +- // copy the samples into the viz input buffer +- CSampleBuffer *viz = m_vizBuffersInput->GetFreeBuffer(); +- int samples = out->pkt->nb_samples; +- int bytes = samples * out->pkt->config.channels / out->pkt->planes * out->pkt->bytes_per_sample; +- for(int i= 0; i < out->pkt->planes; i++) ++ // copy the samples into the viz input buffer ++ CSampleBuffer *viz = m_vizBuffersInput->m_freeSamples.front(); ++ int samples = std::min(vizNumSamples - viz->pkt->nb_samples, out->pkt->nb_samples); ++ ++ // don't copy more than vizNumSamples ++ if (samples > 0) + { +- memcpy(viz->pkt->data[i], out->pkt->data[i], bytes); ++ int bytes = samples * out->pkt->config.channels / out->pkt->planes * out->pkt->bytes_per_sample; ++ int offset = viz->pkt->nb_samples * out->pkt->config.channels / out->pkt->planes * out->pkt->bytes_per_sample; ++ for(int i = 0; i < out->pkt->planes; i++) ++ memcpy(viz->pkt->data[i] + offset, out->pkt->data[i], bytes); ++ } ++ ++ // consume complete source packet ++ viz->pkt->nb_samples += out->pkt->nb_samples; ++ if (viz->pkt->nb_samples >= viz->pkt->max_nb_samples) ++ { ++ // set valid sample count ++ viz->pkt->nb_samples = vizNumSamples; ++ ++ m_vizBuffersInput->m_freeSamples.pop_front(); ++ viz->refCount = 1; ++ m_vizBuffers->m_inputSamples.push_back(viz); + } +- viz->pkt->nb_samples = samples; +- m_vizBuffers->m_inputSamples.push_back(viz); + } + else + CLog::Log(LOGWARNING,"ActiveAE::%s - viz ran out of free buffers", __FUNCTION__); +@@ -2183,7 +2202,12 @@ + } + } + else if (m_vizBuffers) ++ { ++ if (!m_vizBuffersInput->m_freeSamples.empty()) ++ m_vizBuffersInput->m_freeSamples.front()->pkt->nb_samples = 0; ++ + m_vizBuffers->Flush(); ++ } + } + + // mix gui sounds + +============================================================== +file 65-fix-cec-dialog-text.diff +============================================================== + +--- a/addons/resource.language.en_gb/resources/strings.po 2016-08-06 13:03:04.169879835 +0200 ++++ b/addons/resource.language.en_gb/resources/strings.po 2016-08-06 13:03:04.197879836 +0200 +@@ -16235,7 +16235,7 @@ + + #: system/peripherals.xml + msgctxt "#36026" +-msgid "Devices to also put in standby mode" ++msgid "Switch off the TV when the PC goes to standby" + msgstr "" + + #: xbmc/peripherals/devices/PeripheralCecAdapter.cpp + +============================================================== +file 66-fix-buffering-indicator.diff +============================================================== + +--- a/xbmc/video/windows/GUIWindowFullScreen.cpp 2016-10-01 14:30:58.000000000 +0200 ++++ b/xbmc/video/windows/GUIWindowFullScreen.cpp 2016-10-01 20:02:57.037598834 +0200 +@@ -485,14 +485,16 @@ + + void CGUIWindowFullScreen::Process(unsigned int currentTime, CDirtyRegionList &dirtyregion) + { +- if (g_application.m_pPlayer->IsRenderingGuiLayer()) +- MarkDirtyRegion(); ++ unsigned int oldDirty = dirtyregion.size(); + + CGUIWindow::Process(currentTime, dirtyregion); + + //! @todo This isn't quite optimal - ideally we'd only be dirtying up the actual video render rect + //! which is probably the job of the renderer as it can more easily track resizing etc. + m_renderRegion.SetRect(0, 0, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()); ++ ++ if (dirtyregion.size() != oldDirty || g_application.m_pPlayer->IsRenderingGuiLayer()) ++ dirtyregion.push_back(m_renderRegion); + } + + void CGUIWindowFullScreen::Render() diff --git a/projects/imx6/patches/kodi/kodi-100-master-fixes.patch b/projects/imx6/patches/kodi/kodi-100-master-fixes.patch index 9bf0023ad3..4784ddc18d 100644 --- a/projects/imx6/patches/kodi/kodi-100-master-fixes.patch +++ b/projects/imx6/patches/kodi/kodi-100-master-fixes.patch @@ -1,52 +1,114 @@ -diff -aurNp a/xbmc/linux/imx/IMX.cpp b/xbmc/linux/imx/IMX.cpp ---- a/xbmc/linux/imx/IMX.cpp 2016-08-21 23:42:23.000000000 +0200 -+++ b/xbmc/linux/imx/IMX.cpp 2016-09-02 12:51:09.516633817 +0200 -@@ -198,11 +198,6 @@ bool CIMXFps::Recalc() +--- a/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp 2016-10-07 09:41:03.067310207 +0200 ++++ b/xbmc/powermanagement/linux/LogindUPowerSyscall.cpp 2016-10-07 09:41:27.658371366 +0200 +@@ -52,8 +52,8 @@ CLogindUPowerSyscall::CLogindUPowerSysca - double frameNorm = CDVDCodecUtils::NormalizeFrameduration(frameDuration, &hasMatch); + m_canPowerdown = LogindCheckCapability("CanPowerOff"); + m_canReboot = LogindCheckCapability("CanReboot"); +- m_canHibernate = LogindCheckCapability("CanHibernate"); +- m_canSuspend = LogindCheckCapability("CanSuspend"); ++ m_canHibernate = false; ++ m_canSuspend = false; -- if (hasMatch && !patternLength) -- m_patternLength = 1; -- else -- m_patternLength = patternLength; -- - if (!m_hasPattern && hasMatch) - m_frameDuration = frameNorm; + InhibitDelayLock(); + +--- a/xbmc/powermanagement/linux/UPowerSyscall.cpp.orig 2016-10-07 10:01:18.236917326 +0200 ++++ b/xbmc/powermanagement/linux/UPowerSyscall.cpp 2016-10-07 10:01:46.311845478 +0200 +@@ -262,8 +262,8 @@ bool CUPowerSyscall::PumpPowerEvents(IPo + + void CUPowerSyscall::UpdateCapabilities() + { +- m_CanSuspend = CDBusUtil::GetVariant("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "CanSuspend").asBoolean(false); +- m_CanHibernate = CDBusUtil::GetVariant("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower", "CanHibernate").asBoolean(false); ++ m_CanSuspend = false; ++ m_CanHibernate = false; + } -diff -aurNp a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp ---- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2016-08-21 23:42:23.000000000 +0200 -+++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp 2016-09-02 12:42:54.443140655 +0200 -@@ -29,6 +29,7 @@ - #include - #ifdef HAS_IMXVPU - #include -+#include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h" #endif - #include "utils/log.h" - #include "utils/RegExp.h" ---- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2016-09-04 18:08:27.249816157 +0200 -+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h 2016-09-04 18:09:16.803892804 +0200 -@@ -55,9 +55,9 @@ - // priorities to those subsystems can result in a very different user - // experience. With that setting enabled we can build some statistics, - // as numbers are always better than "feelings" --#define IMX_PROFILE_BUFFERS -+//#define IMX_PROFILE_BUFFERS + +From aa2b510f1ab61c8989fe41f23c2704facb962d50 Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Sat, 28 Mar 2015 23:30:03 +0100 +Subject: [PATCH] Add CEC IMX adapter as known type and set no polling. - that + eliminates extensive periodic /sys walkthrough + +Upstream-commit: f7ba60b4e94091a007fd656bc0084b600a12eb17 +--- + xbmc/peripherals/PeripheralTypes.h | 6 ++++++ + xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp | 4 ++++ + 2 files changed, 10 insertions(+) + +diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h +index 565de4b..e2f2805 100644 +--- a/xbmc/peripherals/PeripheralTypes.h ++++ b/xbmc/peripherals/PeripheralTypes.h +@@ -40,11 +40,13 @@ namespace PERIPHERALS + PERIPHERAL_BUS_USB, + PERIPHERAL_BUS_PCI, + PERIPHERAL_BUS_RPI, ++ PERIPHERAL_BUS_IMX, + PERIPHERAL_BUS_CEC, + PERIPHERAL_BUS_ADDON, + #ifdef TARGET_ANDROID + PERIPHERAL_BUS_ANDROID, + #endif ++ //PERIPHERAL_BUS_CEC + }; --#define IMX_PROFILE -+//#define IMX_PROFILE - //#define TRACE_FRAMES + enum PeripheralFeature +@@ -169,6 +171,8 @@ namespace PERIPHERALS + return "pci"; + case PERIPHERAL_BUS_RPI: + return "rpi"; ++ case PERIPHERAL_BUS_IMX: ++ return "imx"; + case PERIPHERAL_BUS_CEC: + return "cec"; + case PERIPHERAL_BUS_ADDON: +@@ -193,6 +197,8 @@ namespace PERIPHERALS + return PERIPHERAL_BUS_PCI; + else if (strTypeLowerCase == "rpi") + return PERIPHERAL_BUS_RPI; ++ else if (strTypeLowerCase == "imx") ++ return PERIPHERAL_BUS_IMX; + else if (strTypeLowerCase == "cec") + return PERIPHERAL_BUS_CEC; + else if (strTypeLowerCase == "addon") +diff --git a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp +index b04fe00..3dc3d0e 100644 +--- a/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp ++++ b/xbmc/peripherals/bus/virtual/PeripheralBusCEC.cpp +@@ -102,6 +102,10 @@ bool CPeripheralBusCEC::PerformDeviceScan(PeripheralScanResults &results) + /** the Pi's adapter cannot be removed, no need to rescan */ + m_bNeedsPolling = false; + break; ++ case ADAPTERTYPE_IMX: ++ result.m_mappedBusType = PERIPHERAL_BUS_IMX; ++ m_bNeedsPolling = false; ++ break; + default: + break; + } + +From 07ae05827ef197fae42a6e849a816a38ffa3bf0d Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Sat, 8 Oct 2016 17:23:32 +0200 +Subject: [PATCH 20/20] [CodecIMX] fix a xvid-type media playback - starting + with green screen + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index f692482..50ff805 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -974,7 +974,7 @@ void CIMXCodec::Process() + m_decInput.setquotasize(m_fps); - #define RENDER_USE_G2D 0 -diff -aurNp a/system/peripherals.xml b/system/peripherals.xml ---- a/system/peripherals.xml 2016-09-07 16:50:55.725114234 +0200 -+++ b/system/peripherals.xml 2016-09-07 16:51:13.472432981 +0200 -@@ -16,7 +16,7 @@ - - - -- -+ - - - + bool getFrame = m_decOpenParam.CodecFormat != VPU_V_AVC || !m_converter; +- getFrame &= m_decOpenParam.CodecFormat != VPU_V_MPEG2; ++ getFrame &= m_decOpenParam.CodecFormat != VPU_V_MPEG2 && m_decOpenParam.CodecFormat != VPU_V_XVID; + if (getFrame || m_decRet & VPU_DEC_RESOLUTION_CHANGED) + { + SetDrainMode((VpuDecInputType)IN_DECODER_SET); diff --git a/projects/imx6/patches/linux/3.14-mx6-sr/linux-800-from-openbricks.patch b/projects/imx6/patches/linux/3.14-mx6-sr/linux-800-from-openbricks.patch new file mode 100644 index 0000000000..58d8fea88e --- /dev/null +++ b/projects/imx6/patches/linux/3.14-mx6-sr/linux-800-from-openbricks.patch @@ -0,0 +1,1880 @@ +https://github.com/OpenBricks/openbricks/tree/krypton-glibc +https://github.com/OpenBricks/openbricks/tree/krypton-glibc/config/platforms/arm/imx6/machines/cuboxi/packages/linux/patches +https://github.com/OpenBricks/openbricks/tree/32da31689ba04a94d1a08bfc04f69d6c1a3c848a/config/platforms/arm/imx6/machines/cuboxi/packages/linux/patches + +============================================================== +file 0004-Dumb_adapter.patch +============================================================== + +commit c466ada304c10af850daaef8b232e0e818bfb6d7 +Author: wolfgar +Date: Sat Sep 13 02:08:32 2014 +0200 + + Remove embedded logics from the driver so that libcec is responsible for + all this work + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index c30237e..fb66c25 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -123,7 +123,7 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + + void mxc_hdmi_cec_handle(u16 cec_stat) + { +- u8 val = 0, i = 0; ++ u8 i = 0; + struct hdmi_cec_event *event = NULL; + /*The current transmission is successful (for initiator only).*/ + if (!open_count) +@@ -158,27 +158,14 @@ void mxc_hdmi_cec_handle(u16 cec_stat) + } + /*An error is detected on cec line (for initiator only). */ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) { +- mutex_lock(&hdmi_cec_data.lock); +- hdmi_cec_data.send_error++; +- if (hdmi_cec_data.send_error > 2) { +- pr_err("%s:Re-transmission is attempted more than 2 times!\n", __func__); +- hdmi_cec_data.send_error = 0; +- mutex_unlock(&hdmi_cec_data.lock); +- hdmi_cec_data.tx_answer = cec_stat; +- wake_up(&tx_cec_queue); +- return; +- } +- for (i = 0; i < hdmi_cec_data.msg_len; i++) +- hdmi_writeb(hdmi_cec_data.last_msg[i], HDMI_CEC_TX_DATA0+i); +- hdmi_writeb(hdmi_cec_data.msg_len, HDMI_CEC_TX_CNT); +- val = hdmi_readb(HDMI_CEC_CTRL); +- val |= 0x01; +- hdmi_writeb(val, HDMI_CEC_CTRL); +- mutex_unlock(&hdmi_cec_data.lock); ++ hdmi_cec_data.tx_answer = cec_stat; ++ wake_up(&tx_cec_queue); ++ return; + } + /*A frame is not acknowledged in a directly addressed message. Or a frame is negatively acknowledged in + a broadcast message (for initiator only).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_NACK) { ++ hdmi_cec_data.send_error++; + hdmi_cec_data.tx_answer = cec_stat; + wake_up(&tx_cec_queue); + } +@@ -392,7 +379,7 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + u_long arg) + { + int ret = 0, status = 0; +- u8 val = 0, msg = 0; ++ u8 val = 0; + struct mxc_edid_cfg hdmi_edid_cfg; + pr_debug("function : %s\n", __func__); + if (!open_count) +@@ -416,15 +403,6 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + hdmi_writeb(0, HDMI_CEC_ADDR_L); + } else + ret = -EINVAL; +- /*Send Polling message with same source and destination address*/ +- if (0 == ret && 15 != hdmi_cec_data.Logical_address) { +- msg = (hdmi_cec_data.Logical_address << 4)|hdmi_cec_data.Logical_address; +- hdmi_writeb(1, HDMI_CEC_TX_CNT); +- hdmi_writeb(msg, HDMI_CEC_TX_DATA0); +- val = hdmi_readb(HDMI_CEC_CTRL); +- val |= 0x01; +- hdmi_writeb(val, HDMI_CEC_CTRL); +- } + mutex_unlock(&hdmi_cec_data.lock); + break; + case HDMICEC_IOC_STARTDEVICE: + +============================================================== +file 0005-assign-minor-to-vhci.patch +============================================================== + +From 27b8b64082db6cdfda751e81e56c0f668053834b Mon Sep 17 00:00:00 2001 +From: Lucas De Marchi +Date: Tue, 18 Feb 2014 02:19:26 -0300 +Subject: [PATCH] Bluetooth: allocate static minor for vhci + +Commit bfacbb9 (Bluetooth: Use devname:vhci module alias for virtual HCI +driver) added the module alias to hci_vhci module so it's possible to +create the /dev/vhci node. However creating an alias without +specifying the minor doesn't allow us to create the node ahead, +triggerring module auto-load when it's first accessed. + +Starting with depmod from kmod 16 we started to warn if there's a +devname alias without specifying the major and minor. + +Let's do the same done for uhid, kvm, fuse and others, specifying a +fixed minor. In systems with systemd as the init the following will +happen: on early boot systemd will call "kmod static-nodes" to read +/lib/modules/$(uname -r)/modules.devname and then create the nodes. When +first accessed these "dead" nodes will trigger the module loading. + +Signed-off-by: Lucas De Marchi +Acked-by: Greg Kroah-Hartman +Signed-off-by: Marcel Holtmann +--- + Documentation/devices.txt | 1 + + drivers/bluetooth/hci_vhci.c | 3 ++- + include/linux/miscdevice.h | 1 + + 3 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devices.txt b/Documentation/devices.txt +index 10378cc..04356f5 100644 +--- a/Documentation/devices.txt ++++ b/Documentation/devices.txt +@@ -353,6 +353,7 @@ Your cooperation is appreciated. + 133 = /dev/exttrp External device trap + 134 = /dev/apm_bios Advanced Power Management BIOS + 135 = /dev/rtc Real Time Clock ++ 137 = /dev/vhci Bluetooth virtual HCI driver + 139 = /dev/openprom SPARC OpenBoot PROM + 140 = /dev/relay8 Berkshire Products Octal relay card + 141 = /dev/relay16 Berkshire Products ISO-16 relay card +diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c +index 1ef6990..add1c6a 100644 +--- a/drivers/bluetooth/hci_vhci.c ++++ b/drivers/bluetooth/hci_vhci.c +@@ -359,7 +359,7 @@ static const struct file_operations vhci_fops = { + static struct miscdevice vhci_miscdev= { + .name = "vhci", + .fops = &vhci_fops, +- .minor = MISC_DYNAMIC_MINOR, ++ .minor = VHCI_MINOR, + }; + + static int __init vhci_init(void) +@@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); + MODULE_VERSION(VERSION); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("devname:vhci"); ++MODULE_ALIAS_MISCDEV(VHCI_MINOR); +diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h +index 3737f72..7bb6148 100644 +--- a/include/linux/miscdevice.h ++++ b/include/linux/miscdevice.h +@@ -23,6 +23,7 @@ + #define TEMP_MINOR 131 /* Temperature Sensor */ + #define RTC_MINOR 135 + #define EFI_RTC_MINOR 136 /* EFI Time services */ ++#define VHCI_MINOR 137 + #define SUN_OPENPROM_MINOR 139 + #define DMAPI_MINOR 140 /* DMAPI */ + #define NVRAM_MINOR 144 + +============================================================== +file 1100-ARM-Avoid-crash-on-power-off-and-reduce-power-consum.patch +============================================================== + +From 7a4bc357a0d2477c0dcdf2a1c471e57050dec041 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sat, 20 Sep 2014 14:05:50 +0200 +Subject: [PATCH] ARM: Avoid crash on power off and reduce power consumption + in 'halt' state. + +Signed-off-by: Rudi +--- + arch/arm/kernel/process.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 1bdd78b..70655b9 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -119,6 +119,17 @@ static void null_restart(enum reboot_mode reboot_mode, const char *cmd) + } + + /* ++ * Enter non-interruptable CPU halt state ++ */ ++static void cpu_halt(void) ++{ ++ local_irq_disable(); ++ ++ while (1) ++ cpu_do_idle(); ++} ++ ++/* + * Function pointers to optional machine specific functions + */ + void (*pm_power_off)(void); +@@ -202,8 +213,7 @@ void machine_halt(void) + local_irq_disable(); + smp_send_stop(); + +- local_irq_disable(); +- while (1); ++ cpu_halt(); + } + + /* +@@ -219,6 +229,8 @@ void machine_power_off(void) + + if (pm_power_off) + pm_power_off(); ++ ++ cpu_halt(); + } + + /* +@@ -244,8 +256,7 @@ void machine_restart(char *cmd) + + /* Whoops - the platform was unable to reboot. Tell the user! */ + printk("Reboot failed -- System halted\n"); +- local_irq_disable(); +- while (1); ++ cpu_halt(); + } + + void __show_regs(struct pt_regs *regs) +-- +1.7.9.5 + + +============================================================== +file 1101-ARM-Disable-timer-events-before-entering-halt-state.patch +============================================================== + +From ae0f301a11bb9d5e484d48238cf15082928a7241 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Sun, 21 Sep 2014 13:53:21 +0200 +Subject: [PATCH] ARM: Disable timer events before entering `halt' state. + +Signed-off-by: Rudi +--- + arch/arm/kernel/process.c | 3 ++- + arch/arm/mach-imx/time.c | 11 +++++++++++ + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 70655b9..d1e4763 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -123,8 +123,9 @@ static void null_restart(enum reboot_mode reboot_mode, const char *cmd) + */ + static void cpu_halt(void) + { ++ clockevents_suspend(); ++ + local_irq_disable(); +- + while (1) + cpu_do_idle(); + } +diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c +index ae61dfd..75afcf9 100644 +--- a/arch/arm/mach-imx/time.c ++++ b/arch/arm/mach-imx/time.c +@@ -232,6 +232,16 @@ static void mxc_set_mode(enum clock_event_mode mode, + } + } + ++ ++/* ++ * Shutdown timer ++ */ ++static void mxc_suspend(struct clock_event_device *evt) ++{ ++ mxc_set_mode(CLOCK_EVT_MODE_SHUTDOWN, evt); ++} ++ ++ + /* + * IRQ handler for the timer + */ +@@ -262,6 +272,7 @@ static struct clock_event_device clockevent_mxc = { + .name = "mxc_timer1", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_mode = mxc_set_mode, ++ .suspend = mxc_suspend, + .set_next_event = mx1_2_set_next_event, + .rating = 200, + }; +-- +1.7.9.5 + + +============================================================== +file 1104-interlaced-fix.patch +============================================================== + +From d6c338100ddd885a7acb1d0cf12da90fa7ac2b93 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Wed, 30 Dec 2015 11:01:32 +0100 +Subject: [PATCH] video: ipu_disp: Fix internal VSYNC clock for interlaced + modes + +Signed-off-by: Rudi +--- + drivers/mxc/ipu3/ipu_disp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c +index b5e21c5..96464b2 100644 +--- a/drivers/mxc/ipu3/ipu_disp.c ++++ b/drivers/mxc/ipu3/ipu_disp.c +@@ -1189,7 +1189,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk, + _ipu_di_sync_config(ipu, + disp, /* display */ + DI_SYNC_COUNT_1, /* counter */ +- v_total*2 - 1, /* run count */ ++ v_total - 1, /* run count */ + (3 - 1), /* run_resolution, counter 1 can reference to counter 6,7,8 with run_resolution=2,3,4 */ + 1, /* offset */ + (3 - 1), /* offset resolution, 3=counter 7 */ +-- +1.9.1 + + +============================================================== +file 1110-video-mxc_hdmi-Use-common-function-to-insert-video-m.patch +============================================================== + +From a86bd823319cf21eec118f238e2d3e97ede3690f Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 08:13:24 +0100 +Subject: [PATCH] video: mxc_hdmi: Use common function to insert video modes + +To simplify further development we move the mode list entry +creation into a single function. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_hdmi.c | 145 ++++++++++++++++++------------------------- + 1 file changed, 60 insertions(+), 85 deletions(-) + +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index 55c39e1..f71c1dd 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -1740,7 +1740,8 @@ static int mxc_edid_read_internal(struct mxc_hdmi *hdmi, unsigned char *edid, + + static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi) + { +- int ret; ++ int ret, n; ++ struct fb_videomode *mode; + u8 edid_old[HDMI_EDID_LEN]; + u8 clkdis; + +@@ -1774,19 +1775,36 @@ static int mxc_hdmi_read_edid(struct mxc_hdmi *hdmi) + + } + +- if (ret < 0) ++ if (ret < 0) { ++ dev_err(&hdmi->pdev->dev, "Failed to read EDID\n"); + return HDMI_EDID_FAIL; ++ } + + if (memcmp(edid_old, hdmi->edid, HDMI_EDID_LEN) == 0) { +- dev_info(&hdmi->pdev->dev, "same edid\n"); ++ dev_info(&hdmi->pdev->dev, "Same EDID\n"); + return HDMI_EDID_SAME; + } + + if (hdmi->fbi->monspecs.modedb_len == 0) { +- dev_info(&hdmi->pdev->dev, "No modes read from edid\n"); ++ dev_warn(&hdmi->pdev->dev, "No modes read from EDID\n"); + return HDMI_EDID_NO_MODES; + } + ++ /* TODO: Is this really neccessary? */ ++ mode = hdmi->fbi->monspecs.modedb; ++ n = hdmi->fbi->monspecs.modedb_len; ++ while (n--) { ++ if ((mode->flag & FB_MODE_IS_STANDARD) && ++ !(mode->vmode & FB_VMODE_ASPECT_MASK)) { ++ if (mode->yres == (mode->xres * 3)/4) ++ mode->vmode |= FB_VMODE_ASPECT_4_3; ++ else ++ mode->vmode |= FB_VMODE_ASPECT_16_9; ++ } ++ ++ mode++; ++ } ++ + return HDMI_EDID_SUCCESS; + } + +@@ -1928,51 +1946,53 @@ static void mxc_hdmi_notify_fb(struct mxc_hdmi *hdmi, bool force_all) + dev_dbg(&hdmi->pdev->dev, "%s exit\n", __func__); + } + +-static void mxc_hdmi_edid_rebuild_modelist(struct mxc_hdmi *hdmi) ++static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + { +- int i, vic; +- struct fb_videomode *mode; ++ struct fb_videomode mode; ++ int i, vic, mode_count = ARRAY_SIZE(mxc_cea_mode); ++ const struct fb_videomode *mode_data = mxc_cea_mode; ++ ++ if (from_edid) { ++ mode_data = hdmi->fbi->monspecs.modedb; ++ mode_count = hdmi->fbi->monspecs.modedb_len; ++ } + + dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); + + console_lock(); + + fb_destroy_modelist(&hdmi->fbi->modelist); ++ ++ /* Always insert VGA mode */ + fb_add_videomode(&vga_mode, &hdmi->fbi->modelist); + +- for (i = 0; i < hdmi->fbi->monspecs.modedb_len; i++) { +- /* +- * We might check here if mode is supported by HDMI. +- * We do not currently support interlaced modes. +- * And add CEA modes in the modelist. +- */ +- mode = &hdmi->fbi->monspecs.modedb[i]; +- +- vic = mxc_edid_mode_to_vic(mode); +- if (hdmi->edid_cfg.hdmi_cap && +- (vic == 0)) ++ for (i = 0; i < mode_count; i++) { ++ vic = from_edid ? mxc_edid_mode_to_vic(&mode_data[i]) : i; ++ ++ if (mode_data[i].xres == 0 || ++ (hdmi->edid_cfg.hdmi_cap && vic == 0)) + continue; + +- if (!(mode->vmode & FB_VMODE_ASPECT_MASK)) { +- if (mode->yres == (mode->xres * 3)/4) +- mode->vmode |= FB_VMODE_ASPECT_4_3; +- else +- mode->vmode |= FB_VMODE_ASPECT_16_9; +- } ++ mode = mode_data[i]; ++ ++ /* TODO: Discuss if we should always set default modes as standard */ ++ if (!from_edid /*&& ignore_edid*/) ++ mode.flag |= FB_MODE_IS_STANDARD; + +- if (fb_add_videomode(mode, &hdmi->fbi->modelist)) ++ if (fb_add_videomode(&mode, &hdmi->fbi->modelist)) + continue; + + dev_dbg(&hdmi->pdev->dev, "Added mode: %d, vic: %d", i, vic); + dev_dbg(&hdmi->pdev->dev, +- "xres = %d, yres = %d, ratio = %s, freq = %d, vmode = %d, flag = %d\n", +- hdmi->fbi->monspecs.modedb[i].xres, +- hdmi->fbi->monspecs.modedb[i].yres, +- mode->vmode & FB_VMODE_ASPECT_4_3 ? "4/3" : +- mode->vmode & FB_VMODE_ASPECT_16_9 ? "16/9" : "n/a", +- hdmi->fbi->monspecs.modedb[i].refresh, +- hdmi->fbi->monspecs.modedb[i].vmode, +- hdmi->fbi->monspecs.modedb[i].flag); ++ "xres = %d, yres = %d, scan = %c, ratio = %s, freq = %d, vmode = %d, flag = %d\n", ++ mode.xres, ++ mode.yres, ++ mode.vmode & FB_VMODE_INTERLACED ? 'i' : 'p', ++ mode.vmode & FB_VMODE_ASPECT_4_3 ? "4/3" : ++ mode.vmode & FB_VMODE_ASPECT_16_9 ? "16/9" : "n/a", ++ mode.refresh, ++ mode.vmode, ++ mode.flag); + } + + fb_new_modelist(hdmi->fbi); +@@ -1986,36 +2006,6 @@ static void mxc_hdmi_default_edid_cfg(struct mxc_hdmi *hdmi) + hdmi->edid_cfg.hdmi_cap = true; + } + +-static void mxc_hdmi_default_modelist(struct mxc_hdmi *hdmi) +-{ +- u32 i; +- struct fb_videomode mode; +- +- dev_dbg(&hdmi->pdev->dev, "%s\n", __func__); +- +- /* If not EDID data read, set up default modelist */ +- dev_info(&hdmi->pdev->dev, "No modes read from edid\n"); +- dev_info(&hdmi->pdev->dev, "create default modelist\n"); +- +- console_lock(); +- +- fb_destroy_modelist(&hdmi->fbi->modelist); +- +- /*Add all no interlaced CEA mode to default modelist */ +- for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) { +- mode = mxc_cea_mode[i]; +- if (mode.xres != 0) { +- if (ignore_edid) +- mode.flag |= FB_MODE_IS_STANDARD; +- fb_add_videomode(&mode, &hdmi->fbi->modelist); +- } +- } +- +- fb_new_modelist(hdmi->fbi); +- +- console_unlock(); +-} +- + static void mxc_hdmi_set_mode(struct mxc_hdmi *hdmi, int edid_status) + { + const struct fb_videomode *mode; +@@ -2108,7 +2098,7 @@ static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) + /* HDMI Initialization Steps D, E, F */ + switch (edid_status) { + case HDMI_EDID_SUCCESS: +- mxc_hdmi_edid_rebuild_modelist(hdmi); ++ mxc_hdmi_create_modelist(hdmi, true); + break; + + /* Nothing to do if EDID same */ +@@ -2120,7 +2110,7 @@ static void mxc_hdmi_cable_connected(struct mxc_hdmi *hdmi) + /* No break here */ + case HDMI_EDID_NO_MODES: + default: +- mxc_hdmi_default_modelist(hdmi); ++ mxc_hdmi_create_modelist(hdmi, false); + break; + } + +@@ -2676,7 +2666,6 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp, + struct mxc_dispdrv_setting *setting) + { + int ret = 0; +- u32 i; + const struct fb_videomode *mode; + struct fb_videomode m; + struct mxc_hdmi *hdmi = mxc_dispdrv_getdata(disp); +@@ -2787,31 +2776,17 @@ static int mxc_hdmi_disp_init(struct mxc_dispdrv_handle *disp, + + spin_lock_init(&hdmi->irq_lock); + +- /* Set the default mode and modelist when disp init. */ ++ /* Create default modelist */ ++ mxc_hdmi_create_modelist(hdmi, false); ++ ++ /* Set the default mode when disp init. */ + fb_find_mode(&hdmi->fbi->var, hdmi->fbi, + hdmi->dft_mode_str, NULL, 0, NULL, + hdmi->default_bpp); +- +- console_lock(); +- +- fb_destroy_modelist(&hdmi->fbi->modelist); +- +- /*Add all no interlaced CEA mode to default modelist */ +- for (i = 0; i < ARRAY_SIZE(mxc_cea_mode); i++) { +- mode = &mxc_cea_mode[i]; +- if (mode->xres != 0) { +- struct fb_videomode m = *mode; +- m.flag |= FB_MODE_IS_STANDARD; +- fb_add_videomode(&m, &hdmi->fbi->modelist); +- } +- } +- +- console_unlock(); +- +- /* Find a nearest mode in default modelist */ + fb_var_to_videomode(&m, &hdmi->fbi->var); + hdmi->dft_mode_set = false; + ++ /* Find a nearest mode in default modelist */ + mode = fb_find_nearest_mode(&m, &hdmi->fbi->modelist); + if (!mode) { + pr_err("%s: could not find mode in modelist\n", __func__); +-- +1.9.1 + + +============================================================== +file 1111-video-mxc_hdmi-Consider-modes-that-differ-only-in-as.patch +============================================================== + +From 9b245791da35efed7d3745ca5ca35d6cc73b49de Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 08:44:50 +0100 +Subject: [PATCH] video: mxc_hdmi: Consider modes that differ only in aspect + ratio as duplicate + +Certain CEA modes differ from each other only by the aspect ratio. If an EDID +indicates support for both modes of such an otherwise identical pair, we create +a mode list entry only for the first one. This is done because our sysfs cannot +distinguish them. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_hdmi.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index f71c1dd..182ae2a 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -1949,7 +1949,7 @@ static void mxc_hdmi_notify_fb(struct mxc_hdmi *hdmi, bool force_all) + static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + { + struct fb_videomode mode; +- int i, vic, mode_count = ARRAY_SIZE(mxc_cea_mode); ++ int i, j, skip, vic, mode_count = ARRAY_SIZE(mxc_cea_mode); + const struct fb_videomode *mode_data = mxc_cea_mode; + + if (from_edid) { +@@ -1975,6 +1975,19 @@ static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + + mode = mode_data[i]; + ++ /* for dual aspect ratio modes, insert the first one only */ ++ if (mode.vmode & FB_VMODE_ASPECT_MASK) { ++ skip = 0; ++ for (j = i - 1; !skip && j >= 0; j--) { ++ skip = mode.xres == mode_data[j].xres && ++ mode.yres == mode_data[j].yres && ++ mode.refresh == mode_data[j].refresh && ++ (mode.vmode ^ FB_VMODE_ASPECT_MASK) == mode_data[j].vmode; ++ } ++ if (skip) ++ continue; ++ } ++ + /* TODO: Discuss if we should always set default modes as standard */ + if (!from_edid /*&& ignore_edid*/) + mode.flag |= FB_MODE_IS_STANDARD; +-- +1.9.1 + + +============================================================== +file 1112-video-mxc_hdmi-Insert-standard-VGA-mode-only-once.patch +============================================================== + +From 2e980a57c261407795511d4794c8d22e78ecb9b2 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Mon, 4 Jan 2016 08:41:22 +0100 +Subject: [PATCH] video: mxc_hdmi: Insert standard VGA mode only once + +Skip standard VGA if found in EDID. We force this mode to be present +by default and therefore should not add it a second time. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_hdmi.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index 182ae2a..ec4a438 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -95,7 +95,7 @@ + * in HDMI Initialization Step B + */ + static const struct fb_videomode vga_mode = { +- /* 640x480 @ 60 Hz, 31.5 kHz hsync */ ++ /* 640x480 @ 59.94 Hz, 31.5 kHz hsync */ + NULL, 60, 640, 480, 39721, 48, 16, 33, 10, 96, 2, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, FB_MODE_IS_VESA, + }; +@@ -1988,6 +1988,10 @@ static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + continue; + } + ++ /* Skip standard VGA (already present) */ ++ if (vic == 1 && (mode.flag & FB_MODE_IS_VESA)) ++ continue; ++ + /* TODO: Discuss if we should always set default modes as standard */ + if (!from_edid /*&& ignore_edid*/) + mode.flag |= FB_MODE_IS_STANDARD; +-- +1.9.1 + + +============================================================== +file 1113-video-mxc_hdmi-mxc_edid-Introduce-fractional-modes.patch +============================================================== + +From 7df36826253b618c3d44d245b2f1e074112b91c3 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 09:26:40 +0100 +Subject: [PATCH] video: mxc_hdmi/mxc_edid: Introduce fractional modes + +In order to support fractional refresh rates (23.976, 29.97, 59.94, 119.88Hz) +we create 'synthetic' modes. These have the same timing as the corresponding +non-fractional modes (i.e. 24, 30, 60 and 120Hz). However, the refresh rate +is set to 23, 29, 59 and 119, respectively. In addition they have the mode +bit FB_VMODE_FRACTIONAL set. This bit is taken in acount when calculating +the real pixel clock. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_edid.c | 15 ++++++++++----- + drivers/video/mxc/mxc_hdmi.c | 25 +++++++++++++++++++++++-- + 2 files changed, 33 insertions(+), 7 deletions(-) + +diff --git a/drivers/video/mxc/mxc_edid.c b/drivers/video/mxc/mxc_edid.c +index 1aaaa68..b3a6ee1 100644 +--- a/drivers/video/mxc/mxc_edid.c ++++ b/drivers/video/mxc/mxc_edid.c +@@ -218,9 +218,9 @@ int mxc_edid_fb_mode_is_equal(bool use_aspect, + u32 mask; + + if (use_aspect) +- mask = ~0; ++ mask = ~FB_VMODE_FRACTIONAL; + else +- mask = ~FB_VMODE_ASPECT_MASK; ++ mask = ~(FB_VMODE_FRACTIONAL | FB_VMODE_ASPECT_MASK); + + return (mode1->xres == mode2->xres && + mode1->yres == mode2->yres && +@@ -823,7 +823,12 @@ const struct fb_videomode *mxc_fb_find_nearest_mode(const struct fb_videomode *m + struct fb_videomode *cmode; + static struct fb_videomode *best; + static u32 diff, diff_refresh; +- u32 mask = relax ? FB_VMODE_MASK_SIMPLE | FB_VMODE_ASPECT_MASK : ~0; ++ u32 mask = relax ? ~FB_VMODE_ASPECT_MASK : ~0; ++ int refresh = mode->refresh; ++ ++ if ((mode->flag & FB_MODE_IS_FROM_VAR) && ++ (mode->vmode & FB_VMODE_FRACTIONAL)) ++ refresh--; + + if (!relax) { + diff = -1; +@@ -844,10 +849,10 @@ const struct fb_videomode *mxc_fb_find_nearest_mode(const struct fb_videomode *m + abs(cmode->yres - mode->yres); + if (diff > d) { + diff = d; +- diff_refresh = abs(cmode->refresh - mode->refresh); ++ diff_refresh = abs(cmode->refresh - refresh); + best = cmode; + } else if (diff == d) { +- d = abs(cmode->refresh - mode->refresh); ++ d = abs(cmode->refresh - refresh); + if (diff_refresh > d) { + diff_refresh = d; + best = cmode; +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index ec4a438..6156e16 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -1999,9 +1999,30 @@ static void mxc_hdmi_create_modelist(struct mxc_hdmi *hdmi, int from_edid) + if (fb_add_videomode(&mode, &hdmi->fbi->modelist)) + continue; + +- dev_dbg(&hdmi->pdev->dev, "Added mode: %d, vic: %d", i, vic); + dev_dbg(&hdmi->pdev->dev, +- "xres = %d, yres = %d, scan = %c, ratio = %s, freq = %d, vmode = %d, flag = %d\n", ++ "Mode: vic=%d, xres=%d, yres=%d, scan=%c, ratio=%s, freq=%d, vmode=%d, flag=%d\n", ++ vic, ++ mode.xres, ++ mode.yres, ++ mode.vmode & FB_VMODE_INTERLACED ? 'i' : 'p', ++ mode.vmode & FB_VMODE_ASPECT_4_3 ? "4/3" : ++ mode.vmode & FB_VMODE_ASPECT_16_9 ? "16/9" : "n/a", ++ mode.refresh, ++ mode.vmode, ++ mode.flag); ++ ++ /* check if fractional mode should be inserted */ ++ if (vic == 0 || !(mode.refresh == 24 || (mode.refresh % 30) == 0)) ++ continue; ++ ++ mode.refresh--; ++ mode.vmode |= FB_VMODE_FRACTIONAL; ++ if (fb_add_videomode(&mode, &hdmi->fbi->modelist)) ++ continue; ++ ++ dev_dbg(&hdmi->pdev->dev, ++ "Mode: vic=%d, xres=%d, yres=%d, scan=%c, ratio=%s, freq=%d, vmode=%d, flag=%d\n", ++ vic, + mode.xres, + mode.yres, + mode.vmode & FB_VMODE_INTERLACED ? 'i' : 'p', +-- +1.9.1 + + +============================================================== +file 1114-video-mxc_edid-Adjust-pixel-timings.patch +============================================================== + +From cec6f4f51f22cd0324f255cb99a85eaa7f3d0d78 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 24 Dec 2015 09:51:31 +0100 +Subject: [PATCH] video: mxc_edid: Adjust pixel timings + +Our approach for fractional mode support requires the pixel timings +in the CEA mode table to describe the non-fractional modes. This +patch sets this for the modes that were defined otherwise. +Also it tweaks the rounding when calculating the real pixel clock +from the pixel time specified in the table. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_edid.c | 19 ++++++++++++------- + include/video/mxc_edid.h | 4 ++-- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/drivers/video/mxc/mxc_edid.c b/drivers/video/mxc/mxc_edid.c +index b3a6ee1..edfd6e8 100644 +--- a/drivers/video/mxc/mxc_edid.c ++++ b/drivers/video/mxc/mxc_edid.c +@@ -38,20 +38,25 @@ + #define DPRINTK(fmt, args...) + #endif + ++/* ++ * Attention: pixel times for the fractional mode entries must ++ * specify the non-fractional frequency of that mode! ++ * I.e. 60Hz instead of 59.94 and 24Hz instead of 23.98. ++ */ + const struct fb_videomode mxc_cea_mode[64] = { + /* #1: 640x480p@59.94/60Hz 4:3 */ + [1] = { +- NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0, ++ NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #2: 720x480p@59.94/60Hz 4:3 */ + [2] = { +- NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, ++ NULL, 60, 720, 480, 37000, 60, 16, 30, 9, 62, 6, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #3: 720x480p@59.94/60Hz 16:9 */ + [3] = { +- NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, ++ NULL, 60, 720, 480, 37000, 60, 16, 30, 9, 62, 6, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0, + }, + /* #4: 1280x720p@59.94/60Hz 16:9 */ +@@ -68,22 +73,22 @@ const struct fb_videomode mxc_cea_mode[64] = { + }, + /* #6: 720(1440)x480iH@59.94/60Hz 4:3 */ + [6] = { +- NULL, 60, 1440, 480, 37037, 38, 114, 8, 31, 124, 6, 0, ++ NULL, 60, 1440, 480, 37000, 38, 114, 8, 31, 124, 6, 0, + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #7: 720(1440)x480iH@59.94/60Hz 16:9 */ + [7] = { +- NULL, 60, 1440, 480, 37037, 38, 114, 8, 31, 124, 6, 0, ++ NULL, 60, 1440, 480, 37000, 38, 114, 8, 31, 124, 6, 0, + FB_VMODE_INTERLACED | FB_VMODE_ASPECT_16_9, 0, + }, + /* #8: 720(1440)x240pH@59.94/60Hz 4:3 */ + [8] = { +- NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0, ++ NULL, 60, 1440, 240, 37000, 114, 38, 15, 4, 124, 3, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_4_3, 0, + }, + /* #9: 720(1440)x240pH@59.94/60Hz 16:9 */ + [9] = { +- NULL, 60, 1440, 240, 37108, 114, 38, 15, 4, 124, 3, 0, ++ NULL, 60, 1440, 240, 37000, 114, 38, 15, 4, 124, 3, 0, + FB_VMODE_NONINTERLACED | FB_VMODE_ASPECT_16_9, 0, + }, + /* #14: 1440x480p@59.94/60Hz 4:3 */ +diff --git a/include/video/mxc_edid.h b/include/video/mxc_edid.h +index 561fe61..2feed16 100644 +--- a/include/video/mxc_edid.h ++++ b/include/video/mxc_edid.h +@@ -100,8 +100,8 @@ struct mxc_edid_cfg { + }; + + static inline unsigned long mxcPICOS2KHZ(u32 pixclock, u32 vmode) { +- u32 x = (1000000000UL / (pixclock) * 1000 / ((vmode & FB_VMODE_FRACTIONAL) ? 1001 : 1000)); +- return x + ((1000000000UL % x) > (x / 2) ? 1 : 0); ++ return ((((vmode & FB_VMODE_FRACTIONAL) ? ++ (999000999UL*4) : (1000000000UL*4)) / pixclock) + 1) >> 2; + } + + int mxc_edid_var_to_vic(struct fb_var_screeninfo *var); +-- +1.9.1 + + +============================================================== +file 1115-video-mxc_ipuv3_fb-Adjust-IPU-pixelclock.patch +============================================================== + +From 8b308a05dbfdbdffaf632857bc70a6005f95a6f5 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Tue, 29 Dec 2015 17:13:54 +0100 +Subject: [PATCH] video: mxc_ipuv3_fb: Adjust IPU pixelclock + +Use 'fractional' pixelclock calculation for IPU as well. + +Signed-off-by: Rudi +--- + drivers/video/mxc/mxc_ipuv3_fb.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c +index 9a3764f..8856c32 100644 +--- a/drivers/video/mxc/mxc_ipuv3_fb.c ++++ b/drivers/video/mxc/mxc_ipuv3_fb.c +@@ -49,6 +49,7 @@ + #include + #include + ++#include