From 27c38bd87c87102dc727935eac71e1bf3f4bebaf Mon Sep 17 00:00:00 2001 From: Peter Vicman Date: Sun, 4 Dec 2016 17:31:18 +0100 Subject: [PATCH] imx6: update kodi, libcec and linux 3.14 patches --- .../kodi/kodi-050-from-openbricks.patch | 191 +- .../patches/kodi/kodi-100-master-fixes.patch | 120 +- .../libcec/libcec-100-from-xbian.patch | 1766 +++++++++++ .../linux-800-from-openbricks.patch | 2710 ++++++++++++++++- .../linux-910.01-cec-upstream.patch | 86 - .../linux-910.02-cec-upstream.patch | 29 - .../3.14-mx6-sr/linux-compiler-gcc.h.patch | 166 - 7 files changed, 4643 insertions(+), 425 deletions(-) create mode 100644 projects/imx6/patches/libcec/libcec-100-from-xbian.patch delete mode 100644 projects/imx6/patches/linux/3.14-mx6-sr/linux-910.01-cec-upstream.patch delete mode 100644 projects/imx6/patches/linux/3.14-mx6-sr/linux-910.02-cec-upstream.patch delete mode 100644 projects/imx6/patches/linux/3.14-mx6-sr/linux-compiler-gcc.h.patch diff --git a/projects/imx6/patches/kodi/kodi-050-from-openbricks.patch b/projects/imx6/patches/kodi/kodi-050-from-openbricks.patch index 812ab1cd6f..e37f37d02f 100644 --- a/projects/imx6/patches/kodi/kodi-050-from-openbricks.patch +++ b/projects/imx6/patches/kodi/kodi-050-from-openbricks.patch @@ -1,6 +1,6 @@ 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 +https://github.com/OpenBricks/openbricks/tree/731d2788a4f5924cdf80314709dc303a43b5c3f5/packages/multimedia/kodi/patches ============================================================== file 0010-IMX-add-Supports-ERENDERFEATURE.patch @@ -3201,12 +3201,77 @@ index 2168e00..22b34d7 100644 ============================================================== -file 0050-Change-mediainfo-logging.patch +file 0042-Honour-forced-aspect-ratio-hint.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 @@ +From 8542fadfce7bfa1c7691403029a81682c389c8c2 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Mon, 3 Oct 2016 18:08:34 +0200 +Subject: [PATCH] Honour forced aspect ratio hint + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 6 +++++- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h | 1 + + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 74f4ae4..155710a 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -544,6 +544,8 @@ bool CIMXCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::stri + #endif + + m_warnOnce = true; ++ m_forcedWidthHeightRatio = m_hints.forced_aspect ? (65536 * m_hints.aspect) : 0; ++ + switch(m_hints.codec) + { + case AV_CODEC_ID_MPEG1VIDEO: +@@ -1155,7 +1157,9 @@ bool CIMXCodec::GetPicture(DVDVideoPicture* pDvdVideoPicture) + pDvdVideoPicture->iWidth = pIMXBuffer->GetPictureWidth(); + pDvdVideoPicture->iHeight = pIMXBuffer->GetPictureHeight(); + +- pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * pIMXBuffer->GetWidthHeightRatio()) + 32767) >> 16; ++ int ratio = m_forcedWidthHeightRatio ? m_forcedWidthHeightRatio : pIMXBuffer->GetWidthHeightRatio(); ++ ++ pDvdVideoPicture->iDisplayWidth = ((pDvdVideoPicture->iWidth * ratio) + 32767) >> 16; + pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight; + + pDvdVideoPicture->pts = pIMXBuffer->GetPts(); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +index 22b34d7..b91cdc2 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.h +@@ -386,6 +386,7 @@ protected: + int m_speed; + CCriticalSection m_signalLock; + CCriticalSection m_queuesLock; ++ int m_forcedWidthHeightRatio; + #ifdef DUMP_STREAM + FILE *m_dump; + #endif +-- +1.9.1 + + +============================================================== +file 0043-Cleanup-mediainfo-logging.patch +============================================================== + +From 5a26b1e3d341dd2591f6315f9fc97b5677105bf8 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Mon, 3 Oct 2016 18:11:31 +0200 +Subject: [PATCH] Cleanup mediainfo logging + +--- + .../DVDCodecs/Video/DVDVideoCodecIMX.cpp | 52 +++++++++++----------- + 1 file changed, 26 insertions(+), 26 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 155710a..3dc63d5 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -504,8 +504,6 @@ bool CIMXCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::stri } m_hints = hints; @@ -3215,7 +3280,7 @@ file 0050-Change-mediainfo-logging.patch int param = 0; SetVPUParams(VPU_DEC_CONF_INPUTTYPE, ¶m); -@@ -514,32 +512,31 @@ +@@ -514,32 +512,31 @@ bool CIMXCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::stri #ifdef MEDIAINFO if (g_advancedSettings.CanLogComponent(LOGVIDEO)) { @@ -3271,7 +3336,7 @@ file 0050-Change-mediainfo-logging.patch } #endif -@@ -624,6 +621,9 @@ +@@ -626,6 +623,9 @@ bool CIMXCodec::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, std::stri return false; } @@ -3281,6 +3346,75 @@ file 0050-Change-mediainfo-logging.patch std::list deintMethods({ EINTERLACEMETHOD::VS_INTERLACEMETHOD_AUTO, EINTERLACEMETHOD::VS_INTERLACEMETHOD_RENDER_BOB }); +-- +1.9.1 + + +============================================================== +file 0044-CodecIMX-fix-a-xvid-type-media-playback-starting-wit.patch +============================================================== + +From 451b97280d92fe1eedd78a5f06ec8b5bad6ae28c Mon Sep 17 00:00:00 2001 +From: Matus Kral +Date: Sat, 8 Oct 2016 17:23:32 +0200 +Subject: [PATCH] [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 3dc63d5..5e0abd5 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -977,7 +977,7 @@ void CIMXCodec::Process() + m_decInput.setquotasize(m_fps); + + 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); +-- +1.9.1 + + +============================================================== +file 0045-Partly-undo-d6f6155a060e0a5b94e3257f7c5d75fa1a8be321.patch +============================================================== + +From 99f481ea2c64ada525e135957be4b50751ca3a09 Mon Sep 17 00:00:00 2001 +From: Rudi +Date: Thu, 13 Oct 2016 20:49:02 +0200 +Subject: [PATCH] Partly undo d6f6155a060e0a5b94e3257f7c5d75fa1a8be321 + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +index 5e0abd5..4fefc27 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp +@@ -393,13 +393,6 @@ bool CIMXCodec::VpuAllocFrameBuffers() + #endif + vpuFrameBuffer.pbufVirtMvCol = ptrVirt + ySize + uSize + vSize; + +- if (i < 2) +- { +- memset(vpuFrameBuffer.pbufVirtY, 16, ySize); +- memset(vpuFrameBuffer.pbufVirtCb, 128, uSize + vSize); +- memset(vpuFrameBuffer.pbufVirtMvCol, 0, mvSize); +- } +- + m_vpuFrameBuffers.push_back(vpuFrameBuffer); + } + +-- +1.9.1 + ============================================================== file 400-Boost-Center-Audio-Channel-on-Downmixing.patch @@ -3367,43 +3501,6 @@ index e4ddf9e..34d0152 100644 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 ============================================================== @@ -3515,7 +3612,7 @@ 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 @@ +@@ -935,8 +935,14 @@ case CEC_USER_CONTROL_CODE_POWER: case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION: case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION: @@ -3527,7 +3624,7 @@ file 55-cec-power-button.diff + cec_command command; + command.opcode = CEC_OPCODE_STANDBY; + command.initiator = CECDEVICE_TV; -+ CecCommand(this, command); ++ CecCommand(this, &command); + } break; case CEC_USER_CONTROL_CODE_VOLUME_UP: @@ -3674,7 +3771,7 @@ 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 @@ +@@ -16416,7 +16416,7 @@ #: system/peripherals.xml msgctxt "#36026" diff --git a/projects/imx6/patches/kodi/kodi-100-master-fixes.patch b/projects/imx6/patches/kodi/kodi-100-master-fixes.patch index 4784ddc18d..a4c1c470ec 100644 --- a/projects/imx6/patches/kodi/kodi-100-master-fixes.patch +++ b/projects/imx6/patches/kodi/kodi-100-master-fixes.patch @@ -1,3 +1,5 @@ +disable standby + --- 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 @@ -25,90 +27,44 @@ #endif -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 +From e0c980535b164d7c28555418e5ce2252dbada2dc Mon Sep 17 00:00:00 2001 +From: Peter Vicman +Date: Thu, 10 Nov 2016 17:05:11 +0100 +Subject: [PATCH] fix freeze on lvds display connected to udoo quad -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 - }; - - 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 +revert 0ff257943e032e0f4b669a65e6449ab1e1699d74 +[IMXRenderer] skip rendering same frame --- - xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + .../cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp | 8 -------- + 1 file changed, 8 deletions(-) -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); +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +index 8569c72..f21fa98 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererIMX.cpp +@@ -132,7 +132,6 @@ bool CRendererIMX::RenderHook(int index) - 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); + 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(); +@@ -142,13 +141,6 @@ bool CRendererIMX::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) + CDVDVideoCodecIMXBuffer *buffer = static_cast(m_buffers[m_iYV12RenderBuffer].hwDec); + if (buffer) + { +- if (buffer == m_bufHistory[0] && flagsPrev == flags) +- { +- g_IMX.WaitVsync(); +- return true; +- } +- +- flagsPrev = flags; + buffer->Lock(); + + SAFE_RELEASE(m_bufHistory[1]); +-- +2.7.1 + diff --git a/projects/imx6/patches/libcec/libcec-100-from-xbian.patch b/projects/imx6/patches/libcec/libcec-100-from-xbian.patch new file mode 100644 index 0000000000..e7676b1e6b --- /dev/null +++ b/projects/imx6/patches/libcec/libcec-100-from-xbian.patch @@ -0,0 +1,1766 @@ +From bff5c44d1c5deeda77439c0f6d8e0ab1fa76c167 Mon Sep 17 00:00:00 2001 +From: Peter Vicman +Date: Sat, 3 Dec 2016 11:33:39 +0100 +Subject: [PATCH] patch for libcec from xbian + +libcec base: libcec-209884d +libcec xbian: + https://github.com/xbianonpi/xbian-sources-libcec/tree/masterv4 2ff5a0175937d5b190256c679d0b3b6f564f903a +--- + CMakeLists.txt | 6 + + debian/control | 7 +- + debian/libcec4-dev.install | 1 + + debian/libcec4.install | 2 + + include/cec.h | 2 + + include/cectypes.h | 47 ++- + src/cec-client/CMakeLists.txt | 4 +- + src/cecc-client/cecc-client.c | 2 +- + src/libcec/CECClient.cpp | 12 +- + src/libcec/CECClient.h | 1 + + src/libcec/CECProcessor.cpp | 6 + + src/libcec/CECProcessor.h | 1 + + src/libcec/CECTypeUtils.h | 2 + + src/libcec/CMakeLists.txt | 22 +- + src/libcec/LibCEC.cpp | 5 + + src/libcec/LibCEC.h | 1 + + src/libcec/adapter/AdapterFactory.cpp | 27 +- + .../adapter/IMX/IMXCECAdapterCommunication.cpp | 381 +++++++++++++++++++++ + .../adapter/IMX/IMXCECAdapterCommunication.h | 139 ++++++++ + src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp | 42 +++ + src/libcec/adapter/IMX/IMXCECAdapterDetection.h | 36 ++ + src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h | 118 +++++++ + src/libcec/adapter/IMX/mxc_hdmi-cec.h | 47 +++ + src/libcec/cmake/CheckPlatformSupport.cmake | 49 ++- + src/libcec/cmake/DisplayPlatformSupport.cmake | 10 +- + src/libcec/cmake/LinkPlatformSupport.cmake | 7 +- + src/libcec/cmake/git-rev.sh | 2 +- + src/libcec/devices/CECBusDevice.cpp | 11 +- + src/libcec/devices/CECBusDevice.h | 2 + + src/libcec/env.h.in | 3 + + src/libcec/implementations/CECCommandHandler.cpp | 16 +- + src/libcec/implementations/CECCommandHandler.h | 7 +- + src/libcec/implementations/GRCommandHandler.cpp | 92 +++++ + src/libcec/implementations/GRCommandHandler.h | 53 +++ + 34 files changed, 1102 insertions(+), 61 deletions(-) + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterCommunication.h + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterDetection.h + create mode 100644 src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h + create mode 100644 src/libcec/adapter/IMX/mxc_hdmi-cec.h + create mode 100644 src/libcec/implementations/GRCommandHandler.cpp + create mode 100644 src/libcec/implementations/GRCommandHandler.h + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 123b3b4..cdf1317 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -5,6 +5,12 @@ set(LIBCEC_VERSION_MAJOR 4) + set(LIBCEC_VERSION_MINOR 0) + set(LIBCEC_VERSION_PATCH 0) + ++find_program(CCACHE_FOUND ccache) ++if(CCACHE_FOUND) ++ set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) ++ set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) ++endif(CCACHE_FOUND) ++ + # cec-client + add_subdirectory(src/cec-client) + add_dependencies(cec-client cec) +diff --git a/debian/control b/debian/control +index e05a063..1675c1b 100644 +--- a/debian/control ++++ b/debian/control +@@ -20,6 +20,7 @@ Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/libcec.git + Package: libcec4-dev + Architecture: any + Section: libdevel ++Replaces: libcec-dev + Depends: libcec4 (= ${binary:Version}), + ${misc:Depends} + Description: libCEC communication Library (development files) +@@ -30,6 +31,7 @@ Description: libCEC communication Library (development files) + Package: libcec4 + Architecture: any + Multi-Arch: same ++Replaces: libcec3 + Pre-Depends: ${misc:Pre-Depends} + Depends: ${shlibs:Depends}, ${misc:Depends} + Description: libCEC communication Library (shared library) +@@ -40,6 +42,7 @@ Description: libCEC communication Library (shared library) + Package: cec-utils + Architecture: any + Section: utils ++Replaces: xbian-package-cec + Depends: libcec4 (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +@@ -60,6 +63,8 @@ Description: Python bindings for libCEC + + Package: libcec + Architecture: any +-Depends: ${shlibs:Depends}, ${misc:Depends}, libcec4 (= ${binary:Version}) ++Depends: ${shlibs:Depends}, ${misc:Depends}, libcec4 (= ${binary:Version}), python-libcec, cec-utils, libcec4-dev ++Provides: xbian-package-cec ++Breaks: xbian-package-cec (<<10.0) + Description: Meta package libCEC. + +diff --git a/debian/libcec4-dev.install b/debian/libcec4-dev.install +index e5bbd96..15a3585 100644 +--- a/debian/libcec4-dev.install ++++ b/debian/libcec4-dev.install +@@ -1,3 +1,4 @@ + usr/include + usr/lib/pkgconfig + usr/lib/*/*.so ++usr/lib/p8-platform +diff --git a/debian/libcec4.install b/debian/libcec4.install +index ca5ebe3..ac5e50a 100644 +--- a/debian/libcec4.install ++++ b/debian/libcec4.install +@@ -1 +1,3 @@ + usr/lib/*/libcec.so.* ++usr/lib/libp*.a ++ +diff --git a/include/cec.h b/include/cec.h +index 71450ae..b4a7d78 100644 +--- a/include/cec.h ++++ b/include/cec.h +@@ -389,6 +389,8 @@ namespace CEC + */ + virtual uint16_t GetAdapterProductId(void) const = 0; + ++ virtual bool TransmitSystemAudioModeRequest(void) = 0; ++ + virtual const char* ToString(const cec_menu_state state) = 0; + virtual const char* ToString(const cec_version version) = 0; + virtual const char* ToString(const cec_power_status status) = 0; +diff --git a/include/cectypes.h b/include/cectypes.h +index 9c91842..9fa69fc 100644 +--- a/include/cectypes.h ++++ b/include/cectypes.h +@@ -267,9 +267,19 @@ namespace CEC { + #define CEC_TDA995x_VIRTUAL_COM "CuBox" + + /*! ++ * the path to use for the i.MX CEC wire ++ */ ++#define CEC_IMX_PATH "/dev/mxc_hdmi_cec" ++ ++/*! ++ * the name of the virtual COM port to use for the i.MX CEC wire ++ */ ++#define CEC_IMX_VIRTUAL_COM "i.MX" ++ ++/*! + * the path to use for the Exynos HDMI CEC device + */ +-#define CEC_EXYNOS_PATH "/dev/CEC" ++#define CEC_EXYNOS_PATH "/dev/CEC" + + /*! + * the name of the virtual COM port to use for the EXYNOS' CEC wire +@@ -296,6 +306,8 @@ namespace CEC { + */ + #define CEC_MIN_LIB_VERSION 4 + ++#define CEC_LIB_VERSION_MAJOR 4 ++ + #define MSGSTART 0xFF + #define MSGEND 0xFE + #define MSGESC 0xFD +@@ -861,6 +873,7 @@ typedef enum cec_adapter_type + ADAPTERTYPE_RPI = 0x100, + ADAPTERTYPE_TDA995x = 0x200, + ADAPTERTYPE_EXYNOS = 0x300, ++ ADAPTERTYPE_IMX = 0x400, + ADAPTERTYPE_AOCEC = 0x500 + } cec_adapter_type; + +@@ -1245,7 +1258,7 @@ typedef struct cec_device_type_list + typedef struct cec_logical_addresses + { + cec_logical_address primary; /**< the primary logical address to use */ +- int addresses[16]; /**< the list of addresses */ ++ uint16_t addresses; /**< the list of addresses */ + + #ifdef __cplusplus + /*! +@@ -1254,8 +1267,7 @@ typedef struct cec_logical_addresses + void Clear(void) + { + primary = CECDEVICE_UNREGISTERED; +- for (unsigned int iPtr = 0; iPtr < 16; iPtr++) +- addresses[iPtr] = 0; ++ addresses = 0; + } + + /*! +@@ -1263,7 +1275,7 @@ typedef struct cec_logical_addresses + */ + bool IsEmpty(void) const + { +- return primary == CECDEVICE_UNREGISTERED; ++ return primary == CECDEVICE_UNREGISTERED && addresses == 0; + } + + /*! +@@ -1272,11 +1284,7 @@ typedef struct cec_logical_addresses + */ + uint16_t AckMask(void) const + { +- uint16_t mask = 0; +- for (unsigned int iPtr = 0; iPtr < 16; iPtr++) +- if (addresses[iPtr] == 1) +- mask |= 0x1 << iPtr; +- return mask; ++ return addresses; + } + + /*! +@@ -1288,7 +1296,7 @@ typedef struct cec_logical_addresses + if (primary == CECDEVICE_UNREGISTERED) + primary = address; + +- addresses[(int) address] = 1; ++ addresses |= (1 << (int) address); + } + + /*! +@@ -1300,7 +1308,7 @@ typedef struct cec_logical_addresses + if (primary == address) + primary = CECDEVICE_UNREGISTERED; + +- addresses[(int) address] = 0; ++ addresses &= ~(uint16_t)(1 << (int) address); + } + + /*! +@@ -1308,7 +1316,7 @@ typedef struct cec_logical_addresses + * @param address The address to check. + * @return True when set, false otherwise. + */ +- bool IsSet(cec_logical_address address) const { return addresses[(int) address] == 1; } ++ bool IsSet(cec_logical_address address) const { return (addresses & (1 << (int) address)); } + + /*! + * @brief Check whether an address is set in this list. +@@ -1317,18 +1325,9 @@ typedef struct cec_logical_addresses + */ + bool operator[](uint8_t pos) const { return pos < 16 ? IsSet((cec_logical_address) pos) : false; } + +- bool operator==(const cec_logical_addresses &other) const +- { +- bool bEqual(true); +- for (uint8_t iPtr = 0; iPtr < 16; iPtr++) +- bEqual &= ((addresses[(int)iPtr] == 1) == other[iPtr]); +- return bEqual; +- } ++ bool operator==(const cec_logical_addresses &other) const { return addresses == other.addresses; } + +- bool operator!=(const cec_logical_addresses &other) const +- { +- return !(*this == other); +- } ++ bool operator!=(const cec_logical_addresses &other) const { return !(*this == other); } + #endif + } cec_logical_addresses; + +diff --git a/src/cec-client/CMakeLists.txt b/src/cec-client/CMakeLists.txt +index 2cb42bb..c708fdb 100644 +--- a/src/cec-client/CMakeLists.txt ++++ b/src/cec-client/CMakeLists.txt +@@ -13,9 +13,9 @@ include(CheckLibraryExists) + include(CheckIncludeFiles) + include(CheckCXXCompilerFlag) + +-check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11) ++check_cxx_compiler_flag("-std=c++0x" SUPPORTS_CXX11) + if (SUPPORTS_CXX11) +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + endif() + + find_package(p8-platform REQUIRED) +diff --git a/src/cecc-client/cecc-client.c b/src/cecc-client/cecc-client.c +index 3373109..914d4d4 100644 +--- a/src/cecc-client/cecc-client.c ++++ b/src/cecc-client/cecc-client.c +@@ -337,7 +337,7 @@ static int cec_process_command_scan(const char* data) + activeSource = g_iface.get_active_source(g_iface.connection); + for (iPtr = 0; iPtr < 16; iPtr++) + { +- if (addresses.addresses[iPtr]) ++ if (addresses.addresses & (1 << iPtr)) + { + cec_menu_language lang; + cec_osd_name osdName; +diff --git a/src/libcec/CECClient.cpp b/src/libcec/CECClient.cpp +index b777faa..9f6e7c5 100644 +--- a/src/libcec/CECClient.cpp ++++ b/src/libcec/CECClient.cpp +@@ -139,10 +139,6 @@ bool CCECClient::OnRegister(void) + // set the physical address + SetPhysicalAddress(m_configuration); + +- // make the primary device the active source if the option is set +- if (m_configuration.bActivateSource == 1) +- GetPrimaryDevice()->ActivateSource(500); +- + return true; + } + +@@ -350,12 +346,13 @@ bool CCECClient::AllocateLogicalAddresses(void) + if (address == CECDEVICE_UNKNOWN) + { + LIB_CEC->AddLog(CEC_LOG_ERROR, "%s - failed to allocate device '%d', type '%s'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr])); +- return false; ++ continue; + } + + // display the registered LA + LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - device '%d', type '%s', LA '%X'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr]), address); + m_configuration.logicalAddresses.Set(address); ++ break; + } + + // persist the new configuration +@@ -1540,6 +1537,11 @@ bool CCECClient::IsLibCECActiveSource(void) + return bReturn; + } + ++bool CCECClient::TransmitSystemAudioModeRequest(void) ++{ ++ return m_processor ? m_processor->TransmitSystemAudioModeRequest(m_configuration.logicalAddresses.primary) : false; ++} ++ + void CCECClient::SourceActivated(const cec_logical_address logicalAddress) + { + LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> source activated: %s (%x)", ToString(logicalAddress), logicalAddress); +diff --git a/src/libcec/CECClient.h b/src/libcec/CECClient.h +index 49528ee..f02775c 100644 +--- a/src/libcec/CECClient.h ++++ b/src/libcec/CECClient.h +@@ -298,6 +298,7 @@ namespace CEC + virtual void RescanActiveDevices(void); + virtual bool IsLibCECActiveSource(void); + bool AudioEnable(bool enable); ++ virtual bool TransmitSystemAudioModeRequest(void); + + // configuration + virtual bool GetCurrentConfiguration(libcec_configuration &configuration); +diff --git a/src/libcec/CECProcessor.cpp b/src/libcec/CECProcessor.cpp +index 8ce46c5..e31e24a 100644 +--- a/src/libcec/CECProcessor.cpp ++++ b/src/libcec/CECProcessor.cpp +@@ -712,6 +712,12 @@ bool CCECProcessor::TransmitPendingActiveSourceCommands(void) + return bReturn; + } + ++bool CCECProcessor::TransmitSystemAudioModeRequest(cec_logical_address initiator) ++{ ++ CCECBusDevice *device = m_busDevices->At(initiator); ++ return device && device->TransmitSystemAudioModeRequest(initiator); ++} ++ + CCECTV *CCECProcessor::GetTV(void) const + { + return CCECBusDevice::AsTV(m_busDevices->At(CECDEVICE_TV)); +diff --git a/src/libcec/CECProcessor.h b/src/libcec/CECProcessor.h +index 08917b9..1971dee 100644 +--- a/src/libcec/CECProcessor.h ++++ b/src/libcec/CECProcessor.h +@@ -149,6 +149,7 @@ namespace CEC + bool GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT); + + bool TransmitPendingActiveSourceCommands(void); ++ bool TransmitSystemAudioModeRequest(cec_logical_address initiator); + + CCECDeviceMap *GetDevices(void) const { return m_busDevices; } + CLibCEC *GetLib(void) const { return m_libcec; } +diff --git a/src/libcec/CECTypeUtils.h b/src/libcec/CECTypeUtils.h +index 0d0cf17..f6c818a 100644 +--- a/src/libcec/CECTypeUtils.h ++++ b/src/libcec/CECTypeUtils.h +@@ -766,6 +766,8 @@ namespace CEC + return "Raspberry Pi"; + case ADAPTERTYPE_TDA995x: + return "TDA995x"; ++ case ADAPTERTYPE_IMX: ++ return "i.MX"; + default: + return "unknown"; + } +diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt +index d3eefa3..6a33abf 100644 +--- a/src/libcec/CMakeLists.txt ++++ b/src/libcec/CMakeLists.txt +@@ -13,9 +13,9 @@ include(CheckIncludeFiles) + include(CheckCXXCompilerFlag) + include(../../cmake/UseMultiArch.cmake) + +-check_cxx_compiler_flag("-std=c++11" SUPPORTS_CXX11) ++check_cxx_compiler_flag("-std=c++0x" SUPPORTS_CXX11) + if (SUPPORTS_CXX11) +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + endif() + + find_package(p8-platform REQUIRED) +@@ -64,7 +64,8 @@ set(CEC_SOURCES_IMPLEMENTATIONS implementations/ANCommandHandler.cpp + implementations/RLCommandHandler.cpp + implementations/PHCommandHandler.cpp + implementations/RHCommandHandler.cpp +- implementations/AQCommandHandler.cpp) ++ implementations/AQCommandHandler.cpp ++ implementations/GRCommandHandler.cpp) + + # /platform/* + set(CEC_SOURCES_PLATFORM platform/adl/adl-edid.cpp +@@ -124,6 +125,7 @@ set(CEC_HEADERS devices/CECRecordingDevice.h + implementations/RHCommandHandler.h + implementations/PHCommandHandler.h + implementations/AQCommandHandler.h ++ implementations/GRCommandHandler.h + CECProcessor.h) + source_group("Header Files" FILES ${CEC_HEADERS}) + +@@ -176,13 +178,17 @@ install(FILES ${PROJECT_SOURCE_DIR}/../../include/cec.h + DESTINATION include/libcec) + + # libCEC target +-add_library(cec SHARED ${CEC_SOURCES}) +-install(TARGETS cec ++add_library(cecobj OBJECT ${CEC_SOURCES}) ++set_property(TARGET ${cecobj} PROPERTY POSITION_INDEPENDENT_CODE 1) ++add_library(cec SHARED $) ++add_library(cecstatic STATIC $) ++set_target_properties(cecstatic PROPERTIES OUTPUT_NAME cec) ++install(TARGETS cec cecstatic + DESTINATION ${LIB_DESTINATION}) +-set_target_properties(cec PROPERTIES VERSION ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH} ++set_target_properties(cec cecstatic PROPERTIES VERSION ${LIBCEC_VERSION_MAJOR}.${LIBCEC_VERSION_MINOR}.${LIBCEC_VERSION_PATCH} + SOVERSION ${LIBCEC_VERSION_MAJOR}) +-target_link_libraries(cec ${p8-platform_LIBRARIES}) +-target_link_libraries(cec ${CMAKE_THREAD_LIBS_INIT}) ++target_link_libraries(cec cecstatic ${p8-platform_LIBRARIES}) ++target_link_libraries(cec cecstatic ${CMAKE_THREAD_LIBS_INIT}) + + include(cmake/LinkPlatformSupport.cmake) + include(cmake/DisplayPlatformSupport.cmake) +diff --git a/src/libcec/LibCEC.cpp b/src/libcec/LibCEC.cpp +index 8eedaa7..9562e06 100644 +--- a/src/libcec/LibCEC.cpp ++++ b/src/libcec/LibCEC.cpp +@@ -624,3 +624,8 @@ bool CLibCEC::AudioEnable(bool enable) + m_client->AudioEnable(enable) : + false; + } ++ ++bool CLibCEC::TransmitSystemAudioModeRequest(void) ++{ ++ return m_client ? m_client->TransmitSystemAudioModeRequest() : false; ++} +diff --git a/src/libcec/LibCEC.h b/src/libcec/LibCEC.h +index 7155926..b9e393b 100644 +--- a/src/libcec/LibCEC.h ++++ b/src/libcec/LibCEC.h +@@ -109,6 +109,7 @@ namespace CEC + bool PersistConfiguration(libcec_configuration *configuration); + void RescanActiveDevices(void); + bool IsLibCECActiveSource(void); ++ bool TransmitSystemAudioModeRequest(void); + + const char* ToString(const cec_menu_state state) { return CCECTypeUtils::ToString(state); } + const char* ToString(const cec_version version) { return CCECTypeUtils::ToString(version); } +diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp +index 1e946e6..261c60d 100644 +--- a/src/libcec/adapter/AdapterFactory.cpp ++++ b/src/libcec/adapter/AdapterFactory.cpp +@@ -63,6 +63,11 @@ + #include "AOCEC/AOCECAdapterCommunication.h" + #endif + ++#if defined(HAVE_IMX_API) ++#include "IMX/IMXCECAdapterDetection.h" ++#include "IMX/IMXCECAdapterCommunication.h" ++#endif ++ + using namespace CEC; + + int8_t CAdapterFactory::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */) +@@ -143,8 +148,21 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 + } + #endif + ++#if defined(HAVE_IMX_API) ++ if (iAdaptersFound < iBufSize && CIMXCECAdapterDetection::FindAdapter() && ++ (!strDevicePath || !strcmp(strDevicePath, CEC_IMX_VIRTUAL_COM))) ++ { ++ snprintf(deviceList[iAdaptersFound].strComPath, sizeof(deviceList[iAdaptersFound].strComPath), CEC_IMX_PATH); ++ snprintf(deviceList[iAdaptersFound].strComName, sizeof(deviceList[iAdaptersFound].strComName), CEC_IMX_VIRTUAL_COM); ++ deviceList[iAdaptersFound].iVendorId = IMX_ADAPTER_VID; ++ deviceList[iAdaptersFound].iProductId = IMX_ADAPTER_PID; ++ deviceList[iAdaptersFound].adapterType = ADAPTERTYPE_IMX; ++ iAdaptersFound++; ++ } ++#endif ++ + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_AOCEC_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_AOCEC_API) && !defined(HAVE_IMX_API) + #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" + #endif + +@@ -173,11 +191,16 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ + return new CRPiCECAdapterCommunication(m_lib->m_cec); + #endif + ++#if defined(HAVE_IMX_API) ++ if (!strcmp(strPort, CEC_IMX_VIRTUAL_COM)) ++ return new CIMXCECAdapterCommunication(m_lib->m_cec); ++#endif ++ + #if defined(HAVE_P8_USB) + return new CUSBCECAdapterCommunication(m_lib->m_cec, strPort, iBaudRate); + #endif + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API) + return NULL; + #endif + } +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp +new file mode 100644 +index 0000000..212dd75 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.cpp +@@ -0,0 +1,381 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * Copyright (C) 2014 by Matus Kral ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++#include "env.h" ++ ++#if defined(HAVE_IMX_API) ++#include "IMXCECAdapterCommunication.h" ++ ++#include "CECTypeUtils.h" ++#include "LibCEC.h" ++#include ++#include ++#include ++ ++using namespace std; ++using namespace CEC; ++using namespace P8PLATFORM; ++ ++#include "IMXCECAdapterMessageQueue.h" ++ ++#define LIB_CEC m_callback->GetLib() ++ ++// these are defined in nxp private header file ++#define CEC_MSG_SUCCESS 0x00 /*Message transmisson Succeed*/ ++#define CEC_CSP_OFF_STATE 0x80 /*CSP in Off State*/ ++#define CEC_BAD_REQ_SERVICE 0x81 /*Bad .req service*/ ++#define CEC_MSG_FAIL_UNABLE_TO_ACCESS 0x82 /*Message transmisson failed: Unable to access CEC line*/ ++#define CEC_MSG_FAIL_ARBITRATION_ERROR 0x83 /*Message transmisson failed: Arbitration error*/ ++#define CEC_MSG_FAIL_BIT_TIMMING_ERROR 0x84 /*Message transmisson failed: Bit timming error*/ ++#define CEC_MSG_FAIL_DEST_NOT_ACK 0x85 /*Message transmisson failed: Destination Address not aknowledged*/ ++#define CEC_MSG_FAIL_DATA_NOT_ACK 0x86 /*Message transmisson failed: Databyte not acknowledged*/ ++ ++CIMXCECAdapterCommunication::CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback) : ++ IAdapterCommunication(callback), ++ m_PAReporter(NULL) ++{ ++ CLockObject lock(m_mutex); ++ ++ m_iNextMessage = 0; ++ m_logicalAddress = CECDEVICE_UNKNOWN; ++ m_bLogicalAddressRegistered = false; ++ m_bInitialised = false; ++ m_dev = new CCDevSocket(CEC_IMX_PATH); ++ m_physicalAddress = -1; ++} ++ ++CIMXCECAdapterCommunication::~CIMXCECAdapterCommunication(void) ++{ ++ Close(); ++ SAFE_DELETE(m_PAReporter); ++ delete m_dev; ++ m_dev = 0; ++} ++ ++bool CIMXCECAdapterCommunication::IsOpen(void) ++{ ++ return IsInitialised() && m_dev->IsOpen(); ++} ++ ++bool CIMXCECAdapterCommunication::Open(uint32_t iTimeoutMs, bool UNUSED(bSkipChecks), bool bStartListening) ++{ ++ if (m_dev->Open(iTimeoutMs)) ++ { ++ if (!bStartListening || CreateThread()) { ++ if (m_dev->Ioctl(HDMICEC_IOC_STARTDEVICE, NULL) == 0) { ++ m_bInitialised = true; ++ RegisterLogicalAddress(CECDEVICE_BROADCAST); ++ return true; ++ } ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to start device\n", __func__); ++ } ++ m_dev->Close(); ++ } ++ ++ return false; ++} ++ ++ ++void CIMXCECAdapterCommunication::Close(void) ++{ ++ m_bInitialised = false; ++ if (m_dev->Ioctl(HDMICEC_IOC_STOPDEVICE, NULL) != 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: Unable to stop device\n", __func__); ++ } ++ StopThread(false); ++ m_dev->Close(); ++} ++ ++ ++std::string CIMXCECAdapterCommunication::GetError(void) const ++{ ++ std::string strError(m_strError); ++ return strError; ++} ++ ++ ++cec_adapter_message_state CIMXCECAdapterCommunication::Write( ++ const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool UNUSED(bIsReply)) ++{ ++ unsigned char message[MAX_MESSAGE_LEN]; ++ CIMXCECAdapterMessageQueueEntry *entry; ++ int msg_len = 1; ++ cec_adapter_message_state rc = ADAPTER_MESSAGE_STATE_ERROR; ++ ++ bRetry = true; ++ if ((size_t)data.parameters.size + data.opcode_set + 1 > sizeof(message)) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: data size too large !", __func__); ++ bRetry = false; ++ return rc; ++ } ++ ++ message[0] = (data.initiator << 4) | (data.destination & 0x0f); ++ if (data.opcode_set) ++ { ++ message[1] = data.opcode; ++ msg_len++; ++ memcpy(&message[2], data.parameters.data, data.parameters.size); ++ msg_len+=data.parameters.size; ++ } ++ ++ entry = new CIMXCECAdapterMessageQueueEntry(message[0], data.opcode); ++ m_messageMutex.Lock(); ++ uint32_t msgKey = ++m_iNextMessage; ++ m_messages.insert(make_pair(msgKey, entry)); ++ m_messageMutex.Unlock(); ++ ++ if (m_dev->Write(message, msg_len) > 0) ++ { ++ if (entry->Wait(data.transmit_timeout ? data.transmit_timeout : iLineTimeout *1000)) ++ { ++ int status = entry->Result(); ++ ++ if (status == MESSAGE_TYPE_NOACK) ++ rc = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED; ++ else if (status == MESSAGE_TYPE_SEND_SUCCESS) ++ rc = ADAPTER_MESSAGE_STATE_SENT_ACKED; ++ ++ bRetry = false; ++ } ++ else ++ { ++ rc = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT; ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: command timed out !", __func__); ++#endif ++ } ++ } ++ else ++ { ++ Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: write failed !", __func__); ++#endif ++ } ++ ++ m_messageMutex.Lock(); ++ m_messages.erase(msgKey); ++ m_messageMutex.Unlock(); ++ ++ delete entry; ++ ++ return rc; ++} ++ ++ ++uint16_t CIMXCECAdapterCommunication::GetFirmwareVersion(void) ++{ ++ /* FIXME add ioctl ? */ ++ return 0; ++} ++ ++ ++cec_vendor_id CIMXCECAdapterCommunication::GetVendorId(void) ++{ ++ return CEC_VENDOR_UNKNOWN; ++} ++ ++ ++uint16_t CIMXCECAdapterCommunication::GetPhysicalAddress(void) ++{ ++ uint8_t phy_addr[4]; ++ uint16_t pa_tmp; ++ ++ if (m_dev->Ioctl(HDMICEC_IOC_GETPHYADDRESS, &phy_addr) != 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_GETPHYADDRESS failed !", __func__); ++ return CEC_INVALID_PHYSICAL_ADDRESS; ++ } ++ ++ if ((pa_tmp = ((phy_addr[0] << 4 | phy_addr[1]) << 8) | (phy_addr[2] << 4 | phy_addr[3]))) ++ m_physicalAddress = pa_tmp; ++ ++ return m_physicalAddress; ++} ++ ++ ++cec_logical_addresses CIMXCECAdapterCommunication::GetLogicalAddresses(void) ++{ ++ cec_logical_addresses addresses; ++ addresses.Clear(); ++ ++ CLockObject lock(m_mutex); ++ if (m_bLogicalAddressRegistered) ++ addresses.Set(m_logicalAddress); ++ ++ return addresses; ++} ++ ++void CIMXCECAdapterCommunication::HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)) ++{ ++ UnregisterLogicalAddress(); ++} ++ ++bool CIMXCECAdapterCommunication::UnregisterLogicalAddress(void) ++{ ++ { ++ CLockObject lock(m_mutex); ++ if (!m_bLogicalAddressRegistered) ++ return true; ++ } ++ ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - releasing previous logical address", __func__); ++#endif ++ return RegisterLogicalAddress(CECDEVICE_BROADCAST); ++} ++ ++bool CIMXCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_address address) ++{ ++ { ++ CLockObject lock(m_mutex); ++ if ((m_logicalAddress == address && m_bLogicalAddressRegistered) || ++ (m_logicalAddress == address && address == CECDEVICE_BROADCAST)) ++ { ++ return true; ++ } ++ } ++ ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: %x to %x", __func__, m_logicalAddress, address); ++#endif ++ ++ if (m_dev->Ioctl(HDMICEC_IOC_SETLOGICALADDRESS, (void *)address) != 0) ++ { ++ LIB_CEC->AddLog(CEC_LOG_ERROR, "%s: HDMICEC_IOC_SETLOGICALADDRESS failed !", __func__); ++ return false; ++ } ++ ++ CLockObject lock(m_mutex); ++ ++ m_logicalAddress = address; ++ m_bLogicalAddressRegistered = (address != CECDEVICE_BROADCAST) ? true : false; ++ return true; ++} ++ ++bool CIMXCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses) ++{ ++ int log_addr = addresses.primary; ++ ++ return RegisterLogicalAddress((cec_logical_address)log_addr); ++} ++ ++ ++void *CIMXCECAdapterCommunication::Process(void) ++{ ++ bool bHandled; ++ hdmi_cec_event event; ++ int ret; ++ ++ cec_logical_address initiator, destination; ++ ++ while (!IsStopped()) ++ { ++ if (IsInitialised() && (ret = m_dev->Read((char *)&event, sizeof(event), 0)) > 0) ++ { ++ ++ initiator = cec_logical_address(event.msg[0] >> 4); ++ destination = cec_logical_address(event.msg[0] & 0x0f); ++ ++ if (event.event_type == MESSAGE_TYPE_RECEIVE_SUCCESS) ++ { ++ cec_command cmd; ++ ++ cec_command::Format( ++ cmd, initiator, destination, ++ ( event.msg_len > 1 ) ? cec_opcode(event.msg[1]) : CEC_OPCODE_NONE); ++ ++ for( uint8_t i = 2; i < event.msg_len; i++ ) ++ cmd.parameters.PushBack(event.msg[i]); ++ ++ if (!IsStopped()) { ++ m_callback->OnCommandReceived(cmd); ++ } ++ } ++ else if (event.event_type == MESSAGE_TYPE_SEND_SUCCESS ++ || event.event_type == MESSAGE_TYPE_NOACK) ++ { ++ bHandled = false; ++ ++ m_messageMutex.Lock(); ++ for (map::iterator it = m_messages.begin(); ++ !bHandled && it != m_messages.end(); it++) ++ { ++ bHandled = it->second->Received(event.event_type, event.msg[0], (cec_opcode)event.msg[1]); ++ } ++ m_messageMutex.Unlock(); ++ ++ if (!bHandled) ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: response not matched !", __func__); ++ } ++ else if (event.event_type == MESSAGE_TYPE_DISCONNECTED) ++ { ++ /* HDMI Hotplug event - disconnect */ ++ } ++ else if (event.event_type == MESSAGE_TYPE_CONNECTED) ++ { ++ if (m_physicalAddress == 0xffff) ++ continue; ++ /* HDMI Hotplug event - connect */ ++ uint16_t oldAddress = m_physicalAddress; ++ ++ if (oldAddress != GetPhysicalAddress()) { ++ if (m_PAReporter) ++ while (m_PAReporter->IsRunning()) Sleep(5); ++ delete m_PAReporter; ++ ++ m_PAReporter = new CCECPAChangedReporter(m_callback, m_physicalAddress); ++ m_PAReporter->CreateThread(false); ++ } ++#ifdef CEC_DEBUGGING ++ LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s: plugin event received", __func__); ++#endif ++ } ++ else ++ LIB_CEC->AddLog(CEC_LOG_WARNING, "%s: unhandled response received %d!", __func__, event.event_type); ++ } ++ } ++ ++ return 0; ++} ++ ++CCECPAChangedReporter::CCECPAChangedReporter(IAdapterCommunicationCallback *callback, uint16_t newPA) : ++ m_callback(callback), ++ m_newPA(newPA) ++{ ++} ++ ++void* CCECPAChangedReporter::Process(void) ++{ ++ m_callback->HandlePhysicalAddressChanged(m_newPA); ++ return NULL; ++} ++ ++#endif // HAVE_IMX_API +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h +new file mode 100644 +index 0000000..2da38c1 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterCommunication.h +@@ -0,0 +1,139 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * Copyright (C) 2014 by Matus Kral ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++#if defined(HAVE_IMX_API) ++ ++#include "adapter/AdapterCommunication.h" ++#include ++#include ++#include ++#include "adapter/IMX/mxc_hdmi-cec.h" ++#include ++ ++#define IMX_ADAPTER_VID 0x0471 /*FIXME TBD*/ ++#define IMX_ADAPTER_PID 0x1001 ++ ++typedef struct hdmi_cec_event{ ++ uint8_t event_type; ++ uint8_t msg_len; ++ uint8_t msg[MAX_MESSAGE_LEN]; ++}hdmi_cec_event; ++ ++ ++namespace P8PLATFORM ++{ ++ class CCDevSocket; ++}; ++ ++namespace CEC ++{ ++ class CIMXCECAdapterMessageQueueEntry; ++ ++ class CCECPAChangedReporter : public P8PLATFORM::CThread ++ { ++ public: ++ CCECPAChangedReporter(IAdapterCommunicationCallback *callback, uint16_t newPA); ++ void* Process(void); ++ ++ private: ++ IAdapterCommunicationCallback *m_callback; ++ uint16_t m_newPA; ++ }; ++ ++ class CIMXCECAdapterCommunication : public IAdapterCommunication, public P8PLATFORM::CThread ++ { ++ public: ++ /*! ++ * @brief Create a new USB-CEC communication handler. ++ * @param callback The callback to use for incoming CEC commands. ++ */ ++ CIMXCECAdapterCommunication(IAdapterCommunicationCallback *callback); ++ virtual ~CIMXCECAdapterCommunication(void); ++ ++ /** @name IAdapterCommunication implementation */ ++ ///{ ++ bool Open(uint32_t iTimeoutMs = CEC_DEFAULT_CONNECT_TIMEOUT, bool bSkipChecks = false, bool bStartListening = true); ++ void Close(void); ++ bool IsOpen(void); ++ std::string GetError(void) const; ++ cec_adapter_message_state Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool bIsReply); ++ ++ bool SetLineTimeout(uint8_t UNUSED(iTimeout)) { return true; } ++ bool StartBootloader(void) { return false; } ++ bool SetLogicalAddresses(const cec_logical_addresses &addresses); ++ cec_logical_addresses GetLogicalAddresses(void); ++ bool PingAdapter(void) { return IsInitialised(); } ++ uint16_t GetFirmwareVersion(void); ++ uint32_t GetFirmwareBuildDate(void) { return 0; } ++ bool IsRunningLatestFirmware(void) { return true; } ++ bool PersistConfiguration(const libcec_configuration & UNUSED(configuration)) { return false; } ++ bool GetConfiguration(libcec_configuration & UNUSED(configuration)) { return false; } ++ std::string GetPortName(void) { return std::string("IMX"); } ++ uint16_t GetPhysicalAddress(void); ++ bool SetControlledMode(bool UNUSED(controlled)) { return true; } ++ cec_vendor_id GetVendorId(void); ++ void HandleLogicalAddressLost(cec_logical_address UNUSED(oldAddress)); ++ bool SupportsSourceLogicalAddress(const cec_logical_address address) { return address > CECDEVICE_TV && address <= CECDEVICE_BROADCAST; } ++ cec_adapter_type GetAdapterType(void) { return ADAPTERTYPE_IMX; } ++ uint16_t GetAdapterVendorId(void) const { return IMX_ADAPTER_VID; } ++ uint16_t GetAdapterProductId(void) const { return IMX_ADAPTER_PID; } ++ void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {} ++ ///} ++ ++ /** @name PLATFORM::CThread implementation */ ++ ///{ ++ void *Process(void); ++ ///} ++ ++ private: ++ bool IsInitialised(void) { return m_bInitialised; }; ++ bool RegisterLogicalAddress(const cec_logical_address address); ++ bool UnregisterLogicalAddress(void); ++ ++ std::string m_strError; /**< current error message */ ++ ++ cec_logical_address m_logicalAddress; ++ uint16_t m_physicalAddress; ++ ++ P8PLATFORM::CMutex m_mutex; ++ P8PLATFORM::CCDevSocket *m_dev; /**< the device connection */ ++ ++ P8PLATFORM::CMutex m_messageMutex; ++ uint32_t m_iNextMessage; ++ std::map m_messages; ++ ++ bool m_bLogicalAddressRegistered; ++ bool m_bInitialised; ++ ++ CCECPAChangedReporter *m_PAReporter; ++ }; ++ ++}; ++ ++#endif +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp +new file mode 100644 +index 0000000..6c93c45 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.cpp +@@ -0,0 +1,42 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++#include "env.h" ++#include ++ ++#if defined(HAVE_IMX_API) ++#include "IMXCECAdapterDetection.h" ++ ++ ++using namespace CEC; ++ ++bool CIMXCECAdapterDetection::FindAdapter(void) ++{ ++ return access(CEC_IMX_PATH, 0) == 0; ++} ++ ++#endif +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterDetection.h b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h +new file mode 100644 +index 0000000..d54891d +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterDetection.h +@@ -0,0 +1,36 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * IMX adpater port is Copyright (C) 2013 by Stephan Rafin ++ * ++ * You can redistribute this file and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ */ ++ ++namespace CEC ++{ ++ class CIMXCECAdapterDetection ++ { ++ public: ++ static bool FindAdapter(void); ++ }; ++} +diff --git a/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h b/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h +new file mode 100644 +index 0000000..e54c192 +--- /dev/null ++++ b/src/libcec/adapter/IMX/IMXCECAdapterMessageQueue.h +@@ -0,0 +1,118 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include ++ ++namespace CEC ++{ ++ using namespace P8PLATFORM; ++ ++ class CIMXCECAdapterMessageQueueEntry ++ { ++ public: ++ CIMXCECAdapterMessageQueueEntry(uint8_t addrs, cec_opcode opcode) ++ : m_bWaiting(true), m_retval((uint32_t)-1), m_bSucceeded(false) ++ { ++ m_opcode = opcode; ++ m_addrs = addrs; ++ } ++ ++ virtual ~CIMXCECAdapterMessageQueueEntry(void) {} ++ ++ /*! ++ * @brief Query result from worker thread ++ */ ++ uint32_t Result() const ++ { ++ return m_retval; ++ } ++ ++ /*! ++ * @brief Signal waiting threads ++ */ ++ void Broadcast(void) ++ { ++ CLockObject lock(m_mutex); ++ m_condition.Broadcast(); ++ } ++ ++ /*! ++ * @brief Signal waiting thread(s) when message matches this entry ++ */ ++ bool Received(int response, uint8_t addrs, cec_opcode opcode) ++ { ++ CLockObject lock(m_mutex); ++ ++ if (!(m_addrs == addrs && m_opcode == opcode)) ++ return false; ++ ++ m_retval = response; ++ m_bSucceeded = true; ++ m_condition.Signal(); ++ return true; ++ } ++ ++ /*! ++ * @brief Wait for a response to this command. ++ * @param iTimeout The timeout to use while waiting. ++ * @return True when a response was received before the timeout passed, false otherwise. ++ */ ++ bool Wait(uint32_t iTimeout) ++ { ++ CLockObject lock(m_mutex); ++ ++ bool bReturn = m_bSucceeded ? true : m_condition.Wait(m_mutex, m_bSucceeded, iTimeout); ++ m_bWaiting = false; ++ return bReturn; ++ } ++ ++ /*! ++ * @return True while a thread is waiting for a signal or isn't waiting yet, false otherwise. ++ */ ++ bool IsWaiting(void) ++ { ++ CLockObject lock(m_mutex); ++ return m_bWaiting; ++ } ++ ++ private: ++ bool m_bWaiting; /**< true while a thread is waiting or when it hasn't started waiting yet */ ++ P8PLATFORM::CCondition m_condition; /**< the condition to wait on */ ++ P8PLATFORM::CMutex m_mutex; /**< mutex for changes to this class */ ++ int m_retval; ++ bool m_bSucceeded; ++ uint8_t m_addrs; ++ cec_opcode m_opcode; ++ }; ++ ++}; +diff --git a/src/libcec/adapter/IMX/mxc_hdmi-cec.h b/src/libcec/adapter/IMX/mxc_hdmi-cec.h +new file mode 100644 +index 0000000..bc5bbce +--- /dev/null ++++ b/src/libcec/adapter/IMX/mxc_hdmi-cec.h +@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef _HDMICEC_H_ ++#define _HDMICEC_H_ ++#include ++ ++/* ++ * Ioctl definitions ++ */ ++ ++/* Use 'k' as magic number */ ++#define HDMICEC_IOC_MAGIC 'H' ++/* ++ * S means "Set" through a ptr, ++ * T means "Tell" directly with the argument value ++ * G means "Get": reply by setting through a pointer ++ * Q means "Query": response is on the return value ++ * X means "eXchange": G and S atomically ++ * H means "sHift": T and Q atomically ++ */ ++#define HDMICEC_IOC_SETLOGICALADDRESS \ ++ _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char) ++#define HDMICEC_IOC_STARTDEVICE _IO(HDMICEC_IOC_MAGIC, 2) ++#define HDMICEC_IOC_STOPDEVICE _IO(HDMICEC_IOC_MAGIC, 3) ++#define HDMICEC_IOC_GETPHYADDRESS \ ++ _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4]) ++ ++#define MAX_MESSAGE_LEN 16 ++ ++#define MESSAGE_TYPE_RECEIVE_SUCCESS 1 ++#define MESSAGE_TYPE_NOACK 2 ++#define MESSAGE_TYPE_DISCONNECTED 3 ++#define MESSAGE_TYPE_CONNECTED 4 ++#define MESSAGE_TYPE_SEND_SUCCESS 5 ++ ++#endif /* !_HDMICEC_H_ */ ++ +diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake +index 532f213..a89e404 100644 +--- a/src/libcec/cmake/CheckPlatformSupport.cmake ++++ b/src/libcec/cmake/CheckPlatformSupport.cmake +@@ -91,24 +91,49 @@ else() + endif() + + # xrandr +- check_include_files("X11/Xlib.h;X11/Xatom.h;X11/extensions/Xrandr.h" HAVE_RANDR_HEADERS) +- check_library_exists(Xrandr XRRGetScreenResources "" HAVE_RANDR_LIB) +- if (HAVE_RANDR_HEADERS AND HAVE_RANDR_LIB) +- set(LIB_INFO "${LIB_INFO}, randr") +- list(APPEND CEC_SOURCES_PLATFORM platform/X11/randr-edid.cpp) +- SET(HAVE_RANDR ON CACHE BOOL "xrandr supported" FORCE) ++ if (${HAVE_RANDR_API}) ++ check_include_files("X11/Xlib.h;X11/Xatom.h;X11/extensions/Xrandr.h" HAVE_RANDR_HEADERS) ++ check_library_exists(Xrandr XRRGetScreenResources "" HAVE_RANDR_LIB) ++ if (HAVE_RANDR_HEADERS AND HAVE_RANDR_LIB) ++ set(LIB_INFO "${LIB_INFO}, randr") ++ list(APPEND CEC_SOURCES_PLATFORM platform/X11/randr-edid.cpp) ++ set(HAVE_RANDR 1) ++ else() ++ set(HAVE_RANDR 0) ++ endif() ++ else() ++ set(HAVE_RANDR 0) + endif() + ++ # iMX6 ++ if (${HAVE_IMX_API}) ++ set(LIB_INFO "${LIB_INFO}, iMX6") ++ set(HAVE_IMX_API 1) ++ set(CEC_SOURCES_ADAPTER_IMX adapter/IMX/IMXCECAdapterDetection.cpp ++ adapter/IMX/IMXCECAdapterCommunication.cpp) ++ source_group("Source Files\\adapter\\iMX6" FILES ${CEC_SOURCES_ADAPTER_IMX}) ++ list(APPEND CEC_SOURCES ${CEC_SOURCES_ADAPTER_IMX}) ++ set(HAVE_RPI_API 0) ++ else() ++ set(HAVE_IMX_API 0) ++ set(HAVE_RPI_API 1) ++ endif() ++ + # raspberry pi +- find_library(RPI_BCM_HOST bcm_host "${RPI_LIB_DIR}") +- check_library_exists(bcm_host bcm_host_init "${RPI_LIB_DIR}" HAVE_RPI_LIB) +- if (HAVE_RPI_LIB) +- SET(HAVE_RPI_API ON CACHE BOOL "raspberry pi supported" FORCE) ++ if (HAVE_RPI_API) ++ find_library(RPI_BCM_HOST bcm_host "${RPI_LIB_DIR}") ++ check_library_exists(bcm_host bcm_host_init "${RPI_LIB_DIR}" HAVE_RPI_API) ++ endif() ++ if (HAVE_RPI_API) + find_library(RPI_VCOS vcos "${RPI_LIB_DIR}") + find_library(RPI_VCHIQ_ARM vchiq_arm "${RPI_LIB_DIR}") + include_directories(${RPI_INCLUDE_DIR} ${RPI_INCLUDE_DIR}/interface/vcos/pthreads ${RPI_INCLUDE_DIR}/interface/vmcs_host/linux) + +- set(LIB_INFO "${LIB_INFO}, RPi") ++ set(LIB_INFO "${LIB_INFO}, 'RPi'") ++ # find includes files on Raspberry Pi ++ include_directories(/opt/vc/include /opt/vc/include/interface/vcos/pthreads /opt/vc/include/interface/vmcs_host/linux) ++ list(APPEND CMAKE_REQUIRED_LIBRARIES "vcos") ++ list(APPEND CMAKE_REQUIRED_LIBRARIES "vchiq_arm") + set(CEC_SOURCES_ADAPTER_RPI adapter/RPi/RPiCECAdapterDetection.cpp + adapter/RPi/RPiCECAdapterCommunication.cpp + adapter/RPi/RPiCECAdapterMessageQueue.cpp) +@@ -148,6 +173,8 @@ else() + else() + set(HAVE_AOCEC_API 0) + endif() ++ ++ + endif() + + # rt +diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake +index 7ec10f5..2262638 100644 +--- a/src/libcec/cmake/DisplayPlatformSupport.cmake ++++ b/src/libcec/cmake/DisplayPlatformSupport.cmake +@@ -45,9 +45,15 @@ else() + endif() + + if (HAVE_AOCEC_API) +- message(STATUS "AOCEC support: yes") ++ message(STATUS "AOCEC support: yes") + else() +- message(STATUS "AOCEC support: no") ++ message(STATUS "AOCEC support: no") ++endif() ++ ++if (HAVE_IMX_API) ++ message(STATUS "i.MX6 support: yes") ++else() ++ message(STATUS "i.MX6 support: no") + endif() + + if (HAVE_PYTHON) +diff --git a/src/libcec/cmake/LinkPlatformSupport.cmake b/src/libcec/cmake/LinkPlatformSupport.cmake +index fc27353..b203f6f 100644 +--- a/src/libcec/cmake/LinkPlatformSupport.cmake ++++ b/src/libcec/cmake/LinkPlatformSupport.cmake +@@ -28,7 +28,12 @@ endif() + + # raspberry pi + if (HAVE_RPI_API) +- target_link_libraries(cec ${RPI_VCOS} ${RPI_VCHIQ_ARM} ${RPI_BCM_HOST}) ++ find_library (VCOS vcos) ++ target_link_libraries(cec ${VCOS}) ++ find_library (VCHIQ_ARM vchiq_arm) ++ target_link_libraries(cec ${VCHIP_ARM}) ++ find_library (BCM_HOST bcm_host) ++ target_link_libraries(cec ${BCM_HOST}) + endif() + + # Apple +diff --git a/src/libcec/cmake/git-rev.sh b/src/libcec/cmake/git-rev.sh +index db682c1..15b6a23 100755 +--- a/src/libcec/cmake/git-rev.sh ++++ b/src/libcec/cmake/git-rev.sh +@@ -2,7 +2,7 @@ + + ## cmake doesn't read the variable when it doesn't end with a newline, and I haven't figured out how to have it add a newline directly... + if git rev-parse --git-dir > /dev/null 2>&1; then +- last_tag=`git describe --tags --abbrev=0` ++ last_tag=`git describe --tags --abbrev=0 --all` + last_hash=`git --no-pager log --abbrev=7 -n 1 --pretty=format:"%h"` + commits_since_tag=`git log ${last_tag}..HEAD --oneline | wc -l` + git_dirty=`git diff HEAD | wc -l` +diff --git a/src/libcec/devices/CECBusDevice.cpp b/src/libcec/devices/CECBusDevice.cpp +index 612be6d..2be9816 100644 +--- a/src/libcec/devices/CECBusDevice.cpp ++++ b/src/libcec/devices/CECBusDevice.cpp +@@ -44,6 +44,7 @@ + #include "implementations/RLCommandHandler.h" + #include "implementations/RHCommandHandler.h" + #include "implementations/AQCommandHandler.h" ++#include "implementations/GRCommandHandler.h" + #include "LibCEC.h" + #include "CECTypeUtils.h" + #include +@@ -217,6 +218,9 @@ bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */) + case CEC_VENDOR_SHARP2: + m_handler = new CAQCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); + break; ++ case CEC_VENDOR_GRUNDIG: ++ m_handler = new CGRCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); ++ break; + default: + m_handler = new CCECCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); + break; +@@ -1263,7 +1267,7 @@ bool CCECBusDevice::PowerOn(const cec_logical_address initiator) + + MarkBusy(); + cec_power_status currentStatus; +- if (m_iLogicalAddress == CECDEVICE_TV || ++ if ((m_iLogicalAddress == CECDEVICE_TV && !ImageViewOnSent()) || + ((currentStatus = GetPowerStatus(initiator, false)) != CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON && + currentStatus != CEC_POWER_STATUS_ON)) + { +@@ -1498,3 +1502,8 @@ bool CCECBusDevice::TransmitMuteAudio(const cec_logical_address source) + return TransmitKeypress(source, CEC_USER_CONTROL_CODE_MUTE) && + TransmitKeyRelease(source); + } ++ ++bool CCECBusDevice::TransmitSystemAudioModeRequest(const cec_logical_address initiator) ++{ ++ return m_handler->TransmitSystemAudioModeRequest(initiator, m_iPhysicalAddress, false); ++} +diff --git a/src/libcec/devices/CECBusDevice.h b/src/libcec/devices/CECBusDevice.h +index b8255aa..8493d48 100644 +--- a/src/libcec/devices/CECBusDevice.h ++++ b/src/libcec/devices/CECBusDevice.h +@@ -199,6 +199,8 @@ namespace CEC + void SignalOpcode(cec_opcode opcode); + bool WaitForOpcode(cec_opcode opcode); + ++ virtual bool TransmitSystemAudioModeRequest(const cec_logical_address initiator); ++ + CCECAudioSystem * AsAudioSystem(void); + static CCECAudioSystem * AsAudioSystem(CCECBusDevice *device); + CCECPlaybackDevice * AsPlaybackDevice(void); +diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in +index fe6c83d..91c7a27 100644 +--- a/src/libcec/env.h.in ++++ b/src/libcec/env.h.in +@@ -66,6 +66,9 @@ + /* Define to 1 for Raspberry Pi support */ + #cmakedefine HAVE_RPI_API @HAVE_RPI_API@ + ++/* Define to 1 for iMX6 support */ ++#cmakedefine HAVE_IMX_API @HAVE_IMX_API@ ++ + /* Define to 1 for TDA995x support */ + #cmakedefine HAVE_TDA995X_API @HAVE_TDA995X_API@ + +diff --git a/src/libcec/implementations/CECCommandHandler.cpp b/src/libcec/implementations/CECCommandHandler.cpp +index 71c2230..5a1e7a0 100644 +--- a/src/libcec/implementations/CECCommandHandler.cpp ++++ b/src/libcec/implementations/CECCommandHandler.cpp +@@ -62,6 +62,7 @@ CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice, + m_iTransmitRetries(iTransmitRetries), + m_bHandlerInited(false), + m_bOPTSendDeckStatusUpdateOnActiveSource(false), ++ m_bOPTSendMenuStatusUpdateOnActiveSource(true), + m_vendorId(CEC_VENDOR_UNKNOWN), + m_iActiveSourcePending(iActiveSourcePending), + m_iPowerStatusRequested(0) +@@ -1133,6 +1134,19 @@ bool CCECCommandHandler::TransmitAudioStatus(const cec_logical_address iInitiato + return Transmit(command, false, bIsReply); + } + ++bool CCECCommandHandler::TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply) ++{ ++ cec_command command; ++ cec_command::Format(command, iInitiator, CECDEVICE_AUDIOSYSTEM, CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST); ++ command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF)); ++ command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF)); ++ ++ if (Transmit(command, true, bIsReply)) ++ return true; ++ ++ return false; ++} ++ + bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply) + { + cec_command command; +@@ -1307,7 +1321,7 @@ bool CCECCommandHandler::ActivateSource(bool bTransmitDelayedCommandsOnly /* = f + if (!bActiveSourceFailed && bSourceSwitchAllowed) + { + bActiveSourceFailed = !m_busDevice->TransmitActiveSource(false); +- if (bTvPresent && !bActiveSourceFailed) ++ if (bTvPresent && !bActiveSourceFailed && SendMenuStatusUpdateOnActiveSource()) + m_busDevice->TransmitMenuState(CECDEVICE_TV, false); + + // update the deck status for playback devices +diff --git a/src/libcec/implementations/CECCommandHandler.h b/src/libcec/implementations/CECCommandHandler.h +index 8ff9a1e..eb52ed3 100644 +--- a/src/libcec/implementations/CECCommandHandler.h ++++ b/src/libcec/implementations/CECCommandHandler.h +@@ -60,7 +60,9 @@ namespace CEC + virtual bool HandleCommand(const cec_command &command); + virtual cec_vendor_id GetVendorId(void) { return m_vendorId; }; + virtual void SetVendorId(cec_vendor_id vendorId) { m_vendorId = vendorId; } +- static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS || vendorId == CEC_VENDOR_SHARP || vendorId == CEC_VENDOR_SHARP2 || vendorId == CEC_VENDOR_TOSHIBA || vendorId == CEC_VENDOR_TOSHIBA2 || vendorId == CEC_VENDOR_ONKYO;} ++ static bool HasSpecificHandler(cec_vendor_id vendorId) { return vendorId == CEC_VENDOR_LG || vendorId == CEC_VENDOR_SAMSUNG || vendorId == CEC_VENDOR_PANASONIC || vendorId == CEC_VENDOR_PHILIPS ++ || vendorId == CEC_VENDOR_SHARP || vendorId == CEC_VENDOR_SHARP2 || vendorId == CEC_VENDOR_TOSHIBA || vendorId == CEC_VENDOR_TOSHIBA2 || vendorId == CEC_VENDOR_ONKYO ++ || vendorId == CEC_VENDOR_GRUNDIG; } + + virtual bool InitHandler(void) { return true; } + virtual bool ActivateSource(bool bTransmitDelayedCommandsOnly = false); +@@ -89,6 +91,7 @@ namespace CEC + virtual bool TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state, bool bIsReply); + virtual bool TransmitVendorID(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint64_t iVendorId, bool bIsReply); + virtual bool TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state, bool bIsReply); ++ virtual bool TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, bool bIsReply); + virtual bool TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply); + virtual bool TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state, bool bIsReply); + virtual bool TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state, bool bIsReply); +@@ -97,6 +100,7 @@ namespace CEC + virtual bool TransmitSystemAudioModeRequest(const cec_logical_address iInitiator, uint16_t iPhysicalAddress); + virtual bool TransmitSetStreamPath(uint16_t iStreamPath, bool bIsReply); + virtual bool SendDeckStatusUpdateOnActiveSource(void) const { return m_bOPTSendDeckStatusUpdateOnActiveSource; }; ++ virtual bool SendMenuStatusUpdateOnActiveSource(void) const { return m_bOPTSendMenuStatusUpdateOnActiveSource; }; + + virtual void ScheduleActivateSource(uint64_t iDelay); + +@@ -165,6 +169,7 @@ namespace CEC + int8_t m_iTransmitRetries; + bool m_bHandlerInited; + bool m_bOPTSendDeckStatusUpdateOnActiveSource; ++ bool m_bOPTSendMenuStatusUpdateOnActiveSource; + cec_vendor_id m_vendorId; + int64_t m_iActiveSourcePending; + P8PLATFORM::CMutex m_mutex; +diff --git a/src/libcec/implementations/GRCommandHandler.cpp b/src/libcec/implementations/GRCommandHandler.cpp +new file mode 100644 +index 0000000..af49af9 +--- /dev/null ++++ b/src/libcec/implementations/GRCommandHandler.cpp +@@ -0,0 +1,92 @@ ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include "GRCommandHandler.h" ++ ++#include "devices/CECBusDevice.h" ++#include "CECProcessor.h" ++#include "LibCEC.h" ++#include "CECClient.h" ++ ++using namespace CEC; ++ ++#define LIB_CEC m_busDevice->GetProcessor()->GetLib() ++#define ToString(p) LIB_CEC->ToString(p) ++ ++CGRCommandHandler::CGRCommandHandler(CCECBusDevice *busDevice, ++ int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */, ++ int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */, ++ int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */, ++ int64_t iActiveSourcePending /* = 0 */) : ++ CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending) ++{ ++ m_vendorId = CEC_VENDOR_GRUNDIG; ++ m_bOPTSendMenuStatusUpdateOnActiveSource = false; ++ ++ m_busDevice->SetCecVersion(CEC_VERSION_1_3A); ++ ++ /* Grundig devices return "" as language */ ++ cec_menu_language lang; ++ snprintf(lang, 4, "eng"); ++ m_busDevice->SetMenuLanguage(lang); ++} ++ ++bool CGRCommandHandler::InitHandler(void) ++{ ++ if (m_bHandlerInited) ++ return true; ++ m_bHandlerInited = true; ++ ++ if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV) ++ return true; ++ ++ CCECBusDevice *primary = m_processor->GetPrimaryDevice(); ++ if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED) ++ { ++ /* imitate Toshiba devices */ ++ if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress()) ++ { ++ primary->SetVendorId(CEC_VENDOR_GRUNDIG); ++ primary->ReplaceHandler(false); ++ } ++ ++ if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV) ++ { ++ /* send the vendor id */ ++ primary->TransmitVendorID(CECDEVICE_BROADCAST, false, false); ++ } ++ } ++ ++ return true; ++} +diff --git a/src/libcec/implementations/GRCommandHandler.h b/src/libcec/implementations/GRCommandHandler.h +new file mode 100644 +index 0000000..e01c7fc +--- /dev/null ++++ b/src/libcec/implementations/GRCommandHandler.h +@@ -0,0 +1,53 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited. All rights reserved. ++ * libCEC(R) is an original work, containing original code. ++ * ++ * libCEC(R) is a trademark of Pulse-Eight Limited. ++ * ++ * This program is dual-licensed; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301 USA ++ * ++ * ++ * Alternatively, you can license this library under a commercial license, ++ * please contact Pulse-Eight Licensing for more information. ++ * ++ * For more information contact: ++ * Pulse-Eight Licensing ++ * http://www.pulse-eight.com/ ++ * http://www.pulse-eight.net/ ++ */ ++ ++#include "env.h" ++#include "CECCommandHandler.h" ++#include "p8-platform/threads/threads.h" ++ ++namespace CEC ++{ ++ class CGRCommandHandler : public CCECCommandHandler ++ { ++ public: ++ CGRCommandHandler(CCECBusDevice *busDevice, ++ int32_t iTransmitTimeout = CEC_DEFAULT_TRANSMIT_TIMEOUT, ++ int32_t iTransmitWait = CEC_DEFAULT_TRANSMIT_WAIT, ++ int8_t iTransmitRetries = CEC_DEFAULT_TRANSMIT_RETRIES, ++ int64_t iActiveSourcePending = 0); ++ ++ bool InitHandler(void); ++ virtual ~CGRCommandHandler(void) {}; ++ }; ++}; +-- +2.7.1 + 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 index 58d8fea88e..b9dbab6f86 100644 --- 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 @@ -1,23 +1,163 @@ 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 +https://github.com/OpenBricks/openbricks/tree/731d2788a4f5924cdf80314709dc303a43b5c3f5/config/platforms/arm/imx6/machines/cuboxi/packages/linux/patches ============================================================== -file 0004-Dumb_adapter.patch +file 0001-MXC-CEC-Remove-superflous-guards-that-could-even-bre.patch ============================================================== -commit c466ada304c10af850daaef8b232e0e818bfb6d7 -Author: wolfgar -Date: Sat Sep 13 02:08:32 2014 +0200 +From 90d153b9d46ad06a4a513902d3bb72d23c45bdcc Mon Sep 17 00:00:00 2001 +From: wolfgar +Date: Mon, 31 Oct 2016 10:58:44 +0100 +Subject: [PATCH] MXC-CEC: Remove superflous guards that could even break + invocation from mxc-hdmi - Remove embedded logics from the driver so that libcec is responsible for - all this work +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 20 ++------------------ + 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -index c30237e..fb66c25 100644 +index ac70a0c..f787274 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) +@@ -83,8 +83,6 @@ struct hdmi_cec_event { + + static LIST_HEAD(head); + +-static int hdmi_cec_ready = 0; +-static int hdmi_cec_started; + static int hdmi_cec_major; + static struct class *hdmi_cec_class; + static struct hdmi_cec_priv hdmi_cec_data; +@@ -314,7 +312,7 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + mutex_unlock(&hdmi_cec_data.lock); + return -EACCES; + } +- /* Ensure that there is only one writer who is the only listener of tx_cec_queue */ ++ /* Ensure that there is only one writer who is the unique listener of tx_cec_queue */ + if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) { + mutex_unlock(&hdmi_cec_data.lock); + return -EBUSY; +@@ -358,13 +356,11 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + return ret; + } + ++ + void hdmi_cec_start_device(void) + { + u8 val; + +- if (!hdmi_cec_ready || hdmi_cec_started) +- return; +- + val = hdmi_readb(HDMI_MC_CLKDIS); + val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; + hdmi_writeb(val, HDMI_MC_CLKDIS); +@@ -377,11 +373,7 @@ void hdmi_cec_start_device(void) + hdmi_writeb(val, HDMI_CEC_MASK); + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); + hdmi_cec_data.link_status = hdmi_readb(HDMI_PHY_STAT0) & 0x02; +- mutex_lock(&hdmi_cec_data.lock); + hdmi_cec_data.cec_state = true; +- mutex_unlock(&hdmi_cec_data.lock); +- +- hdmi_cec_started = 1; + } + EXPORT_SYMBOL(hdmi_cec_start_device); + +@@ -389,9 +381,6 @@ void hdmi_cec_stop_device(void) + { + u8 val; + +- if (!hdmi_cec_ready || !hdmi_cec_started) +- return; +- + hdmi_writeb(0x10, HDMI_CEC_CTRL); + val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST | \ + HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; +@@ -401,11 +390,7 @@ void hdmi_cec_stop_device(void) + val = hdmi_readb(HDMI_MC_CLKDIS); + val |= HDMI_MC_CLKDIS_CECCLK_DISABLE; + hdmi_writeb(val, HDMI_MC_CLKDIS); +- mutex_lock(&hdmi_cec_data.lock); + hdmi_cec_data.cec_state = false; +- mutex_unlock(&hdmi_cec_data.lock); +- +- hdmi_cec_started = 0; + } + EXPORT_SYMBOL(hdmi_cec_stop_device); + +@@ -579,7 +564,6 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + INIT_DELAYED_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker); + + dev_info(&pdev->dev, "HDMI CEC initialized\n"); +- hdmi_cec_ready = 1; + goto out; + + err_out_class: +-- +1.9.1 + + +============================================================== +file 0002-MXC-CEC-Flush-pending-events-at-close.patch +============================================================== + +From 3309b17795c3c9cc1b457caf154f0f2e87121aa3 Mon Sep 17 00:00:00 2001 +From: wolfgar +Date: Mon, 31 Oct 2016 10:59:44 +0100 +Subject: [PATCH] MXC-CEC: Flush pending events at close + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index f787274..210d764 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -465,11 +465,18 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + */ + static int hdmi_cec_release(struct inode *inode, struct file *filp) + { ++ struct hdmi_cec_event *event, *tmp_event; + mutex_lock(&hdmi_cec_data.lock); + if (open_count) { + open_count = 0; + hdmi_cec_data.cec_state = false; + hdmi_cec_data.Logical_address = 15; ++ ++ /* Flush eventual events which have not been read by user space */ ++ list_for_each_entry_safe(event, tmp_event, &head, list) { ++ list_del(&event->list); ++ vfree(event); ++ } + } + mutex_unlock(&hdmi_cec_data.lock); + +-- +1.9.1 + + +============================================================== +file 0003-MXC-CEC-Remove-embedded-logics-from-the-driver-so-th.patch +============================================================== + +From 66ca526351cb7fe726e8e7ae19818e09e63fa19d Mon Sep 17 00:00:00 2001 +From: wolfgar +Date: Mon, 31 Oct 2016 11:00:46 +0100 +Subject: [PATCH] MXC-CEC: Remove embedded logics from the driver so that + libcec is responsible for all this work + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 34 ++++++---------------------------- + 1 file changed, 6 insertions(+), 28 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index 210d764..da34f27 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -132,7 +132,7 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) void mxc_hdmi_cec_handle(u16 cec_stat) { @@ -26,7 +166,7 @@ index c30237e..fb66c25 100644 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) +@@ -167,27 +167,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) { @@ -58,7 +198,7 @@ index c30237e..fb66c25 100644 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, +@@ -403,7 +390,7 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, u_long arg) { int ret = 0, status = 0; @@ -67,7 +207,7 @@ index c30237e..fb66c25 100644 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, +@@ -427,15 +414,6 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, hdmi_writeb(0, HDMI_CEC_ADDR_L); } else ret = -EINVAL; @@ -83,9 +223,1598 @@ index c30237e..fb66c25 100644 mutex_unlock(&hdmi_cec_data.lock); break; case HDMICEC_IOC_STARTDEVICE: +-- +1.9.1 + ============================================================== -file 0005-assign-minor-to-vhci.patch +file 0004-MXC-CEC-Remove-some-more-unneeded-guards-variables-a.patch +============================================================== + +From 6e0fb54a084d886f1c55660485bbdde3dea57057 Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:37 +0100 +Subject: [PATCH] MXC-CEC: Remove some more unneeded guards, variables and + comments + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 82 ++++++++++++++----------------------- + 1 file changed, 31 insertions(+), 51 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index da34f27..ffaf20c 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -47,24 +47,22 @@ + #include "mxc_hdmi-cec.h" + + +-#define MAX_MESSAGE_LEN 17 ++#define MAX_MESSAGE_LEN 17 + +-#define MESSAGE_TYPE_RECEIVE_SUCCESS 1 ++#define MESSAGE_TYPE_RECEIVE_SUCCESS 1 + #define MESSAGE_TYPE_NOACK 2 +-#define MESSAGE_TYPE_DISCONNECTED 3 ++#define MESSAGE_TYPE_DISCONNECTED 3 + #define MESSAGE_TYPE_CONNECTED 4 +-#define MESSAGE_TYPE_SEND_SUCCESS 5 ++#define MESSAGE_TYPE_SEND_SUCCESS 5 + +-#define CEC_TX_INPROGRESS -1 +-#define CEC_TX_AVAIL 0 ++#define CEC_TX_INPROGRESS -1 ++#define CEC_TX_AVAIL 0 + + struct hdmi_cec_priv { + int receive_error; + int send_error; + u8 Logical_address; + bool cec_state; +- u8 last_msg[MAX_MESSAGE_LEN]; +- u8 msg_len; + int tx_answer; + u16 latest_cec_stat; + u8 link_status; +@@ -223,11 +221,6 @@ static void mxc_hdmi_cec_worker(struct work_struct *work) + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); + } + +-/*! +- * @brief open function for cec file operation +- * +- * @return 0 on success or negative error code on error +- */ + static int hdmi_cec_open(struct inode *inode, struct file *filp) + { + mutex_lock(&hdmi_cec_data.lock); +@@ -247,10 +240,9 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) + { + struct hdmi_cec_event *event = NULL; ++ + pr_debug("function : %s\n", __func__); + +- if (!open_count) +- return -ENODEV; + mutex_lock(&hdmi_cec_data.lock); + if (false == hdmi_cec_data.cec_state) { + mutex_unlock(&hdmi_cec_data.lock); +@@ -292,8 +284,6 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + + pr_debug("function : %s\n", __func__); + +- if (!open_count) +- return -ENODEV; + mutex_lock(&hdmi_cec_data.lock); + if (false == hdmi_cec_data.cec_state) { + mutex_unlock(&hdmi_cec_data.lock); +@@ -321,8 +311,6 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + val = hdmi_readb(HDMI_CEC_CTRL); + val |= 0x01; + hdmi_writeb(val, HDMI_CEC_CTRL); +- memcpy(hdmi_cec_data.last_msg, msg, msg_len); +- hdmi_cec_data.msg_len = msg_len; + mutex_unlock(&hdmi_cec_data.lock); + + ret = wait_event_interruptible_timeout(tx_cec_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); +@@ -336,9 +324,9 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + /* msg correctly sent */ + ret = msg_len; + else +- ret = -EIO; ++ ret = -EIO; + +- tx_out: ++tx_out: + hdmi_cec_data.tx_answer = CEC_TX_AVAIL; + return ret; + } +@@ -381,20 +369,15 @@ void hdmi_cec_stop_device(void) + } + EXPORT_SYMBOL(hdmi_cec_stop_device); + +-/*! +- * @brief IO ctrl function for vpu file operation +- * @param cmd IO ctrl command +- * @return 0 on success or negative error code on error +- */ + static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + u_long arg) + { + int ret = 0, status = 0; + u8 val = 0; + struct mxc_edid_cfg hdmi_edid_cfg; ++ + pr_debug("function : %s\n", __func__); +- if (!open_count) +- return -ENODEV; ++ + switch (cmd) { + case HDMICEC_IOC_SETLOGICALADDRESS: + mutex_lock(&hdmi_cec_data.lock); +@@ -437,13 +420,12 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + return ret; + } + +-/*! +- * @brief Release function for vpu file operation +- * @return 0 on success or negative error code on error +- */ + static int hdmi_cec_release(struct inode *inode, struct file *filp) + { + struct hdmi_cec_event *event, *tmp_event; ++ ++ pr_debug("function : %s\n", __func__); ++ + mutex_lock(&hdmi_cec_data.lock); + if (open_count) { + open_count = 0; +@@ -473,7 +455,7 @@ static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) + mask = (POLLOUT | POLLWRNORM); + mutex_lock(&hdmi_cec_data.lock); + if (!list_empty(&head)) +- mask |= (POLLIN | POLLRDNORM); ++ mask |= (POLLIN | POLLRDNORM); + mutex_unlock(&hdmi_cec_data.lock); + return mask; + } +@@ -499,14 +481,14 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + + hdmi_cec_major = register_chrdev(hdmi_cec_major, "mxc_hdmi_cec", &hdmi_cec_fops); + if (hdmi_cec_major < 0) { +- dev_err(&pdev->dev, "hdmi_cec: unable to get a major for HDMI CEC\n"); ++ dev_err(&pdev->dev, "Unable to get a major for HDMI CEC\n"); + err = -EBUSY; + goto out; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(res == NULL)) { +- dev_err(&pdev->dev, "hdmi_cec:No HDMI irq line provided\n"); ++ dev_err(&pdev->dev, "No HDMI irq line provided\n"); + goto err_out_chrdev; + } + spin_lock_init(&hdmi_cec_data.irq_lock); +@@ -514,7 +496,7 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + err = devm_request_irq(&pdev->dev, irq, mxc_hdmi_cec_isr, IRQF_SHARED, + dev_name(&pdev->dev), &hdmi_cec_data); + if (err < 0) { +- dev_err(&pdev->dev, "hdmi_cec:Unable to request irq: %d\n", err); ++ dev_err(&pdev->dev, "Unable to request irq: %d\n", err); + goto err_out_chrdev; + } + +@@ -524,8 +506,8 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + goto err_out_chrdev; + } + +- temp_class = device_create(hdmi_cec_class, NULL, MKDEV(hdmi_cec_major, 0), +- NULL, "mxc_hdmi_cec"); ++ temp_class = device_create(hdmi_cec_class, NULL, ++ MKDEV(hdmi_cec_major, 0), NULL, "mxc_hdmi_cec"); + if (IS_ERR(temp_class)) { + err = PTR_ERR(temp_class); + goto err_out_class; +@@ -533,7 +515,7 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { +- dev_err(&pdev->dev, "can't get/select CEC pinctrl\n"); ++ dev_err(&pdev->dev, "Can't get/select CEC pinctrl\n"); + goto err_out_class; + } + +@@ -562,14 +544,13 @@ out: + + static int hdmi_cec_dev_remove(struct platform_device *pdev) + { +- if (hdmi_cec_data.cec_state) +- hdmi_cec_stop_device(); +- if (hdmi_cec_major > 0) { +- device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0)); +- class_destroy(hdmi_cec_class); +- unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec"); +- hdmi_cec_major = 0; +-} ++ hdmi_cec_stop_device(); ++ ++ device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0)); ++ class_destroy(hdmi_cec_class); ++ unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec"); ++ hdmi_cec_major = 0; ++ + return 0; + } + +@@ -583,9 +564,9 @@ static struct platform_driver mxc_hdmi_cec_driver = { + .probe = hdmi_cec_dev_probe, + .remove = hdmi_cec_dev_remove, + .driver = { +- .name = "mxc_hdmi_cec", +- .of_match_table = imx_hdmi_cec_match, +- }, ++ .name = "mxc_hdmi_cec", ++ .of_match_table = imx_hdmi_cec_match, ++ }, + }; + + module_platform_driver(mxc_hdmi_cec_driver); +@@ -594,4 +575,3 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc."); + MODULE_DESCRIPTION("Linux HDMI CEC driver for Freescale i.MX/MXC"); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("platform:mxc_hdmi_cec"); +- +-- +1.9.1 + + +============================================================== +file 0005-MXC-CEC-Restructure-code-to-avoid-race-conditions.patch +============================================================== + +From 52969de0f8a8afb87ccc43fe568e11f9a3cfccdf Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:38 +0100 +Subject: [PATCH] MXC-CEC: Restructure code to avoid race conditions + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 258 ++++++++++++++++++++++++------------ + drivers/video/mxc/mxc_hdmi.c | 7 +- + include/linux/mfd/mxc-hdmi-core.h | 1 + + 3 files changed, 175 insertions(+), 91 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index ffaf20c..f62bcbc 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -58,16 +58,32 @@ + #define CEC_TX_INPROGRESS -1 + #define CEC_TX_AVAIL 0 + ++/* These flags must not collide with HDMI_IH_CEC_STAT0_xxxx */ ++#define CEC_STAT0_EX_CONNECTED 0x0100 ++#define CEC_STAT0_EX_DISCONNECTED 0x0200 ++ ++#define CEC_STAT0_MASK_ALL (HDMI_IH_CEC_STAT0_WAKEUP | \ ++ HDMI_IH_CEC_STAT0_ERROR_FOLL | \ ++ HDMI_IH_CEC_STAT0_ARB_LOST | \ ++ HDMI_IH_CEC_STAT0_ERROR_INIT | \ ++ HDMI_IH_CEC_STAT0_NACK | \ ++ HDMI_IH_CEC_STAT0_EOM | \ ++ HDMI_IH_CEC_STAT0_DONE) ++ ++#define CEC_STAT0_MASK_DEFAULT (HDMI_IH_CEC_STAT0_WAKEUP | \ ++ HDMI_IH_CEC_STAT0_ERROR_FOLL | \ ++ HDMI_IH_CEC_STAT0_ARB_LOST) ++ + struct hdmi_cec_priv { + int receive_error; + int send_error; + u8 Logical_address; +- bool cec_state; ++ u8 cec_state; + int tx_answer; +- u16 latest_cec_stat; ++ u32 cec_stat0; + u8 link_status; + spinlock_t irq_lock; +- struct delayed_work hdmi_cec_work; ++ struct work_struct hdmi_cec_work; + struct mutex lock; + }; + +@@ -81,68 +97,79 @@ struct hdmi_cec_event { + + static LIST_HEAD(head); + ++static int hdmi_cec_irq; + static int hdmi_cec_major; + static struct class *hdmi_cec_class; + static struct hdmi_cec_priv hdmi_cec_data; + static u8 open_count; ++static u8 want_start; ++static u8 link_status; ++static u8 is_initialized; + + static wait_queue_head_t hdmi_cec_queue; + static wait_queue_head_t tx_cec_queue; + ++ ++static u32 get_hpd_stat(struct hdmi_cec_priv *hdmi_cec) ++{ ++ u32 cec_stat0 = 0; ++ ++ if (hdmi_cec->link_status ^ link_status) { ++ hdmi_cec->link_status = link_status; ++ if (hdmi_cec->link_status) ++ cec_stat0 = CEC_STAT0_EX_CONNECTED; ++ else ++ cec_stat0 = CEC_STAT0_EX_DISCONNECTED; ++ } ++ ++ return cec_stat0; ++} ++ + static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + { + struct hdmi_cec_priv *hdmi_cec = data; +- u16 cec_stat = 0; + unsigned long flags; +- u8 phy_stat0; ++ u8 cec_stat; + + spin_lock_irqsave(&hdmi_cec->irq_lock, flags); + +- hdmi_writeb(0x7f, HDMI_IH_MUTE_CEC_STAT0); ++ hdmi_writeb(CEC_STAT0_MASK_ALL, HDMI_IH_MUTE_CEC_STAT0); + +- cec_stat = hdmi_readb(HDMI_IH_CEC_STAT0); ++ cec_stat = hdmi_readb(HDMI_IH_CEC_STAT0) & CEC_STAT0_MASK_ALL; + hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0); +- phy_stat0 = hdmi_readb(HDMI_PHY_STAT0) & 0x02; +- if (hdmi_cec->link_status ^ phy_stat0) { +- /* HPD value changed */ +- hdmi_cec->link_status = phy_stat0; +- if (hdmi_cec->link_status) +- cec_stat |= 0x80; /* Connected */ +- else +- cec_stat |= 0x100; /* Disconnected */ +- } +- if ((cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | \ +- HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | \ +- HDMI_IH_CEC_STAT0_DONE | 0x180)) == 0) { ++ ++ if ((cec_stat & ~CEC_STAT0_MASK_DEFAULT) == 0) { ++ if (hdmi_cec->cec_state) ++ hdmi_writeb(CEC_STAT0_MASK_DEFAULT, HDMI_IH_MUTE_CEC_STAT0); + spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); +- return IRQ_HANDLED; ++ return IRQ_NONE; + } +- pr_debug("HDMI CEC interrupt received\n"); +- /* FIXME : there is a race with latest_cec_stat */ +- hdmi_cec->latest_cec_stat = cec_stat ; + +- schedule_delayed_work(&(hdmi_cec->hdmi_cec_work), msecs_to_jiffies(20)); ++ pr_debug("HDMI-CEC: interrupt received\n"); ++ ++ hdmi_cec->cec_stat0 = cec_stat | get_hpd_stat(hdmi_cec); ++ schedule_work(&hdmi_cec->hdmi_cec_work); + + spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); + + return IRQ_HANDLED; + } + +-void mxc_hdmi_cec_handle(u16 cec_stat) ++static void mxc_hdmi_cec_handle(u32 cec_stat) + { + u8 i = 0; + struct hdmi_cec_event *event = NULL; +- /*The current transmission is successful (for initiator only).*/ ++ + if (!open_count) + return; + ++ /*The current transmission is successful (for initiator only).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_DONE) { + hdmi_cec_data.tx_answer = cec_stat; + wake_up(&tx_cec_queue); + } + /*EOM is detected so that the received data is ready in the receiver data buffer*/ + if (cec_stat & HDMI_IH_CEC_STAT0_EOM) { +- hdmi_writeb(0x02, HDMI_IH_CEC_STAT0); + event = vmalloc(sizeof(struct hdmi_cec_event)); + if (NULL == event) { + pr_err("%s: Not enough memory!\n", __func__); +@@ -181,8 +208,8 @@ void mxc_hdmi_cec_handle(u16 cec_stat) + hdmi_cec_data.receive_error++; + } + /*HDMI cable connected*/ +- if (cec_stat & 0x80) { +- pr_info("HDMI link connected\n"); ++ if (cec_stat & CEC_STAT0_EX_CONNECTED) { ++ pr_info("HDMI-CEC: link connected\n"); + event = vmalloc(sizeof(struct hdmi_cec_event)); + if (NULL == event) { + pr_err("%s: Not enough memory\n", __func__); +@@ -196,8 +223,8 @@ void mxc_hdmi_cec_handle(u16 cec_stat) + wake_up(&hdmi_cec_queue); + } + /*HDMI cable disconnected*/ +- if (cec_stat & 0x100) { +- pr_info("HDMI link disconnected\n"); ++ if (cec_stat & CEC_STAT0_EX_DISCONNECTED) { ++ pr_info("HDMI-CEC: link disconnected\n"); + event = vmalloc(sizeof(struct hdmi_cec_event)); + if (NULL == event) { + pr_err("%s: Not enough memory!\n", __func__); +@@ -210,15 +237,19 @@ void mxc_hdmi_cec_handle(u16 cec_stat) + mutex_unlock(&hdmi_cec_data.lock); + wake_up(&hdmi_cec_queue); + } +- return; + } +-EXPORT_SYMBOL(mxc_hdmi_cec_handle); ++ + static void mxc_hdmi_cec_worker(struct work_struct *work) + { +- u8 val; +- mxc_hdmi_cec_handle(hdmi_cec_data.latest_cec_stat); +- val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST; +- hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); ++ unsigned long flags; ++ ++ mxc_hdmi_cec_handle(hdmi_cec_data.cec_stat0); ++ ++ spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); ++ hdmi_cec_data.cec_stat0 = 0; ++ if (hdmi_cec_data.cec_state) ++ hdmi_writeb(CEC_STAT0_MASK_DEFAULT, HDMI_IH_MUTE_CEC_STAT0); ++ spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); + } + + static int hdmi_cec_open(struct inode *inode, struct file *filp) +@@ -244,7 +275,7 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + pr_debug("function : %s\n", __func__); + + mutex_lock(&hdmi_cec_data.lock); +- if (false == hdmi_cec_data.cec_state) { ++ if (!hdmi_cec_data.cec_state) { + mutex_unlock(&hdmi_cec_data.lock); + return -EACCES; + } +@@ -278,32 +309,31 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) + { +- int ret = 0 , i = 0; +- u8 msg[MAX_MESSAGE_LEN]; +- u8 msg_len = 0, val = 0; ++ int ret = 0; ++ u8 i, msg_len, val; ++ u8 msg[MAX_MESSAGE_LEN] = { 0 }; + + pr_debug("function : %s\n", __func__); + + mutex_lock(&hdmi_cec_data.lock); +- if (false == hdmi_cec_data.cec_state) { +- mutex_unlock(&hdmi_cec_data.lock); +- return -EACCES; +- } +- /* Ensure that there is only one writer who is the unique listener of tx_cec_queue */ +- if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) { ++ ++ if (!hdmi_cec_data.cec_state) ++ ret = -EACCES; ++ else if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) ++ ret = -EBUSY; ++ else if (count > MAX_MESSAGE_LEN) ++ ret = -EINVAL; ++ else if (copy_from_user(&msg, buf, count)) ++ ret = -EACCES; ++ ++ if (ret) { + mutex_unlock(&hdmi_cec_data.lock); +- return -EBUSY; ++ return ret; + } +- mutex_unlock(&hdmi_cec_data.lock); +- if (count > MAX_MESSAGE_LEN) +- return -EINVAL; +- memset(&msg, 0, MAX_MESSAGE_LEN); +- ret = copy_from_user(&msg, buf, count); +- if (ret) +- return -EACCES; +- mutex_lock(&hdmi_cec_data.lock); ++ + hdmi_cec_data.send_error = 0; + hdmi_cec_data.tx_answer = CEC_TX_INPROGRESS; ++ + msg_len = count; + hdmi_writeb(msg_len, HDMI_CEC_TX_CNT); + for (i = 0; i < msg_len; i++) +@@ -311,9 +341,11 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + val = hdmi_readb(HDMI_CEC_CTRL); + val |= 0x01; + hdmi_writeb(val, HDMI_CEC_CTRL); ++ + mutex_unlock(&hdmi_cec_data.lock); + +- ret = wait_event_interruptible_timeout(tx_cec_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); ++ ret = wait_event_interruptible_timeout( ++ tx_cec_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); + + if (ret < 0) { + ret = -ERESTARTSYS; +@@ -331,10 +363,37 @@ tx_out: + return ret; + } + ++void hdmi_cec_hpd_changed(unsigned int state) ++{ ++ unsigned long flags; ++ u32 cec_stat0; ++ ++ pr_debug("function : %s\n", __func__); ++ ++ link_status = state & 1; ++ ++ if (is_initialized) { ++ spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); ++ cec_stat0 = get_hpd_stat(&hdmi_cec_data); ++ spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); ++ ++ if (cec_stat0) ++ mxc_hdmi_cec_handle(cec_stat0); ++ } ++} ++EXPORT_SYMBOL(hdmi_cec_hpd_changed); + + void hdmi_cec_start_device(void) + { + u8 val; ++ unsigned long flags; ++ ++ if (!is_initialized) { ++ want_start = 1; ++ return; ++ } ++ ++ spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); + + val = hdmi_readb(HDMI_MC_CLKDIS); + val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; +@@ -342,30 +401,44 @@ void hdmi_cec_start_device(void) + hdmi_writeb(0x02, HDMI_CEC_CTRL); + /* Force read unlock */ + hdmi_writeb(0x0, HDMI_CEC_LOCK); ++ + val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; + hdmi_writeb(val, HDMI_CEC_POLARITY); +- val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST; ++ ++ val = CEC_STAT0_MASK_DEFAULT; + hdmi_writeb(val, HDMI_CEC_MASK); + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); +- hdmi_cec_data.link_status = hdmi_readb(HDMI_PHY_STAT0) & 0x02; ++ hdmi_cec_data.link_status = link_status; + hdmi_cec_data.cec_state = true; ++ ++ spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); + } + EXPORT_SYMBOL(hdmi_cec_start_device); + + void hdmi_cec_stop_device(void) + { + u8 val; ++ unsigned long flags; + ++ if (!is_initialized) { ++ want_start = 0; ++ return; ++ } ++ ++ spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); ++ ++ hdmi_cec_data.cec_state = false; + hdmi_writeb(0x10, HDMI_CEC_CTRL); +- val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST | \ +- HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; ++ val = CEC_STAT0_MASK_ALL; + hdmi_writeb(val, HDMI_CEC_MASK); + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); ++ + hdmi_writeb(0x0, HDMI_CEC_POLARITY); + val = hdmi_readb(HDMI_MC_CLKDIS); + val |= HDMI_MC_CLKDIS_CECCLK_DISABLE; + hdmi_writeb(val, HDMI_MC_CLKDIS); +- hdmi_cec_data.cec_state = false; ++ ++ spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); + } + EXPORT_SYMBOL(hdmi_cec_stop_device); + +@@ -381,7 +454,7 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + switch (cmd) { + case HDMICEC_IOC_SETLOGICALADDRESS: + mutex_lock(&hdmi_cec_data.lock); +- if (false == hdmi_cec_data.cec_state) { ++ if (!hdmi_cec_data.cec_state) { + mutex_unlock(&hdmi_cec_data.lock); + pr_err("Trying to set logical address while not started\n"); + return -EACCES; +@@ -474,32 +547,23 @@ const struct file_operations hdmi_cec_fops = { + static int hdmi_cec_dev_probe(struct platform_device *pdev) + { + int err = 0; +- struct device *temp_class; +- struct resource *res; + struct pinctrl *pinctrl; +- int irq = platform_get_irq(pdev, 0); ++ struct device *temp_class; ++ ++ hdmi_cec_irq = platform_get_irq(pdev, 0); ++ if (hdmi_cec_irq < 0) { ++ dev_err(&pdev->dev, "No HDMI irq line provided\n"); ++ err = -ENXIO; ++ goto err_out; ++ } + + hdmi_cec_major = register_chrdev(hdmi_cec_major, "mxc_hdmi_cec", &hdmi_cec_fops); + if (hdmi_cec_major < 0) { + dev_err(&pdev->dev, "Unable to get a major for HDMI CEC\n"); + err = -EBUSY; +- goto out; ++ goto err_out; + } + +- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +- if (unlikely(res == NULL)) { +- dev_err(&pdev->dev, "No HDMI irq line provided\n"); +- goto err_out_chrdev; +- } +- spin_lock_init(&hdmi_cec_data.irq_lock); +- +- err = devm_request_irq(&pdev->dev, irq, mxc_hdmi_cec_isr, IRQF_SHARED, +- dev_name(&pdev->dev), &hdmi_cec_data); +- if (err < 0) { +- dev_err(&pdev->dev, "Unable to request irq: %d\n", err); +- goto err_out_chrdev; +- } +- + hdmi_cec_class = class_create(THIS_MODULE, "mxc_hdmi_cec"); + if (IS_ERR(hdmi_cec_class)) { + err = PTR_ERR(hdmi_cec_class); +@@ -507,7 +571,7 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + } + + temp_class = device_create(hdmi_cec_class, NULL, +- MKDEV(hdmi_cec_major, 0), NULL, "mxc_hdmi_cec"); ++ MKDEV(hdmi_cec_major, 0), NULL, "mxc_hdmi_cec"); + if (IS_ERR(temp_class)) { + err = PTR_ERR(temp_class); + goto err_out_class; +@@ -516,29 +580,44 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) { + dev_err(&pdev->dev, "Can't get/select CEC pinctrl\n"); ++ err = PTR_ERR(pinctrl); + goto err_out_class; + } + ++ INIT_LIST_HEAD(&head); ++ + init_waitqueue_head(&hdmi_cec_queue); + init_waitqueue_head(&tx_cec_queue); + +- INIT_LIST_HEAD(&head); +- + mutex_init(&hdmi_cec_data.lock); ++ spin_lock_init(&hdmi_cec_data.irq_lock); ++ + hdmi_cec_data.Logical_address = 15; + hdmi_cec_data.tx_answer = CEC_TX_AVAIL; ++ INIT_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker); ++ + platform_set_drvdata(pdev, &hdmi_cec_data); +- INIT_DELAYED_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker); + +- dev_info(&pdev->dev, "HDMI CEC initialized\n"); +- goto out; ++ err = devm_request_irq(&pdev->dev, hdmi_cec_irq, mxc_hdmi_cec_isr, ++ IRQF_SHARED, dev_name(&pdev->dev), &hdmi_cec_data); ++ if (err < 0) { ++ dev_err(&pdev->dev, "Unable to request irq%d: %d\n", hdmi_cec_irq, err); ++ goto err_out_class; ++ } ++ ++ is_initialized = 1; ++ if (want_start) ++ hdmi_cec_start_device(); ++ ++ pr_info("HDMI-CEC initialized\n"); ++ return 0; + + err_out_class: + device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0)); + class_destroy(hdmi_cec_class); + err_out_chrdev: + unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec"); +-out: ++err_out: + return err; + } + +@@ -546,6 +625,9 @@ static int hdmi_cec_dev_remove(struct platform_device *pdev) + { + hdmi_cec_stop_device(); + ++ is_initialized = 0; ++ devm_free_irq(&pdev->dev, hdmi_cec_irq, &hdmi_cec_data); ++ + device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0)); + class_destroy(hdmi_cec_class); + unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec"); +diff --git a/drivers/video/mxc/mxc_hdmi.c b/drivers/video/mxc/mxc_hdmi.c +index 55c39e1..591dde4 100644 +--- a/drivers/video/mxc/mxc_hdmi.c ++++ b/drivers/video/mxc/mxc_hdmi.c +@@ -212,7 +212,6 @@ static bool hdmi_inited; + static bool hdcp_init; + + extern const struct fb_videomode mxc_cea_mode[64]; +-extern void mxc_hdmi_cec_handle(u16 cec_stat); + + extern int mxcfb_blank(int blank, struct fb_info *info); + +@@ -2204,7 +2203,8 @@ static void hotplug_worker(struct work_struct *work) + sprintf(event_string, "EVENT=plugin"); + kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp); + #ifdef CONFIG_MXC_HDMI_CEC +- mxc_hdmi_cec_handle(0x80); ++ if (hdmi->edid_cfg.hdmi_cap) ++ hdmi_cec_hpd_changed(1); + #endif + } else { + /* Plugout event */ +@@ -2216,7 +2216,8 @@ static void hotplug_worker(struct work_struct *work) + sprintf(event_string, "EVENT=plugout"); + kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp); + #ifdef CONFIG_MXC_HDMI_CEC +- mxc_hdmi_cec_handle(0x100); ++ if (hdmi->edid_cfg.hdmi_cap) ++ hdmi_cec_hpd_changed(0); + #endif + } + } +diff --git a/include/linux/mfd/mxc-hdmi-core.h b/include/linux/mfd/mxc-hdmi-core.h +index db16f5f..6c9c36d 100644 +--- a/include/linux/mfd/mxc-hdmi-core.h ++++ b/include/linux/mfd/mxc-hdmi-core.h +@@ -64,5 +64,6 @@ int check_hdmi_state(void); + + void hdmi_cec_start_device(void); + void hdmi_cec_stop_device(void); ++void hdmi_cec_hpd_changed(unsigned int state); + + #endif +-- +1.9.1 + + +============================================================== +file 0006-MXC-CEC-Rename-variables-minor-code-style-cleanups.patch +============================================================== + +From 07f57cc3eea59941d627fb46c95776ce67309e5f Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:38 +0100 +Subject: [PATCH] MXC-CEC: Rename variables, minor code style cleanups + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 112 ++++++++++++++++++------------------ + 1 file changed, 56 insertions(+), 56 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index f62bcbc..b0619ac 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -75,13 +75,14 @@ + HDMI_IH_CEC_STAT0_ARB_LOST) + + struct hdmi_cec_priv { +- int receive_error; +- int send_error; +- u8 Logical_address; +- u8 cec_state; ++ int receive_error; ++ int send_error; + int tx_answer; + u32 cec_stat0; ++ u8 logical_address; ++ u8 is_started; + u8 link_status; ++ u8 open_count; + spinlock_t irq_lock; + struct work_struct hdmi_cec_work; + struct mutex lock; +@@ -95,19 +96,18 @@ struct hdmi_cec_event { + }; + + +-static LIST_HEAD(head); ++static LIST_HEAD(ev_pending); + + static int hdmi_cec_irq; + static int hdmi_cec_major; + static struct class *hdmi_cec_class; + static struct hdmi_cec_priv hdmi_cec_data; +-static u8 open_count; + static u8 want_start; + static u8 link_status; + static u8 is_initialized; + +-static wait_queue_head_t hdmi_cec_queue; +-static wait_queue_head_t tx_cec_queue; ++static wait_queue_head_t rx_queue; ++static wait_queue_head_t tx_queue; + + + static u32 get_hpd_stat(struct hdmi_cec_priv *hdmi_cec) +@@ -139,7 +139,7 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0); + + if ((cec_stat & ~CEC_STAT0_MASK_DEFAULT) == 0) { +- if (hdmi_cec->cec_state) ++ if (hdmi_cec->is_started) + hdmi_writeb(CEC_STAT0_MASK_DEFAULT, HDMI_IH_MUTE_CEC_STAT0); + spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); + return IRQ_NONE; +@@ -160,13 +160,13 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + u8 i = 0; + struct hdmi_cec_event *event = NULL; + +- if (!open_count) ++ if (!hdmi_cec_data.open_count) + return; + + /*The current transmission is successful (for initiator only).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_DONE) { + hdmi_cec_data.tx_answer = cec_stat; +- wake_up(&tx_cec_queue); ++ wake_up(&tx_queue); + } + /*EOM is detected so that the received data is ready in the receiver data buffer*/ + if (cec_stat & HDMI_IH_CEC_STAT0_EOM) { +@@ -186,14 +186,14 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0+i); + hdmi_writeb(0x0, HDMI_CEC_LOCK); + mutex_lock(&hdmi_cec_data.lock); +- list_add_tail(&event->list, &head); ++ list_add_tail(&event->list, &ev_pending); + mutex_unlock(&hdmi_cec_data.lock); +- wake_up(&hdmi_cec_queue); ++ wake_up(&rx_queue); + } + /*An error is detected on cec line (for initiator only). */ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) { + hdmi_cec_data.tx_answer = cec_stat; +- wake_up(&tx_cec_queue); ++ wake_up(&tx_queue); + return; + } + /*A frame is not acknowledged in a directly addressed message. Or a frame is negatively acknowledged in +@@ -201,7 +201,7 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + 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); ++ wake_up(&tx_queue); + } + /*An error is notified by a follower. Abnormal logic data bit error (for follower).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL) { +@@ -218,9 +218,9 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + memset(event, 0, sizeof(struct hdmi_cec_event)); + event->event_type = MESSAGE_TYPE_CONNECTED; + mutex_lock(&hdmi_cec_data.lock); +- list_add_tail(&event->list, &head); ++ list_add_tail(&event->list, &ev_pending); + mutex_unlock(&hdmi_cec_data.lock); +- wake_up(&hdmi_cec_queue); ++ wake_up(&rx_queue); + } + /*HDMI cable disconnected*/ + if (cec_stat & CEC_STAT0_EX_DISCONNECTED) { +@@ -233,9 +233,9 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + memset(event, 0, sizeof(struct hdmi_cec_event)); + event->event_type = MESSAGE_TYPE_DISCONNECTED; + mutex_lock(&hdmi_cec_data.lock); +- list_add_tail(&event->list, &head); ++ list_add_tail(&event->list, &ev_pending); + mutex_unlock(&hdmi_cec_data.lock); +- wake_up(&hdmi_cec_queue); ++ wake_up(&rx_queue); + } + } + +@@ -247,22 +247,22 @@ static void mxc_hdmi_cec_worker(struct work_struct *work) + + spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); + hdmi_cec_data.cec_stat0 = 0; +- if (hdmi_cec_data.cec_state) ++ if (hdmi_cec_data.is_started) + hdmi_writeb(CEC_STAT0_MASK_DEFAULT, HDMI_IH_MUTE_CEC_STAT0); + spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); + } + +-static int hdmi_cec_open(struct inode *inode, struct file *filp) ++static int hdmi_cec_open(struct inode *inode, struct file *file) + { + mutex_lock(&hdmi_cec_data.lock); +- if (open_count) { ++ if (hdmi_cec_data.open_count) { + mutex_unlock(&hdmi_cec_data.lock); + return -EBUSY; + } +- open_count = 1; +- filp->private_data = (void *)(&hdmi_cec_data); +- hdmi_cec_data.Logical_address = 15; +- hdmi_cec_data.cec_state = false; ++ hdmi_cec_data.open_count = 1; ++ file->private_data = (void *)(&hdmi_cec_data); ++ hdmi_cec_data.logical_address = 15; ++ hdmi_cec_data.is_started = false; + mutex_unlock(&hdmi_cec_data.lock); + return 0; + } +@@ -275,26 +275,26 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + pr_debug("function : %s\n", __func__); + + mutex_lock(&hdmi_cec_data.lock); +- if (!hdmi_cec_data.cec_state) { ++ if (!hdmi_cec_data.is_started) { + mutex_unlock(&hdmi_cec_data.lock); + return -EACCES; + } + +- if (list_empty(&head)) { ++ if (list_empty(&ev_pending)) { + if (file->f_flags & O_NONBLOCK) { + mutex_unlock(&hdmi_cec_data.lock); + return -EAGAIN; + } else { + do { + mutex_unlock(&hdmi_cec_data.lock); +- if (wait_event_interruptible(hdmi_cec_queue, (!list_empty(&head)))) ++ if (wait_event_interruptible(rx_queue, !list_empty(&ev_pending))) + return -ERESTARTSYS; + mutex_lock(&hdmi_cec_data.lock); +- } while (list_empty(&head)); ++ } while (list_empty(&ev_pending)); + } + } + +- event = list_first_entry(&head, struct hdmi_cec_event, list); ++ event = list_first_entry(&ev_pending, struct hdmi_cec_event, list); + list_del(&event->list); + mutex_unlock(&hdmi_cec_data.lock); + if (copy_to_user(buf, event, +@@ -311,19 +311,19 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + { + int ret = 0; + u8 i, msg_len, val; +- u8 msg[MAX_MESSAGE_LEN] = { 0 }; ++ u8 msg[MAX_MESSAGE_LEN]; + + pr_debug("function : %s\n", __func__); + + mutex_lock(&hdmi_cec_data.lock); + +- if (!hdmi_cec_data.cec_state) ++ if (!hdmi_cec_data.is_started) + ret = -EACCES; + else if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) + ret = -EBUSY; + else if (count > MAX_MESSAGE_LEN) + ret = -EINVAL; +- else if (copy_from_user(&msg, buf, count)) ++ else if (copy_from_user(msg, buf, count)) + ret = -EACCES; + + if (ret) { +@@ -345,7 +345,7 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + mutex_unlock(&hdmi_cec_data.lock); + + ret = wait_event_interruptible_timeout( +- tx_cec_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); ++ tx_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); + + if (ret < 0) { + ret = -ERESTARTSYS; +@@ -409,7 +409,7 @@ void hdmi_cec_start_device(void) + hdmi_writeb(val, HDMI_CEC_MASK); + hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); + hdmi_cec_data.link_status = link_status; +- hdmi_cec_data.cec_state = true; ++ hdmi_cec_data.is_started = true; + + spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); + } +@@ -427,7 +427,7 @@ void hdmi_cec_stop_device(void) + + spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); + +- hdmi_cec_data.cec_state = false; ++ hdmi_cec_data.is_started = false; + hdmi_writeb(0x10, HDMI_CEC_CTRL); + val = CEC_STAT0_MASK_ALL; + hdmi_writeb(val, HDMI_CEC_MASK); +@@ -442,7 +442,7 @@ void hdmi_cec_stop_device(void) + } + EXPORT_SYMBOL(hdmi_cec_stop_device); + +-static long hdmi_cec_ioctl(struct file *filp, u_int cmd, ++static long hdmi_cec_ioctl(struct file *file, u_int cmd, + u_long arg) + { + int ret = 0, status = 0; +@@ -454,18 +454,18 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + switch (cmd) { + case HDMICEC_IOC_SETLOGICALADDRESS: + mutex_lock(&hdmi_cec_data.lock); +- if (!hdmi_cec_data.cec_state) { ++ if (!hdmi_cec_data.is_started) { + mutex_unlock(&hdmi_cec_data.lock); + pr_err("Trying to set logical address while not started\n"); + return -EACCES; + } +- hdmi_cec_data.Logical_address = (u8)arg; +- if (hdmi_cec_data.Logical_address <= 7) { +- val = 1 << hdmi_cec_data.Logical_address; ++ hdmi_cec_data.logical_address = (u8)arg; ++ if (hdmi_cec_data.logical_address <= 7) { ++ val = 1 << hdmi_cec_data.logical_address; + hdmi_writeb(val, HDMI_CEC_ADDR_L); + hdmi_writeb(0, HDMI_CEC_ADDR_H); +- } else if (hdmi_cec_data.Logical_address > 7 && hdmi_cec_data.Logical_address <= 15) { +- val = 1 << (hdmi_cec_data.Logical_address - 8); ++ } else if (hdmi_cec_data.logical_address > 7 && hdmi_cec_data.logical_address <= 15) { ++ val = 1 << (hdmi_cec_data.logical_address - 8); + hdmi_writeb(val, HDMI_CEC_ADDR_H); + hdmi_writeb(0, HDMI_CEC_ADDR_L); + } else +@@ -493,20 +493,20 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, + return ret; + } + +-static int hdmi_cec_release(struct inode *inode, struct file *filp) ++static int hdmi_cec_release(struct inode *inode, struct file *file) + { + struct hdmi_cec_event *event, *tmp_event; + + pr_debug("function : %s\n", __func__); + + mutex_lock(&hdmi_cec_data.lock); +- if (open_count) { +- open_count = 0; +- hdmi_cec_data.cec_state = false; +- hdmi_cec_data.Logical_address = 15; ++ if (hdmi_cec_data.open_count) { ++ hdmi_cec_data.open_count = 0; ++ hdmi_cec_data.is_started = false; ++ hdmi_cec_data.logical_address = 15; + + /* Flush eventual events which have not been read by user space */ +- list_for_each_entry_safe(event, tmp_event, &head, list) { ++ list_for_each_entry_safe(event, tmp_event, &ev_pending, list) { + list_del(&event->list); + vfree(event); + } +@@ -522,12 +522,12 @@ static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) + + pr_debug("function : %s\n", __func__); + +- poll_wait(file, &hdmi_cec_queue, wait); ++ poll_wait(file, &rx_queue, wait); + + /* Always writable */ + mask = (POLLOUT | POLLWRNORM); + mutex_lock(&hdmi_cec_data.lock); +- if (!list_empty(&head)) ++ if (!list_empty(&ev_pending)) + mask |= (POLLIN | POLLRDNORM); + mutex_unlock(&hdmi_cec_data.lock); + return mask; +@@ -584,15 +584,15 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + goto err_out_class; + } + +- INIT_LIST_HEAD(&head); ++ INIT_LIST_HEAD(&ev_pending); + +- init_waitqueue_head(&hdmi_cec_queue); +- init_waitqueue_head(&tx_cec_queue); ++ init_waitqueue_head(&rx_queue); ++ init_waitqueue_head(&tx_queue); + + mutex_init(&hdmi_cec_data.lock); + spin_lock_init(&hdmi_cec_data.irq_lock); + +- hdmi_cec_data.Logical_address = 15; ++ hdmi_cec_data.logical_address = 15; + hdmi_cec_data.tx_answer = CEC_TX_AVAIL; + INIT_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker); + +-- +1.9.1 + + +============================================================== +file 0007-MXC-CEC-Use-a-more-efficient-buffer-allocation-schem.patch +============================================================== + +From 0205ed2cfff7bbeb8ecd9a17cd068309468aa323 Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:38 +0100 +Subject: [PATCH] MXC-CEC: Use a more efficient buffer allocation scheme + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 170 ++++++++++++++++++++++++------------ + 1 file changed, 115 insertions(+), 55 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index b0619ac..22447cf 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -96,6 +96,7 @@ struct hdmi_cec_event { + }; + + ++static LIST_HEAD(ev_idle); + static LIST_HEAD(ev_pending); + + static int hdmi_cec_irq; +@@ -110,6 +111,60 @@ static wait_queue_head_t rx_queue; + static wait_queue_head_t tx_queue; + + ++static struct hdmi_cec_event *alloc_event(void) ++{ ++ int i; ++ struct hdmi_cec_event *event; ++ ++ if (list_empty(&ev_idle)) { ++ event = (void *)__get_free_page(GFP_KERNEL); ++ ++ if (!event) { ++ pr_err("HDMI-CEC: Failed to allocate event buffer\n"); ++ return NULL; ++ } ++ ++ for (i = 1; i < PAGE_SIZE / sizeof(struct hdmi_cec_event); i++) ++ list_add_tail(&event[i].list, &ev_idle); ++ ++ pr_debug("HDMI-CEC: Allocated event buffer page: @%08lx (%d)\n", ++ (unsigned long)event, i); ++ } else { ++ event = list_first_entry(&ev_idle, struct hdmi_cec_event, list); ++ list_del(&event->list); ++ } ++ ++ memset(event, 0, sizeof(struct hdmi_cec_event)); ++ return event; ++} ++ ++static void free_events(void) ++{ ++ struct hdmi_cec_event *event, *tmp_event; ++ ++ /* Flush events which have not been read by user space */ ++ list_splice_init(&ev_pending, &ev_idle); ++ ++ /* Find item(s) starting on a page boundary */ ++ list_for_each_entry_safe(event, tmp_event, &ev_idle, list) { ++ if (((unsigned long)event & ~PAGE_MASK) == 0) ++ list_move_tail(&event->list, &ev_pending); ++ } ++ ++ /* Discard idle list */ ++ INIT_LIST_HEAD(&ev_idle); ++ ++ /* Empty pending list and free page(s) */ ++ while (!list_empty(&ev_pending)) { ++ event = list_first_entry(&ev_pending, struct hdmi_cec_event, list); ++ list_del(&event->list); ++ free_page((unsigned long)event); ++ ++ pr_debug("HDMI-CEC: Freed event buffer page: @%08lx\n", ++ (unsigned long)event); ++ } ++} ++ + static u32 get_hpd_stat(struct hdmi_cec_priv *hdmi_cec) + { + u32 cec_stat0 = 0; +@@ -157,12 +212,29 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + + static void mxc_hdmi_cec_handle(u32 cec_stat) + { +- u8 i = 0; +- struct hdmi_cec_event *event = NULL; ++ int i; ++ struct hdmi_cec_event *event; + + if (!hdmi_cec_data.open_count) + return; + ++ /*HDMI cable connected: handle first*/ ++ if (cec_stat & CEC_STAT0_EX_CONNECTED) { ++ pr_info("HDMI-CEC: link connected\n"); ++ ++ mutex_lock(&hdmi_cec_data.lock); ++ event = alloc_event(); ++ if (!event) { ++ mutex_unlock(&hdmi_cec_data.lock); ++ return; ++ } ++ event->event_type = MESSAGE_TYPE_CONNECTED; ++ list_add_tail(&event->list, &ev_pending); ++ mutex_unlock(&hdmi_cec_data.lock); ++ ++ wake_up(&rx_queue); ++ } ++ + /*The current transmission is successful (for initiator only).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_DONE) { + hdmi_cec_data.tx_answer = cec_stat; +@@ -170,24 +242,28 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + } + /*EOM is detected so that the received data is ready in the receiver data buffer*/ + if (cec_stat & HDMI_IH_CEC_STAT0_EOM) { +- event = vmalloc(sizeof(struct hdmi_cec_event)); +- if (NULL == event) { +- pr_err("%s: Not enough memory!\n", __func__); ++ mutex_lock(&hdmi_cec_data.lock); ++ event = alloc_event(); ++ if (!event) { ++ mutex_unlock(&hdmi_cec_data.lock); + return; + } +- memset(event, 0, sizeof(struct hdmi_cec_event)); ++ + event->msg_len = hdmi_readb(HDMI_CEC_RX_CNT); +- if (!event->msg_len) { +- pr_err("%s: Invalid CEC message length!\n", __func__); ++ if (!event->msg_len || event->msg_len > MAX_MESSAGE_LEN) { ++ pr_err("HDMI-CEC: Invalid CEC message length\n"); ++ list_add_tail(&event->list, &ev_idle); ++ mutex_unlock(&hdmi_cec_data.lock); + return; + } ++ + event->event_type = MESSAGE_TYPE_RECEIVE_SUCCESS; + for (i = 0; i < event->msg_len; i++) +- event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0+i); +- hdmi_writeb(0x0, HDMI_CEC_LOCK); +- mutex_lock(&hdmi_cec_data.lock); ++ event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0 + i); ++ + list_add_tail(&event->list, &ev_pending); + mutex_unlock(&hdmi_cec_data.lock); ++ + wake_up(&rx_queue); + } + /*An error is detected on cec line (for initiator only). */ +@@ -207,34 +283,21 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL) { + hdmi_cec_data.receive_error++; + } +- /*HDMI cable connected*/ +- if (cec_stat & CEC_STAT0_EX_CONNECTED) { +- pr_info("HDMI-CEC: link connected\n"); +- event = vmalloc(sizeof(struct hdmi_cec_event)); +- if (NULL == event) { +- pr_err("%s: Not enough memory\n", __func__); +- return; +- } +- memset(event, 0, sizeof(struct hdmi_cec_event)); +- event->event_type = MESSAGE_TYPE_CONNECTED; +- mutex_lock(&hdmi_cec_data.lock); +- list_add_tail(&event->list, &ev_pending); +- mutex_unlock(&hdmi_cec_data.lock); +- wake_up(&rx_queue); +- } +- /*HDMI cable disconnected*/ ++ ++ /*HDMI cable disconnected: handle last*/ + if (cec_stat & CEC_STAT0_EX_DISCONNECTED) { + pr_info("HDMI-CEC: link disconnected\n"); +- event = vmalloc(sizeof(struct hdmi_cec_event)); +- if (NULL == event) { +- pr_err("%s: Not enough memory!\n", __func__); ++ ++ mutex_lock(&hdmi_cec_data.lock); ++ event = alloc_event(); ++ if (!event) { ++ mutex_unlock(&hdmi_cec_data.lock); + return; + } +- memset(event, 0, sizeof(struct hdmi_cec_event)); + event->event_type = MESSAGE_TYPE_DISCONNECTED; +- mutex_lock(&hdmi_cec_data.lock); + list_add_tail(&event->list, &ev_pending); + mutex_unlock(&hdmi_cec_data.lock); ++ + wake_up(&rx_queue); + } + } +@@ -245,6 +308,9 @@ static void mxc_hdmi_cec_worker(struct work_struct *work) + + mxc_hdmi_cec_handle(hdmi_cec_data.cec_stat0); + ++ if (hdmi_cec_data.cec_stat0 & HDMI_IH_CEC_STAT0_EOM) ++ hdmi_writeb(0x0, HDMI_CEC_LOCK); ++ + spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); + hdmi_cec_data.cec_stat0 = 0; + if (hdmi_cec_data.is_started) +@@ -270,7 +336,8 @@ static int hdmi_cec_open(struct inode *inode, struct file *file) + static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) + { +- struct hdmi_cec_event *event = NULL; ++ ssize_t len; ++ struct hdmi_cec_event *event; + + pr_debug("function : %s\n", __func__); + +@@ -284,26 +351,24 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + if (file->f_flags & O_NONBLOCK) { + mutex_unlock(&hdmi_cec_data.lock); + return -EAGAIN; +- } else { +- do { +- mutex_unlock(&hdmi_cec_data.lock); +- if (wait_event_interruptible(rx_queue, !list_empty(&ev_pending))) +- return -ERESTARTSYS; +- mutex_lock(&hdmi_cec_data.lock); +- } while (list_empty(&ev_pending)); + } ++ ++ do { ++ mutex_unlock(&hdmi_cec_data.lock); ++ if (wait_event_interruptible(rx_queue, !list_empty(&ev_pending))) ++ return -ERESTARTSYS; ++ mutex_lock(&hdmi_cec_data.lock); ++ } while (list_empty(&ev_pending)); + } + ++ len = offsetof(struct hdmi_cec_event, list); + event = list_first_entry(&ev_pending, struct hdmi_cec_event, list); +- list_del(&event->list); ++ if (copy_to_user(buf, event, len)) ++ len = -EFAULT; ++ list_move_tail(&event->list, &ev_idle); + mutex_unlock(&hdmi_cec_data.lock); +- if (copy_to_user(buf, event, +- sizeof(struct hdmi_cec_event) - sizeof(struct list_head))) { +- vfree(event); +- return -EFAULT; +- } +- vfree(event); +- return (sizeof(struct hdmi_cec_event) - sizeof(struct list_head)); ++ ++ return len; + } + + static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, +@@ -495,8 +560,6 @@ static long hdmi_cec_ioctl(struct file *file, u_int cmd, + + static int hdmi_cec_release(struct inode *inode, struct file *file) + { +- struct hdmi_cec_event *event, *tmp_event; +- + pr_debug("function : %s\n", __func__); + + mutex_lock(&hdmi_cec_data.lock); +@@ -505,11 +568,7 @@ static int hdmi_cec_release(struct inode *inode, struct file *file) + hdmi_cec_data.is_started = false; + hdmi_cec_data.logical_address = 15; + +- /* Flush eventual events which have not been read by user space */ +- list_for_each_entry_safe(event, tmp_event, &ev_pending, list) { +- list_del(&event->list); +- vfree(event); +- } ++ free_events(); + } + mutex_unlock(&hdmi_cec_data.lock); + +@@ -584,6 +643,7 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) + goto err_out_class; + } + ++ INIT_LIST_HEAD(&ev_idle); + INIT_LIST_HEAD(&ev_pending); + + init_waitqueue_head(&rx_queue); +-- +1.9.1 + + +============================================================== +file 0008-MXC-CEC-Fix-message-length-while-keeping-compatibili.patch +============================================================== + +From 19dd5ab55ca121073d35d104a49431b8c3cf3cf1 Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:38 +0100 +Subject: [PATCH] MXC-CEC: Fix message length while keeping compatibility with + old client libs + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index 22447cf..8777320 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -47,7 +47,7 @@ + #include "mxc_hdmi-cec.h" + + +-#define MAX_MESSAGE_LEN 17 ++#define MAX_MESSAGE_LEN 16 + + #define MESSAGE_TYPE_RECEIVE_SUCCESS 1 + #define MESSAGE_TYPE_NOACK 2 +@@ -92,6 +92,7 @@ struct hdmi_cec_event { + int event_type; + int msg_len; + u8 msg[MAX_MESSAGE_LEN]; ++ u8 padding[4]; /* compatibility with old userland */ + struct list_head list; + }; + +@@ -336,15 +337,21 @@ static int hdmi_cec_open(struct inode *inode, struct file *file) + static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) + { +- ssize_t len; ++ ssize_t len = 0; + struct hdmi_cec_event *event; + + pr_debug("function : %s\n", __func__); + + mutex_lock(&hdmi_cec_data.lock); +- if (!hdmi_cec_data.is_started) { ++ ++ if (!hdmi_cec_data.is_started) ++ len = -EACCES; ++ else if (count < offsetof(struct hdmi_cec_event, padding)) ++ len = -EINVAL; ++ ++ if (len < 0) { + mutex_unlock(&hdmi_cec_data.lock); +- return -EACCES; ++ return len; + } + + if (list_empty(&ev_pending)) { +@@ -361,7 +368,8 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + } while (list_empty(&ev_pending)); + } + +- len = offsetof(struct hdmi_cec_event, list); ++ /* Hack: older versions of libcec attempt to read more bytes than we provide */ ++ len = min(count, offsetof(struct hdmi_cec_event, list)); + event = list_first_entry(&ev_pending, struct hdmi_cec_event, list); + if (copy_to_user(buf, event, len)) + len = -EFAULT; +-- +1.9.1 + + +============================================================== +file 0009-MXC-CEC-Change-return-codes-and-add-poll-support-for.patch +============================================================== + +From 57a5e256cca14fdf8f4dabd839bf21762cff2eaa Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:39 +0100 +Subject: [PATCH] MXC-CEC: Change return codes and add poll support for write + function + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index 8777320..8134cc8 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -328,6 +328,7 @@ static int hdmi_cec_open(struct inode *inode, struct file *file) + } + hdmi_cec_data.open_count = 1; + file->private_data = (void *)(&hdmi_cec_data); ++ hdmi_cec_data.tx_answer = CEC_TX_AVAIL; + hdmi_cec_data.logical_address = 15; + hdmi_cec_data.is_started = false; + mutex_unlock(&hdmi_cec_data.lock); +@@ -393,7 +394,9 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + if (!hdmi_cec_data.is_started) + ret = -EACCES; + else if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) +- ret = -EBUSY; ++ ret = -EAGAIN; ++ else if (hdmi_cec_data.link_status != 1) ++ ret = -EAGAIN; + else if (count > MAX_MESSAGE_LEN) + ret = -EINVAL; + else if (copy_from_user(msg, buf, count)) +@@ -420,18 +423,15 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + ret = wait_event_interruptible_timeout( + tx_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); + +- if (ret < 0) { ++ if (ret < 0) + ret = -ERESTARTSYS; +- goto tx_out; +- } +- +- if (hdmi_cec_data.tx_answer & HDMI_IH_CEC_STAT0_DONE) +- /* msg correctly sent */ +- ret = msg_len; ++ else if (hdmi_cec_data.tx_answer & HDMI_IH_CEC_STAT0_DONE) ++ ret = msg_len; /* msg sent, ACK received */ ++ else if (hdmi_cec_data.tx_answer & HDMI_IH_CEC_STAT0_NACK) ++ ret = -EIO; /* msg sent, NACK received */ + else +- ret = -EIO; ++ ret = -EPIPE; /* other error */ + +-tx_out: + hdmi_cec_data.tx_answer = CEC_TX_AVAIL; + return ret; + } +@@ -575,6 +575,7 @@ static int hdmi_cec_release(struct inode *inode, struct file *file) + hdmi_cec_data.open_count = 0; + hdmi_cec_data.is_started = false; + hdmi_cec_data.logical_address = 15; ++ hdmi_cec_data.tx_answer = CEC_TX_AVAIL; + + free_events(); + } +@@ -590,13 +591,17 @@ static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) + pr_debug("function : %s\n", __func__); + + poll_wait(file, &rx_queue, wait); ++ poll_wait(file, &tx_queue, wait); ++ ++ if (hdmi_cec_data.link_status == 1 && ++ hdmi_cec_data.tx_answer == CEC_TX_AVAIL) ++ mask |= POLLOUT | POLLWRNORM; + +- /* Always writable */ +- mask = (POLLOUT | POLLWRNORM); + mutex_lock(&hdmi_cec_data.lock); + if (!list_empty(&ev_pending)) +- mask |= (POLLIN | POLLRDNORM); ++ mask |= POLLIN | POLLRDNORM; + mutex_unlock(&hdmi_cec_data.lock); ++ + return mask; + } + +-- +1.9.1 + + +============================================================== +file 0010-assign-minor-to-vhci.patch ============================================================== From 27b8b64082db6cdfda751e81e56c0f668053834b Mon Sep 17 00:00:00 2001 @@ -133,7 +1862,7 @@ 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 = { +@@ -360,7 +360,7 @@ static const struct file_operations vhci_fops = { static struct miscdevice vhci_miscdev= { .name = "vhci", .fops = &vhci_fops, @@ -142,7 +1871,7 @@ index 1ef6990..add1c6a 100644 }; static int __init vhci_init(void) -@@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); +@@ -386,3 +386,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); MODULE_ALIAS("devname:vhci"); @@ -160,6 +1889,957 @@ index 3737f72..7bb6148 100644 #define DMAPI_MINOR 140 /* DMAPI */ #define NVRAM_MINOR 144 +============================================================== +file 0010-MXC-CEC-Use-instance-data-pointer-whenever-possible.patch +============================================================== + +From 8f0d740e104758b558d8209d4736e7fcf0238b8e Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:39 +0100 +Subject: [PATCH] MXC-CEC: Use instance data pointer whenever possible + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 191 +++++++++++++++++++----------------- + 1 file changed, 100 insertions(+), 91 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index 8134cc8..80344d9 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -183,11 +183,11 @@ static u32 get_hpd_stat(struct hdmi_cec_priv *hdmi_cec) + + static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + { +- struct hdmi_cec_priv *hdmi_cec = data; ++ struct hdmi_cec_priv *priv = data; + unsigned long flags; + u8 cec_stat; + +- spin_lock_irqsave(&hdmi_cec->irq_lock, flags); ++ spin_lock_irqsave(&priv->irq_lock, flags); + + hdmi_writeb(CEC_STAT0_MASK_ALL, HDMI_IH_MUTE_CEC_STAT0); + +@@ -195,58 +195,58 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0); + + if ((cec_stat & ~CEC_STAT0_MASK_DEFAULT) == 0) { +- if (hdmi_cec->is_started) ++ if (priv->is_started) + hdmi_writeb(CEC_STAT0_MASK_DEFAULT, HDMI_IH_MUTE_CEC_STAT0); +- spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); ++ spin_unlock_irqrestore(&priv->irq_lock, flags); + return IRQ_NONE; + } + + pr_debug("HDMI-CEC: interrupt received\n"); + +- hdmi_cec->cec_stat0 = cec_stat | get_hpd_stat(hdmi_cec); +- schedule_work(&hdmi_cec->hdmi_cec_work); ++ priv->cec_stat0 = cec_stat | get_hpd_stat(priv); ++ schedule_work(&priv->hdmi_cec_work); + +- spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags); ++ spin_unlock_irqrestore(&priv->irq_lock, flags); + + return IRQ_HANDLED; + } + +-static void mxc_hdmi_cec_handle(u32 cec_stat) ++static void mxc_hdmi_cec_handle(struct hdmi_cec_priv *priv, u32 cec_stat) + { + int i; + struct hdmi_cec_event *event; + +- if (!hdmi_cec_data.open_count) ++ if (!priv->open_count) + return; + + /*HDMI cable connected: handle first*/ + if (cec_stat & CEC_STAT0_EX_CONNECTED) { + pr_info("HDMI-CEC: link connected\n"); + +- mutex_lock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); + event = alloc_event(); + if (!event) { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + return; + } + event->event_type = MESSAGE_TYPE_CONNECTED; + list_add_tail(&event->list, &ev_pending); +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + + wake_up(&rx_queue); + } + + /*The current transmission is successful (for initiator only).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_DONE) { +- hdmi_cec_data.tx_answer = cec_stat; ++ priv->tx_answer = cec_stat; + wake_up(&tx_queue); + } + /*EOM is detected so that the received data is ready in the receiver data buffer*/ + if (cec_stat & HDMI_IH_CEC_STAT0_EOM) { +- mutex_lock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); + event = alloc_event(); + if (!event) { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + return; + } + +@@ -254,7 +254,7 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + if (!event->msg_len || event->msg_len > MAX_MESSAGE_LEN) { + pr_err("HDMI-CEC: Invalid CEC message length\n"); + list_add_tail(&event->list, &ev_idle); +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + return; + } + +@@ -263,41 +263,41 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0 + i); + + list_add_tail(&event->list, &ev_pending); +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + + wake_up(&rx_queue); + } + /*An error is detected on cec line (for initiator only). */ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) { +- hdmi_cec_data.tx_answer = cec_stat; ++ priv->tx_answer = cec_stat; + wake_up(&tx_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; ++ priv->send_error++; ++ priv->tx_answer = cec_stat; + wake_up(&tx_queue); + } + /*An error is notified by a follower. Abnormal logic data bit error (for follower).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL) { +- hdmi_cec_data.receive_error++; ++ priv->receive_error++; + } + + /*HDMI cable disconnected: handle last*/ + if (cec_stat & CEC_STAT0_EX_DISCONNECTED) { + pr_info("HDMI-CEC: link disconnected\n"); + +- mutex_lock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); + event = alloc_event(); + if (!event) { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + return; + } + event->event_type = MESSAGE_TYPE_DISCONNECTED; + list_add_tail(&event->list, &ev_pending); +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + + wake_up(&rx_queue); + } +@@ -306,32 +306,36 @@ static void mxc_hdmi_cec_handle(u32 cec_stat) + static void mxc_hdmi_cec_worker(struct work_struct *work) + { + unsigned long flags; ++ struct hdmi_cec_priv *priv = &hdmi_cec_data; + +- mxc_hdmi_cec_handle(hdmi_cec_data.cec_stat0); ++ mxc_hdmi_cec_handle(priv, priv->cec_stat0); + +- if (hdmi_cec_data.cec_stat0 & HDMI_IH_CEC_STAT0_EOM) ++ if (priv->cec_stat0 & HDMI_IH_CEC_STAT0_EOM) + hdmi_writeb(0x0, HDMI_CEC_LOCK); + +- spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); +- hdmi_cec_data.cec_stat0 = 0; +- if (hdmi_cec_data.is_started) ++ spin_lock_irqsave(&priv->irq_lock, flags); ++ priv->cec_stat0 = 0; ++ if (priv->is_started) + hdmi_writeb(CEC_STAT0_MASK_DEFAULT, HDMI_IH_MUTE_CEC_STAT0); +- spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); ++ spin_unlock_irqrestore(&priv->irq_lock, flags); + } + + static int hdmi_cec_open(struct inode *inode, struct file *file) + { +- mutex_lock(&hdmi_cec_data.lock); +- if (hdmi_cec_data.open_count) { +- mutex_unlock(&hdmi_cec_data.lock); ++ struct hdmi_cec_priv *priv = &hdmi_cec_data; ++ ++ mutex_lock(&priv->lock); ++ if (priv->open_count) { ++ mutex_unlock(&priv->lock); + return -EBUSY; + } +- hdmi_cec_data.open_count = 1; +- file->private_data = (void *)(&hdmi_cec_data); +- hdmi_cec_data.tx_answer = CEC_TX_AVAIL; +- hdmi_cec_data.logical_address = 15; +- hdmi_cec_data.is_started = false; +- mutex_unlock(&hdmi_cec_data.lock); ++ file->private_data = priv; ++ ++ priv->tx_answer = CEC_TX_AVAIL; ++ priv->logical_address = 15; ++ priv->is_started = false; ++ priv->open_count = 1; ++ mutex_unlock(&priv->lock); + return 0; + } + +@@ -340,32 +344,33 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + { + ssize_t len = 0; + struct hdmi_cec_event *event; ++ struct hdmi_cec_priv *priv = file->private_data; + + pr_debug("function : %s\n", __func__); + +- mutex_lock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); + +- if (!hdmi_cec_data.is_started) ++ if (!priv->is_started) + len = -EACCES; + else if (count < offsetof(struct hdmi_cec_event, padding)) + len = -EINVAL; + + if (len < 0) { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + return len; + } + + if (list_empty(&ev_pending)) { + if (file->f_flags & O_NONBLOCK) { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + return -EAGAIN; + } + + do { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + if (wait_event_interruptible(rx_queue, !list_empty(&ev_pending))) + return -ERESTARTSYS; +- mutex_lock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); + } while (list_empty(&ev_pending)); + } + +@@ -375,7 +380,7 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + if (copy_to_user(buf, event, len)) + len = -EFAULT; + list_move_tail(&event->list, &ev_idle); +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + + return len; + } +@@ -386,16 +391,17 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + int ret = 0; + u8 i, msg_len, val; + u8 msg[MAX_MESSAGE_LEN]; ++ struct hdmi_cec_priv *priv = file->private_data; + + pr_debug("function : %s\n", __func__); + +- mutex_lock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); + +- if (!hdmi_cec_data.is_started) ++ if (!priv->is_started) + ret = -EACCES; +- else if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) ++ else if (priv->tx_answer != CEC_TX_AVAIL) + ret = -EAGAIN; +- else if (hdmi_cec_data.link_status != 1) ++ else if (priv->link_status != 1) + ret = -EAGAIN; + else if (count > MAX_MESSAGE_LEN) + ret = -EINVAL; +@@ -403,12 +409,12 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + ret = -EACCES; + + if (ret) { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + return ret; + } + +- hdmi_cec_data.send_error = 0; +- hdmi_cec_data.tx_answer = CEC_TX_INPROGRESS; ++ priv->send_error = 0; ++ priv->tx_answer = CEC_TX_INPROGRESS; + + msg_len = count; + hdmi_writeb(msg_len, HDMI_CEC_TX_CNT); +@@ -418,40 +424,41 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + val |= 0x01; + hdmi_writeb(val, HDMI_CEC_CTRL); + +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + + ret = wait_event_interruptible_timeout( +- tx_queue, hdmi_cec_data.tx_answer != CEC_TX_INPROGRESS, HZ); ++ tx_queue, priv->tx_answer != CEC_TX_INPROGRESS, HZ); + + if (ret < 0) + ret = -ERESTARTSYS; +- else if (hdmi_cec_data.tx_answer & HDMI_IH_CEC_STAT0_DONE) ++ else if (priv->tx_answer & HDMI_IH_CEC_STAT0_DONE) + ret = msg_len; /* msg sent, ACK received */ +- else if (hdmi_cec_data.tx_answer & HDMI_IH_CEC_STAT0_NACK) ++ else if (priv->tx_answer & HDMI_IH_CEC_STAT0_NACK) + ret = -EIO; /* msg sent, NACK received */ + else + ret = -EPIPE; /* other error */ + +- hdmi_cec_data.tx_answer = CEC_TX_AVAIL; ++ priv->tx_answer = CEC_TX_AVAIL; + return ret; + } + + void hdmi_cec_hpd_changed(unsigned int state) + { ++ u32 cec_stat0; + unsigned long flags; +- u32 cec_stat0; ++ struct hdmi_cec_priv *priv = &hdmi_cec_data; + + pr_debug("function : %s\n", __func__); + + link_status = state & 1; + + if (is_initialized) { +- spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); +- cec_stat0 = get_hpd_stat(&hdmi_cec_data); +- spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); ++ spin_lock_irqsave(&priv->irq_lock, flags); ++ cec_stat0 = get_hpd_stat(priv); ++ spin_unlock_irqrestore(&priv->irq_lock, flags); + + if (cec_stat0) +- mxc_hdmi_cec_handle(cec_stat0); ++ mxc_hdmi_cec_handle(priv, cec_stat0); + } + } + EXPORT_SYMBOL(hdmi_cec_hpd_changed); +@@ -515,35 +522,35 @@ void hdmi_cec_stop_device(void) + } + EXPORT_SYMBOL(hdmi_cec_stop_device); + +-static long hdmi_cec_ioctl(struct file *file, u_int cmd, +- u_long arg) ++static long hdmi_cec_ioctl(struct file *file, u_int cmd, u_long arg) + { +- int ret = 0, status = 0; +- u8 val = 0; ++ u8 val; ++ int ret = 0; + struct mxc_edid_cfg hdmi_edid_cfg; ++ struct hdmi_cec_priv *priv = file->private_data; + + pr_debug("function : %s\n", __func__); + + switch (cmd) { + case HDMICEC_IOC_SETLOGICALADDRESS: +- mutex_lock(&hdmi_cec_data.lock); +- if (!hdmi_cec_data.is_started) { +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); ++ if (!priv->is_started) { ++ mutex_unlock(&priv->lock); + pr_err("Trying to set logical address while not started\n"); + return -EACCES; + } +- hdmi_cec_data.logical_address = (u8)arg; +- if (hdmi_cec_data.logical_address <= 7) { +- val = 1 << hdmi_cec_data.logical_address; ++ priv->logical_address = (u8)arg; ++ if (priv->logical_address <= 7) { ++ val = 1 << priv->logical_address; + hdmi_writeb(val, HDMI_CEC_ADDR_L); + hdmi_writeb(0, HDMI_CEC_ADDR_H); +- } else if (hdmi_cec_data.logical_address > 7 && hdmi_cec_data.logical_address <= 15) { +- val = 1 << (hdmi_cec_data.logical_address - 8); ++ } else if (priv->logical_address <= 15) { ++ val = 1 << (priv->logical_address - 8); + hdmi_writeb(val, HDMI_CEC_ADDR_H); + hdmi_writeb(0, HDMI_CEC_ADDR_L); + } else + ret = -EINVAL; +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + break; + case HDMICEC_IOC_STARTDEVICE: + hdmi_cec_start_device(); +@@ -553,10 +560,9 @@ static long hdmi_cec_ioctl(struct file *file, u_int cmd, + break; + case HDMICEC_IOC_GETPHYADDRESS: + hdmi_get_edid_cfg(&hdmi_edid_cfg); +- status = copy_to_user((void __user *)arg, +- &hdmi_edid_cfg.physical_address, +- 4*sizeof(u8)); +- if (status) ++ if (copy_to_user((void __user *)arg, ++ &hdmi_edid_cfg.physical_address, ++ 4 * sizeof(u8))) + ret = -EFAULT; + break; + default: +@@ -568,18 +574,20 @@ static long hdmi_cec_ioctl(struct file *file, u_int cmd, + + static int hdmi_cec_release(struct inode *inode, struct file *file) + { ++ struct hdmi_cec_priv *priv = &hdmi_cec_data; ++ + pr_debug("function : %s\n", __func__); + +- mutex_lock(&hdmi_cec_data.lock); +- if (hdmi_cec_data.open_count) { +- hdmi_cec_data.open_count = 0; +- hdmi_cec_data.is_started = false; +- hdmi_cec_data.logical_address = 15; +- hdmi_cec_data.tx_answer = CEC_TX_AVAIL; ++ mutex_lock(&priv->lock); ++ if (priv->open_count) { ++ priv->open_count = 0; ++ priv->is_started = false; ++ priv->logical_address = 15; ++ priv->tx_answer = CEC_TX_AVAIL; + + free_events(); + } +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + + return 0; + } +@@ -587,20 +595,21 @@ static int hdmi_cec_release(struct inode *inode, struct file *file) + static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) + { + unsigned int mask = 0; ++ struct hdmi_cec_priv *priv = file->private_data; + + pr_debug("function : %s\n", __func__); + + poll_wait(file, &rx_queue, wait); + poll_wait(file, &tx_queue, wait); + +- if (hdmi_cec_data.link_status == 1 && +- hdmi_cec_data.tx_answer == CEC_TX_AVAIL) ++ if (priv->link_status == 1 && ++ priv->tx_answer == CEC_TX_AVAIL) + mask |= POLLOUT | POLLWRNORM; + +- mutex_lock(&hdmi_cec_data.lock); ++ mutex_lock(&priv->lock); + if (!list_empty(&ev_pending)) + mask |= POLLIN | POLLRDNORM; +- mutex_unlock(&hdmi_cec_data.lock); ++ mutex_unlock(&priv->lock); + + return mask; + } +-- +1.9.1 + + +============================================================== +file 0011-MXC-CEC-Re-order-functions-and-remove-debug-trace-me.patch +============================================================== + +From aeefcbe8831cbdd5a54a1144b89a4d8e2a427e2c Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:39 +0100 +Subject: [PATCH] MXC-CEC: Re-order functions and remove debug trace messages + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 239 ++++++++++++++++++------------------ + 1 file changed, 118 insertions(+), 121 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index 80344d9..fcf2a28 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -241,6 +241,7 @@ static void mxc_hdmi_cec_handle(struct hdmi_cec_priv *priv, u32 cec_stat) + priv->tx_answer = cec_stat; + wake_up(&tx_queue); + } ++ + /*EOM is detected so that the received data is ready in the receiver data buffer*/ + if (cec_stat & HDMI_IH_CEC_STAT0_EOM) { + mutex_lock(&priv->lock); +@@ -267,12 +268,14 @@ static void mxc_hdmi_cec_handle(struct hdmi_cec_priv *priv, u32 cec_stat) + + wake_up(&rx_queue); + } ++ + /*An error is detected on cec line (for initiator only). */ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) { + priv->tx_answer = cec_stat; + wake_up(&tx_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) { +@@ -280,6 +283,7 @@ static void mxc_hdmi_cec_handle(struct hdmi_cec_priv *priv, u32 cec_stat) + priv->tx_answer = cec_stat; + wake_up(&tx_queue); + } ++ + /*An error is notified by a follower. Abnormal logic data bit error (for follower).*/ + if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL) { + priv->receive_error++; +@@ -320,6 +324,89 @@ static void mxc_hdmi_cec_worker(struct work_struct *work) + spin_unlock_irqrestore(&priv->irq_lock, flags); + } + ++ ++void hdmi_cec_hpd_changed(unsigned int state) ++{ ++ u32 cec_stat0; ++ unsigned long flags; ++ struct hdmi_cec_priv *priv = &hdmi_cec_data; ++ ++ pr_debug("function : %s (%d)\n", __func__, state); ++ ++ link_status = state & 1; ++ ++ if (is_initialized) { ++ spin_lock_irqsave(&priv->irq_lock, flags); ++ cec_stat0 = get_hpd_stat(priv); ++ spin_unlock_irqrestore(&priv->irq_lock, flags); ++ ++ if (cec_stat0) ++ mxc_hdmi_cec_handle(priv, cec_stat0); ++ } ++} ++EXPORT_SYMBOL(hdmi_cec_hpd_changed); ++ ++void hdmi_cec_start_device(void) ++{ ++ u8 val; ++ unsigned long flags; ++ ++ if (!is_initialized) { ++ want_start = 1; ++ return; ++ } ++ ++ spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); ++ ++ val = hdmi_readb(HDMI_MC_CLKDIS); ++ val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; ++ hdmi_writeb(val, HDMI_MC_CLKDIS); ++ hdmi_writeb(0x02, HDMI_CEC_CTRL); ++ /* Force read unlock */ ++ hdmi_writeb(0x0, HDMI_CEC_LOCK); ++ ++ val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK | ++ HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; ++ hdmi_writeb(val, HDMI_CEC_POLARITY); ++ ++ val = CEC_STAT0_MASK_DEFAULT; ++ hdmi_writeb(val, HDMI_CEC_MASK); ++ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); ++ hdmi_cec_data.link_status = link_status; ++ hdmi_cec_data.is_started = true; ++ ++ spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); ++} ++EXPORT_SYMBOL(hdmi_cec_start_device); ++ ++void hdmi_cec_stop_device(void) ++{ ++ u8 val; ++ unsigned long flags; ++ ++ if (!is_initialized) { ++ want_start = 0; ++ return; ++ } ++ ++ spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); ++ ++ hdmi_cec_data.is_started = false; ++ hdmi_writeb(0x10, HDMI_CEC_CTRL); ++ val = CEC_STAT0_MASK_ALL; ++ hdmi_writeb(val, HDMI_CEC_MASK); ++ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); ++ ++ hdmi_writeb(0x0, HDMI_CEC_POLARITY); ++ val = hdmi_readb(HDMI_MC_CLKDIS); ++ val |= HDMI_MC_CLKDIS_CECCLK_DISABLE; ++ hdmi_writeb(val, HDMI_MC_CLKDIS); ++ ++ spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); ++} ++EXPORT_SYMBOL(hdmi_cec_stop_device); ++ ++ + static int hdmi_cec_open(struct inode *inode, struct file *file) + { + struct hdmi_cec_priv *priv = &hdmi_cec_data; +@@ -339,6 +426,24 @@ static int hdmi_cec_open(struct inode *inode, struct file *file) + return 0; + } + ++static int hdmi_cec_release(struct inode *inode, struct file *file) ++{ ++ struct hdmi_cec_priv *priv = file->private_data; ++ ++ mutex_lock(&priv->lock); ++ if (priv->open_count) { ++ priv->open_count = 0; ++ priv->is_started = false; ++ priv->logical_address = 15; ++ priv->tx_answer = CEC_TX_AVAIL; ++ ++ free_events(); ++ } ++ mutex_unlock(&priv->lock); ++ ++ return 0; ++} ++ + static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) + { +@@ -346,8 +451,6 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count, + struct hdmi_cec_event *event; + struct hdmi_cec_priv *priv = file->private_data; + +- pr_debug("function : %s\n", __func__); +- + mutex_lock(&priv->lock); + + if (!priv->is_started) +@@ -393,8 +496,6 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + u8 msg[MAX_MESSAGE_LEN]; + struct hdmi_cec_priv *priv = file->private_data; + +- pr_debug("function : %s\n", __func__); +- + mutex_lock(&priv->lock); + + if (!priv->is_started) +@@ -442,85 +543,25 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + return ret; + } + +-void hdmi_cec_hpd_changed(unsigned int state) +-{ +- u32 cec_stat0; +- unsigned long flags; +- struct hdmi_cec_priv *priv = &hdmi_cec_data; +- +- pr_debug("function : %s\n", __func__); +- +- link_status = state & 1; +- +- if (is_initialized) { +- spin_lock_irqsave(&priv->irq_lock, flags); +- cec_stat0 = get_hpd_stat(priv); +- spin_unlock_irqrestore(&priv->irq_lock, flags); +- +- if (cec_stat0) +- mxc_hdmi_cec_handle(priv, cec_stat0); +- } +-} +-EXPORT_SYMBOL(hdmi_cec_hpd_changed); +- +-void hdmi_cec_start_device(void) ++static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) + { +- u8 val; +- unsigned long flags; +- +- if (!is_initialized) { +- want_start = 1; +- return; +- } +- +- spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); +- +- val = hdmi_readb(HDMI_MC_CLKDIS); +- val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; +- hdmi_writeb(val, HDMI_MC_CLKDIS); +- hdmi_writeb(0x02, HDMI_CEC_CTRL); +- /* Force read unlock */ +- hdmi_writeb(0x0, HDMI_CEC_LOCK); +- +- val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; +- hdmi_writeb(val, HDMI_CEC_POLARITY); +- +- val = CEC_STAT0_MASK_DEFAULT; +- hdmi_writeb(val, HDMI_CEC_MASK); +- hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); +- hdmi_cec_data.link_status = link_status; +- hdmi_cec_data.is_started = true; +- +- spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); +-} +-EXPORT_SYMBOL(hdmi_cec_start_device); +- +-void hdmi_cec_stop_device(void) +-{ +- u8 val; +- unsigned long flags; +- +- if (!is_initialized) { +- want_start = 0; +- return; +- } ++ unsigned int mask = 0; ++ struct hdmi_cec_priv *priv = file->private_data; + +- spin_lock_irqsave(&hdmi_cec_data.irq_lock, flags); ++ poll_wait(file, &rx_queue, wait); ++ poll_wait(file, &tx_queue, wait); + +- hdmi_cec_data.is_started = false; +- hdmi_writeb(0x10, HDMI_CEC_CTRL); +- val = CEC_STAT0_MASK_ALL; +- hdmi_writeb(val, HDMI_CEC_MASK); +- hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); ++ if (priv->link_status == 1 && ++ priv->tx_answer == CEC_TX_AVAIL) ++ mask |= POLLOUT | POLLWRNORM; + +- hdmi_writeb(0x0, HDMI_CEC_POLARITY); +- val = hdmi_readb(HDMI_MC_CLKDIS); +- val |= HDMI_MC_CLKDIS_CECCLK_DISABLE; +- hdmi_writeb(val, HDMI_MC_CLKDIS); ++ mutex_lock(&priv->lock); ++ if (!list_empty(&ev_pending)) ++ mask |= POLLIN | POLLRDNORM; ++ mutex_unlock(&priv->lock); + +- spin_unlock_irqrestore(&hdmi_cec_data.irq_lock, flags); ++ return mask; + } +-EXPORT_SYMBOL(hdmi_cec_stop_device); + + static long hdmi_cec_ioctl(struct file *file, u_int cmd, u_long arg) + { +@@ -529,8 +570,6 @@ static long hdmi_cec_ioctl(struct file *file, u_int cmd, u_long arg) + struct mxc_edid_cfg hdmi_edid_cfg; + struct hdmi_cec_priv *priv = file->private_data; + +- pr_debug("function : %s\n", __func__); +- + switch (cmd) { + case HDMICEC_IOC_SETLOGICALADDRESS: + mutex_lock(&priv->lock); +@@ -572,48 +611,6 @@ static long hdmi_cec_ioctl(struct file *file, u_int cmd, u_long arg) + return ret; + } + +-static int hdmi_cec_release(struct inode *inode, struct file *file) +-{ +- struct hdmi_cec_priv *priv = &hdmi_cec_data; +- +- pr_debug("function : %s\n", __func__); +- +- mutex_lock(&priv->lock); +- if (priv->open_count) { +- priv->open_count = 0; +- priv->is_started = false; +- priv->logical_address = 15; +- priv->tx_answer = CEC_TX_AVAIL; +- +- free_events(); +- } +- mutex_unlock(&priv->lock); +- +- return 0; +-} +- +-static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait) +-{ +- unsigned int mask = 0; +- struct hdmi_cec_priv *priv = file->private_data; +- +- pr_debug("function : %s\n", __func__); +- +- poll_wait(file, &rx_queue, wait); +- poll_wait(file, &tx_queue, wait); +- +- if (priv->link_status == 1 && +- priv->tx_answer == CEC_TX_AVAIL) +- mask |= POLLOUT | POLLWRNORM; +- +- mutex_lock(&priv->lock); +- if (!list_empty(&ev_pending)) +- mask |= POLLIN | POLLRDNORM; +- mutex_unlock(&priv->lock); +- +- return mask; +-} +- + + const struct file_operations hdmi_cec_fops = { + .owner = THIS_MODULE, +-- +1.9.1 + + +============================================================== +file 0012-MXC-CEC-Provide-send-notifications.patch +============================================================== + +From 73230c020f3fb1385046890df1695d1bc2e6082e Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 09:27:40 +0100 +Subject: [PATCH] MXC-CEC: Provide send notifications + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index fcf2a28..dfb4aa4 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -494,6 +494,7 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + int ret = 0; + u8 i, msg_len, val; + u8 msg[MAX_MESSAGE_LEN]; ++ struct hdmi_cec_event *event; + struct hdmi_cec_priv *priv = file->private_data; + + mutex_lock(&priv->lock); +@@ -540,6 +541,24 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + ret = -EPIPE; /* other error */ + + priv->tx_answer = CEC_TX_AVAIL; ++ ++ if (ret >= 0 || ret == -EIO) { ++ mutex_lock(&priv->lock); ++ ++ event = alloc_event(); ++ if (event) { ++ event->event_type = (ret == -EIO) ? ++ MESSAGE_TYPE_NOACK : MESSAGE_TYPE_SEND_SUCCESS; ++ event->msg_len = msg_len; ++ memcpy(event->msg, msg, msg_len); ++ ++ list_add_tail(&event->list, &ev_pending); ++ wake_up(&rx_queue); ++ } ++ ++ mutex_unlock(&priv->lock); ++ } ++ + return ret; + } + +-- +1.9.1 + + +============================================================== +file 0013-MXC-CEC-Enable-transmissions-retries-in-case-of-erro.patch +============================================================== + +From 0fd44cc4dc2fb1f5a0cb26aa74a2c11af1b0d79e Mon Sep 17 00:00:00 2001 +From: warped-rudi +Date: Wed, 9 Nov 2016 17:25:01 +0100 +Subject: [PATCH] MXC-CEC: Enable transmissions retries in case of errors and + NACKs + +--- + drivers/mxc/hdmi-cec/mxc_hdmi-cec.c | 29 +++++++++++++++-------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +index dfb4aa4..4d22e38 100644 +--- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c ++++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c +@@ -58,6 +58,9 @@ + #define CEC_TX_INPROGRESS -1 + #define CEC_TX_AVAIL 0 + ++#define CEC_TX_RETRIES 3 ++ ++ + /* These flags must not collide with HDMI_IH_CEC_STAT0_xxxx */ + #define CEC_STAT0_EX_CONNECTED 0x0100 + #define CEC_STAT0_EX_DISCONNECTED 0x0200 +@@ -214,6 +217,7 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data) + static void mxc_hdmi_cec_handle(struct hdmi_cec_priv *priv, u32 cec_stat) + { + int i; ++ u8 val; + struct hdmi_cec_event *event; + + if (!priv->open_count) +@@ -270,18 +274,16 @@ static void mxc_hdmi_cec_handle(struct hdmi_cec_priv *priv, u32 cec_stat) + } + + /*An error is detected on cec line (for initiator only). */ +- if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) { +- priv->tx_answer = cec_stat; +- wake_up(&tx_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) { +- priv->send_error++; +- priv->tx_answer = cec_stat; +- wake_up(&tx_queue); ++ if (cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK)) { ++ if (++priv->send_error < CEC_TX_RETRIES) { ++ val = hdmi_readb(HDMI_CEC_CTRL) & ~0x07; ++ hdmi_writeb(val | 0x01, HDMI_CEC_CTRL); ++ } else { ++ priv->tx_answer = cec_stat; ++ wake_up(&tx_queue); ++ } + } + + /*An error is notified by a follower. Abnormal logic data bit error (for follower).*/ +@@ -521,10 +523,9 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, + msg_len = count; + hdmi_writeb(msg_len, HDMI_CEC_TX_CNT); + for (i = 0; i < msg_len; i++) +- hdmi_writeb(msg[i], HDMI_CEC_TX_DATA0+i); +- val = hdmi_readb(HDMI_CEC_CTRL); +- val |= 0x01; +- hdmi_writeb(val, HDMI_CEC_CTRL); ++ hdmi_writeb(msg[i], HDMI_CEC_TX_DATA0 + i); ++ val = hdmi_readb(HDMI_CEC_CTRL) & ~0x07; ++ hdmi_writeb(val | 0x03, HDMI_CEC_CTRL); + + mutex_unlock(&priv->lock); + +-- +1.9.1 + + ============================================================== file 1100-ARM-Avoid-crash-on-power-off-and-reduce-power-consum.patch ============================================================== diff --git a/projects/imx6/patches/linux/3.14-mx6-sr/linux-910.01-cec-upstream.patch b/projects/imx6/patches/linux/3.14-mx6-sr/linux-910.01-cec-upstream.patch deleted file mode 100644 index 62be487a36..0000000000 --- a/projects/imx6/patches/linux/3.14-mx6-sr/linux-910.01-cec-upstream.patch +++ /dev/null @@ -1,86 +0,0 @@ -commit 7c545ae5467cca6ce537e213ecd647fcd4c3c4c0 -Author: wolfgar -Date: Fri Sep 12 01:42:52 2014 +0200 - - Remove superflous guards that could even break invocation from mxc-hdmi - -diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -index e53510f..88670bd 100644 ---- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -@@ -83,8 +83,6 @@ struct hdmi_cec_event { - - static LIST_HEAD(head); - --static int hdmi_cec_ready = 0; --static int hdmi_cec_started; - static int hdmi_cec_major; - static struct class *hdmi_cec_class; - static struct hdmi_cec_priv hdmi_cec_data; -@@ -315,7 +313,7 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, - mutex_unlock(&hdmi_cec_data.lock); - return -EACCES; - } -- /* Ensure that there is only one writer who is the only listener of tx_cec_queue */ -+ /* Ensure that there is only one writer who is the unique listener of tx_cec_queue */ - if (hdmi_cec_data.tx_answer != CEC_TX_AVAIL) { - mutex_unlock(&hdmi_cec_data.lock); - return -EBUSY; -@@ -359,13 +357,11 @@ static ssize_t hdmi_cec_write(struct file *file, const char __user *buf, - return ret; - } - -+ - void hdmi_cec_start_device(void) - { - u8 val; - -- if (!hdmi_cec_ready || hdmi_cec_started) -- return; -- - val = hdmi_readb(HDMI_MC_CLKDIS); - val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE; - hdmi_writeb(val, HDMI_MC_CLKDIS); -@@ -378,11 +374,7 @@ void hdmi_cec_start_device(void) - hdmi_writeb(val, HDMI_CEC_MASK); - hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0); - hdmi_cec_data.link_status = hdmi_readb(HDMI_PHY_STAT0) & 0x02; -- mutex_lock(&hdmi_cec_data.lock); - hdmi_cec_data.cec_state = true; -- mutex_unlock(&hdmi_cec_data.lock); -- -- hdmi_cec_started = 1; - } - EXPORT_SYMBOL(hdmi_cec_start_device); - -@@ -390,9 +382,6 @@ void hdmi_cec_stop_device(void) - { - u8 val; - -- if (!hdmi_cec_ready || !hdmi_cec_started) -- return; -- - hdmi_writeb(0x10, HDMI_CEC_CTRL); - val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST | \ - HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE; -@@ -402,11 +391,7 @@ void hdmi_cec_stop_device(void) - val = hdmi_readb(HDMI_MC_CLKDIS); - val |= HDMI_MC_CLKDIS_CECCLK_DISABLE; - hdmi_writeb(val, HDMI_MC_CLKDIS); -- mutex_lock(&hdmi_cec_data.lock); - hdmi_cec_data.cec_state = false; -- mutex_unlock(&hdmi_cec_data.lock); -- -- hdmi_cec_started = 0; - } - EXPORT_SYMBOL(hdmi_cec_stop_device); - -@@ -580,7 +565,6 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev) - INIT_DELAYED_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker); - - dev_info(&pdev->dev, "HDMI CEC initialized\n"); -- hdmi_cec_ready = 1; - goto out; - - err_out_class: - diff --git a/projects/imx6/patches/linux/3.14-mx6-sr/linux-910.02-cec-upstream.patch b/projects/imx6/patches/linux/3.14-mx6-sr/linux-910.02-cec-upstream.patch deleted file mode 100644 index 0d473c664f..0000000000 --- a/projects/imx6/patches/linux/3.14-mx6-sr/linux-910.02-cec-upstream.patch +++ /dev/null @@ -1,29 +0,0 @@ -commit b6b72f40ec3b9d7faa0e37e87c3509848928746c -Author: wolfgar -Date: Fri Sep 12 03:05:22 2014 +0200 - - Flush pending events at close - -diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -index 88670bd..f8b3f7a 100644 ---- a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c -@@ -466,11 +466,18 @@ static long hdmi_cec_ioctl(struct file *filp, u_int cmd, - */ - static int hdmi_cec_release(struct inode *inode, struct file *filp) - { -+ struct hdmi_cec_event *event, *tmp_event; - mutex_lock(&hdmi_cec_data.lock); - if (open_count) { - open_count = 0; - hdmi_cec_data.cec_state = false; - hdmi_cec_data.Logical_address = 15; -+ -+ /* Flush eventual events which have not been read by user space */ -+ list_for_each_entry_safe(event, tmp_event, &head, list) { -+ list_del(&event->list); -+ vfree(event); -+ } - } - mutex_unlock(&hdmi_cec_data.lock); - diff --git a/projects/imx6/patches/linux/3.14-mx6-sr/linux-compiler-gcc.h.patch b/projects/imx6/patches/linux/3.14-mx6-sr/linux-compiler-gcc.h.patch deleted file mode 100644 index 51b93a3034..0000000000 --- a/projects/imx6/patches/linux/3.14-mx6-sr/linux-compiler-gcc.h.patch +++ /dev/null @@ -1,166 +0,0 @@ -From cb984d101b30eb7478d32df56a0023e4603cba7f Mon Sep 17 00:00:00 2001 -From: Joe Perches -Date: Thu, 25 Jun 2015 15:01:02 -0700 -Subject: compiler-gcc: integrate the various compiler-gcc[345].h files - -As gcc major version numbers are going to advance rather rapidly in the -future, there's no real value in separate files for each compiler -version. - -Deduplicate some of the macros #defined in each file too. - -Neaten comments using normal kernel commenting style. - -Signed-off-by: Joe Perches -Cc: Andi Kleen -Cc: Michal Marek -Cc: Segher Boessenkool -Cc: Sasha Levin -Cc: Anton Blanchard -Cc: Alan Modra -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - include/linux/compiler-gcc.h | 120 ++++++++++++++++++++++++++++++++++++++++-- - include/linux/compiler-gcc3.h | 23 -------- - include/linux/compiler-gcc4.h | 91 -------------------------------- - include/linux/compiler-gcc5.h | 67 ----------------------- - 4 files changed, 116 insertions(+), 185 deletions(-) - delete mode 100644 include/linux/compiler-gcc3.h - delete mode 100644 include/linux/compiler-gcc4.h - delete mode 100644 include/linux/compiler-gcc5.h - -diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h -index 5c2c14e..dfaa7b3 100644 ---- a/include/linux/compiler-gcc.h -+++ b/include/linux/compiler-gcc.h -@@ -122,10 +122,122 @@ - #define __maybe_unused __attribute__((unused)) - #define __always_unused __attribute__((unused)) - --#define __gcc_header(x) #x --#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h) --#define gcc_header(x) _gcc_header(x) --#include gcc_header(__GNUC__) -+/* gcc version specific checks */ -+ -+#if GCC_VERSION < 30200 -+# error Sorry, your compiler is too old - please upgrade it. -+#endif -+ -+#if GCC_VERSION < 30300 -+# define __used __attribute__((__unused__)) -+#else -+# define __used __attribute__((__used__)) -+#endif -+ -+#ifdef CONFIG_GCOV_KERNEL -+# if GCC_VERSION < 30400 -+# error "GCOV profiling support for gcc versions below 3.4 not included" -+# endif /* __GNUC_MINOR__ */ -+#endif /* CONFIG_GCOV_KERNEL */ -+ -+#if GCC_VERSION >= 30400 -+#define __must_check __attribute__((warn_unused_result)) -+#endif -+ -+#if GCC_VERSION >= 40000 -+ -+/* GCC 4.1.[01] miscompiles __weak */ -+#ifdef __KERNEL__ -+# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101 -+# error Your version of gcc miscompiles the __weak directive -+# endif -+#endif -+ -+#define __used __attribute__((__used__)) -+#define __compiler_offsetof(a, b) \ -+ __builtin_offsetof(a, b) -+ -+#if GCC_VERSION >= 40100 && GCC_VERSION < 40600 -+# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) -+#endif -+ -+#if GCC_VERSION >= 40300 -+/* Mark functions as cold. gcc will assume any path leading to a call -+ * to them will be unlikely. This means a lot of manual unlikely()s -+ * are unnecessary now for any paths leading to the usual suspects -+ * like BUG(), printk(), panic() etc. [but let's keep them for now for -+ * older compilers] -+ * -+ * Early snapshots of gcc 4.3 don't support this and we can't detect this -+ * in the preprocessor, but we can live with this because they're unreleased. -+ * Maketime probing would be overkill here. -+ * -+ * gcc also has a __attribute__((__hot__)) to move hot functions into -+ * a special section, but I don't see any sense in this right now in -+ * the kernel context -+ */ -+#define __cold __attribute__((__cold__)) -+ -+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) -+ -+#ifndef __CHECKER__ -+# define __compiletime_warning(message) __attribute__((warning(message))) -+# define __compiletime_error(message) __attribute__((error(message))) -+#endif /* __CHECKER__ */ -+#endif /* GCC_VERSION >= 40300 */ -+ -+#if GCC_VERSION >= 40500 -+/* -+ * Mark a position in code as unreachable. This can be used to -+ * suppress control flow warnings after asm blocks that transfer -+ * control elsewhere. -+ * -+ * Early snapshots of gcc 4.5 don't support this and we can't detect -+ * this in the preprocessor, but we can live with this because they're -+ * unreleased. Really, we need to have autoconf for the kernel. -+ */ -+#define unreachable() __builtin_unreachable() -+ -+/* Mark a function definition as prohibited from being cloned. */ -+#define __noclone __attribute__((__noclone__)) -+ -+#endif /* GCC_VERSION >= 40500 */ -+ -+#if GCC_VERSION >= 40600 -+/* -+ * Tell the optimizer that something else uses this function or variable. -+ */ -+#define __visible __attribute__((externally_visible)) -+#endif -+ -+/* -+ * GCC 'asm goto' miscompiles certain code sequences: -+ * -+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 -+ * -+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. -+ * -+ * (asm goto is automatically volatile - the naming reflects this.) -+ */ -+#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) -+ -+#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP -+#if GCC_VERSION >= 40400 -+#define __HAVE_BUILTIN_BSWAP32__ -+#define __HAVE_BUILTIN_BSWAP64__ -+#endif -+#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600) -+#define __HAVE_BUILTIN_BSWAP16__ -+#endif -+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ -+ -+#if GCC_VERSION >= 50000 -+#define KASAN_ABI_VERSION 4 -+#elif GCC_VERSION >= 40902 -+#define KASAN_ABI_VERSION 3 -+#endif -+ -+#endif /* gcc version >= 40000 specific checks */ - - #if !defined(__noclone) - #define __noclone /* not needed */ --- -cgit v0.12 -