From 4344e2a16b8ce3a5fb69b5c19c6057f22bbfc5e8 Mon Sep 17 00:00:00 2001 From: Gerald Dachs Date: Tue, 22 Mar 2016 19:34:58 +0100 Subject: [PATCH] libcec: repaired detection of logical address; prevent that amlogic adapter hangs on close --- .../patches/libcec-03-amlogic-support.patch | 296 ++++++++++-------- .../linux/080-amlogic-cec-driver.patch | 171 +++++++--- .../linux/080-amlogic-cec-driver.patch | 171 +++++++--- 3 files changed, 410 insertions(+), 228 deletions(-) diff --git a/packages/devel/libcec/patches/libcec-03-amlogic-support.patch b/packages/devel/libcec/patches/libcec-03-amlogic-support.patch index 8d58b75439..390a7e7615 100644 --- a/packages/devel/libcec/patches/libcec-03-amlogic-support.patch +++ b/packages/devel/libcec/patches/libcec-03-amlogic-support.patch @@ -1,36 +1,7 @@ -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/include/cectypes.h libcec-3.0.1-with-amlogic-adapter/include/cectypes.h ---- libcec-3.0.1/include/cectypes.h 2016-02-21 01:11:20.791177759 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/include/cectypes.h 2016-02-10 13:45:19.057046951 +0100 -@@ -320,6 +320,16 @@ - - - /*! -+ * the path to use for the Amlogic HDMI CEC device -+ */ -+#define CEC_AMLOGIC_PATH "/dev/AmlogicCEC" -+ -+/*! -+ * the name of the virtual COM port to use for the AMLOGIC' CEC wire -+ */ -+#define CEC_AMLOGIC_VIRTUAL_COM "Amlogic" -+ -+/*! - * Mimimum client version - */ - #define CEC_MIN_LIB_VERSION 3 -@@ -888,7 +898,8 @@ - ADAPTERTYPE_RPI = 0x100, - ADAPTERTYPE_TDA995x = 0x200, - ADAPTERTYPE_EXYNOS = 0x300, -- ADAPTERTYPE_IMX = 0x400 -+ ADAPTERTYPE_IMX = 0x400, -+ ADAPTERTYPE_AMLOGIC = 0x500 - } cec_adapter_type; - - /** force exporting through swig */ -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/README.md libcec-3.0.1-with-amlogic-adapter/README.md ---- libcec-3.0.1/README.md 2015-07-03 19:20:49.000000000 +0200 -+++ libcec-3.0.1-with-amlogic-adapter/README.md 2016-02-10 12:03:54.517523977 +0100 +diff --git a/README.md b/README.md +index dfaf4d6..0dffdcf 100644 +--- a/README.md ++++ b/README.md @@ -58,6 +58,12 @@ cmake -DHAVE_EXYNOS_API=1 .. ``` @@ -44,9 +15,54 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/README.md libcec-3. ## TDA995x ## To compile in support for TDA995x devices, you have to pass the argument -DHAVE_TDA995X_API=1 to cmake: ``` -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/AdapterFactory.cpp libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/AdapterFactory.cpp ---- libcec-3.0.1/src/libcec/adapter/AdapterFactory.cpp 2016-02-21 01:11:12.579266950 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/AdapterFactory.cpp 2016-02-10 12:41:44.252060917 +0100 +diff --git a/include/cectypes.h b/include/cectypes.h +index e28c8df..c0b9476 100644 +--- a/include/cectypes.h ++++ b/include/cectypes.h +@@ -318,6 +318,15 @@ namespace CEC { + */ + #define CEC_IMX_VIRTUAL_COM "i.MX" + ++/*! ++ * the path to use for the Amlogic HDMI CEC device ++ */ ++#define CEC_AMLOGIC_PATH "/dev/AmlogicCEC" ++ ++/*! ++ * the name of the virtual COM port to use for the AMLOGIC' CEC wire ++ */ ++#define CEC_AMLOGIC_VIRTUAL_COM "Amlogic" + + /*! + * Mimimum client version +@@ -889,7 +898,8 @@ typedef enum cec_adapter_type + ADAPTERTYPE_RPI = 0x100, + ADAPTERTYPE_TDA995x = 0x200, + ADAPTERTYPE_EXYNOS = 0x300, +- ADAPTERTYPE_IMX = 0x400 ++ ADAPTERTYPE_IMX = 0x400, ++ ADAPTERTYPE_AMLOGIC = 0x500 + } cec_adapter_type; + + /** force exporting through swig */ +diff --git a/src/libcec/CMakeLists.txt b/src/libcec/CMakeLists.txt +index a494533..e94b094 100644 +--- a/src/libcec/CMakeLists.txt ++++ b/src/libcec/CMakeLists.txt +@@ -87,6 +87,9 @@ set(CEC_HEADERS devices/CECRecordingDevice.h + adapter/Exynos/ExynosCEC.h + adapter/Exynos/ExynosCECAdapterDetection.h + adapter/Exynos/ExynosCECAdapterCommunication.h ++ adapter/Amlogic/AmlogicCEC.h ++ adapter/Amlogic/AmlogicCECAdapterDetection.h ++ adapter/Amlogic/AmlogicCECAdapterCommunication.h + adapter/Pulse-Eight/USBCECAdapterMessageQueue.h + adapter/Pulse-Eight/USBCECAdapterCommunication.h + adapter/Pulse-Eight/USBCECAdapterCommands.h +diff --git a/src/libcec/adapter/AdapterFactory.cpp b/src/libcec/adapter/AdapterFactory.cpp +index 92e378b..55703b9 100644 +--- a/src/libcec/adapter/AdapterFactory.cpp ++++ b/src/libcec/adapter/AdapterFactory.cpp @@ -63,6 +63,11 @@ #include "IMX/IMXCECAdapterCommunication.h" #endif @@ -59,7 +75,16 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ using namespace CEC; int8_t CAdapterFactory::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */) -@@ -131,6 +136,18 @@ +@@ -131,8 +136,6 @@ 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))) +@@ -146,8 +149,20 @@ int8_t CAdapterFactory::DetectAdapters(cec_adapter_descriptor *deviceList, uint8 } #endif @@ -74,12 +99,15 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ + iAdaptersFound++; + } +#endif + +-#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_IMX_API) + ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_IMX_API) && !defined(HAVE_AMLOGIC_API) + #error "libCEC doesn't have support for any type of adapter. please check your build system or configuration" + #endif - - #if defined(HAVE_IMX_API) -@@ -166,6 +183,11 @@ - return new CExynosCECAdapterCommunication(m_lib->m_cec); +@@ -176,11 +191,16 @@ IAdapterCommunication *CAdapterFactory::GetInstance(const char *strPort, uint16_ + return new CIMXCECAdapterCommunication(m_lib->m_cec); #endif +#if defined(HAVE_AMLOGIC_API) @@ -87,22 +115,68 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ + return new CAmlogicCECAdapterCommunication(m_lib->m_cec); +#endif + - #if defined(HAVE_RPI_API) - if (!strcmp(strPort, CEC_RPI_VIRTUAL_COM)) - return new CRPiCECAdapterCommunication(m_lib->m_cec); -@@ -180,7 +202,7 @@ + #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) && !defined(HAVE_IMX_API) -+#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API) && !defined(HAVE_AMLOGIC_API) ++#if !defined(HAVE_RPI_API) && !defined(HAVE_P8_USB) && !defined(HAVE_TDA995X_API) && !defined(HAVE_EXYNOS_API) && !defined(HAVE_IMX_API) && !defined(HAVE_AMLOGIC_API) return NULL; #endif } -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp ---- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp 1970-01-01 01:00:00.000000000 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp 2016-02-28 12:31:26.771045268 +0100 -@@ -0,0 +1,298 @@ +diff --git a/src/libcec/adapter/Amlogic/AmlogicCEC.h b/src/libcec/adapter/Amlogic/AmlogicCEC.h +new file mode 100644 +index 0000000..7b86982 +--- /dev/null ++++ b/src/libcec/adapter/Amlogic/AmlogicCEC.h +@@ -0,0 +1,41 @@ ++#pragma once ++/* ++ * This file is part of the libCEC(R) library. ++ * ++ * libCEC Amlogic Code Copyright (C) 2016 Gerald Dachs ++ * based heavily on: ++ * libCEC Exynos Code Copyright (C) 2014 Valentin Manea ++ * 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., 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/ ++ */ ++ ++ ++#define CEC_DEFAULT_PADDR 0x1000 ++#define CEC_IOC_SETLADDR _IOW('c', 0, unsigned int) ++#define CEC_IOC_GETPADDR _IO('c', 1) ++#define CEC_MAX_FRAME_SIZE 16 +diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp +new file mode 100644 +index 0000000..5aeddda +--- /dev/null ++++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.cpp +@@ -0,0 +1,305 @@ +/* + * This file is part of the libCEC(R) library. + * @@ -346,6 +420,7 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ + uint32_t size; + fd_set rfds; + cec_logical_address initiator, destination; ++ struct timeval tv; + + if (!IsOpen()) + return 0; @@ -362,8 +437,15 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + -+ if (select(fd + 1, &rfds, NULL, NULL, NULL) >= 0 ) ++ tv.tv_sec = 1; ++ tv.tv_usec = 0; ++ ++ if (select(fd + 1, &rfds, NULL, NULL, &tv) >= 0 ) + { ++ ++ if (!FD_ISSET(fd, &rfds)) ++ continue; ++ + size = read(fd, buffer, CEC_MAX_FRAME_SIZE); + + if (size > 0) @@ -394,16 +476,17 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ + m_callback->OnCommandReceived(cmd); + } + } -+ + } + + return 0; +} + +#endif // HAVE_AMLOGIC_API -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h ---- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h 1970-01-01 01:00:00.000000000 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h 2016-02-28 12:16:30.985474428 +0100 +diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h +new file mode 100644 +index 0000000..0e99cf8 +--- /dev/null ++++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterCommunication.h @@ -0,0 +1,105 @@ +#pragma once +/* @@ -510,9 +593,11 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ + }; +}; +#endif -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp ---- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp 1970-01-01 01:00:00.000000000 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp 2016-02-10 11:57:58.445532459 +0100 +diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp +new file mode 100644 +index 0000000..2247346 +--- /dev/null ++++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of the libCEC(R) library. @@ -564,9 +649,11 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ +} + +#endif -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h ---- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h 1970-01-01 01:00:00.000000000 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h 2016-02-10 11:57:58.445532459 +0100 +diff --git a/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h +new file mode 100644 +index 0000000..8a7418d +--- /dev/null ++++ b/src/libcec/adapter/Amlogic/AmlogicCECAdapterDetection.h @@ -0,0 +1,46 @@ +#pragma once +/* @@ -614,54 +701,10 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/ + static bool FindAdapter(void); + }; +} -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCEC.h libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCEC.h ---- libcec-3.0.1/src/libcec/adapter/Amlogic/AmlogicCEC.h 1970-01-01 01:00:00.000000000 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/adapter/Amlogic/AmlogicCEC.h 2016-02-10 11:57:58.445532459 +0100 -@@ -0,0 +1,41 @@ -+#pragma once -+/* -+ * This file is part of the libCEC(R) library. -+ * -+ * libCEC Amlogic Code Copyright (C) 2016 Gerald Dachs -+ * based heavily on: -+ * libCEC Exynos Code Copyright (C) 2014 Valentin Manea -+ * 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., 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/ -+ */ -+ -+ -+#define CEC_DEFAULT_PADDR 0x1000 -+#define CEC_IOC_SETLADDR _IOW('c', 0, unsigned int) -+#define CEC_IOC_GETPADDR _IO('c', 1) -+#define CEC_MAX_FRAME_SIZE 16 -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/CheckPlatformSupport.cmake libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/CheckPlatformSupport.cmake ---- libcec-3.0.1/src/libcec/cmake/CheckPlatformSupport.cmake 2016-02-21 01:11:12.579266950 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/CheckPlatformSupport.cmake 2016-02-10 13:18:20.847385373 +0100 +diff --git a/src/libcec/cmake/CheckPlatformSupport.cmake b/src/libcec/cmake/CheckPlatformSupport.cmake +index dc5bc25..64003d9 100644 +--- a/src/libcec/cmake/CheckPlatformSupport.cmake ++++ b/src/libcec/cmake/CheckPlatformSupport.cmake @@ -11,6 +11,7 @@ # HAVE_IMX_API 1 if i.MX is supported # HAVE_TDA995X_API 1 if TDA995X is supported @@ -670,7 +713,7 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/Ch # HAVE_P8_USB_DETECT 1 if Pulse-Eight devices can be auto-detected # -@@ -129,6 +130,18 @@ +@@ -142,6 +143,18 @@ else() else() set(HAVE_EXYNOS_API 0) endif() @@ -689,11 +732,12 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/Ch endif() # rt -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/DisplayPlatformSupport.cmake libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/DisplayPlatformSupport.cmake ---- libcec-3.0.1/src/libcec/cmake/DisplayPlatformSupport.cmake 2016-02-21 01:11:12.579266950 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/cmake/DisplayPlatformSupport.cmake 2016-02-10 12:47:10.380408360 +0100 -@@ -50,6 +50,12 @@ - message(STATUS "Exynos support: no") +diff --git a/src/libcec/cmake/DisplayPlatformSupport.cmake b/src/libcec/cmake/DisplayPlatformSupport.cmake +index 4e24def..1890cac 100644 +--- a/src/libcec/cmake/DisplayPlatformSupport.cmake ++++ b/src/libcec/cmake/DisplayPlatformSupport.cmake +@@ -50,6 +50,12 @@ else() + message(STATUS "DRM support: no") endif() +if (HAVE_AMLOGIC_API) @@ -705,23 +749,11 @@ diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/cmake/Di if (HAVE_PYTHON) message(STATUS "Python support: version ${PYTHONLIBS_VERSION_STRING} (${PYTHON_VERSION})") else() -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/CMakeLists.txt libcec-3.0.1-with-amlogic-adapter/src/libcec/CMakeLists.txt ---- libcec-3.0.1/src/libcec/CMakeLists.txt 2015-07-03 19:20:49.000000000 +0200 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/CMakeLists.txt 2016-02-10 11:57:58.445532459 +0100 -@@ -83,6 +83,9 @@ - adapter/Exynos/ExynosCEC.h - adapter/Exynos/ExynosCECAdapterDetection.h - adapter/Exynos/ExynosCECAdapterCommunication.h -+ adapter/Amlogic/AmlogicCEC.h -+ adapter/Amlogic/AmlogicCECAdapterDetection.h -+ adapter/Amlogic/AmlogicCECAdapterCommunication.h - adapter/Pulse-Eight/USBCECAdapterMessageQueue.h - adapter/Pulse-Eight/USBCECAdapterCommunication.h - adapter/Pulse-Eight/USBCECAdapterCommands.h -diff -Nur -x .cproject -x .project -x .settings libcec-3.0.1/src/libcec/env.h.in libcec-3.0.1-with-amlogic-adapter/src/libcec/env.h.in ---- libcec-3.0.1/src/libcec/env.h.in 2016-02-21 01:11:12.579266950 +0100 -+++ libcec-3.0.1-with-amlogic-adapter/src/libcec/env.h.in 2016-02-10 11:57:58.449532413 +0100 -@@ -69,6 +69,9 @@ +diff --git a/src/libcec/env.h.in b/src/libcec/env.h.in +index 384f1c7..c3f00bc 100644 +--- a/src/libcec/env.h.in ++++ b/src/libcec/env.h.in +@@ -75,6 +75,9 @@ /* Define to 1 for Exynos support */ #cmakedefine HAVE_EXYNOS_API @HAVE_EXYNOS_API@ diff --git a/projects/WeTek_Core/patches/linux/080-amlogic-cec-driver.patch b/projects/WeTek_Core/patches/linux/080-amlogic-cec-driver.patch index 5d72bcde96..12dcacca90 100644 --- a/projects/WeTek_Core/patches/linux/080-amlogic-cec-driver.patch +++ b/projects/WeTek_Core/patches/linux/080-amlogic-cec-driver.patch @@ -55,10 +55,10 @@ index 7a944cd..f74ec1f 100755 #EXTRA_CFLAGS += -O2 diff --git a/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c new file mode 100644 -index 0000000..bd31aaa +index 0000000..a3556b3 --- /dev/null +++ b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c -@@ -0,0 +1,596 @@ +@@ -0,0 +1,671 @@ +/* linux/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c + * + * Copyright (c) 2016 Gerald Dachs @@ -84,6 +84,7 @@ index 0000000..bd31aaa +#include +#include +#include ++#include + +#include +#include @@ -127,6 +128,8 @@ index 0000000..bd31aaa +/* CEC Tx buffer size */ +#define CEC_TX_BUFF_SIZE 16 + ++static DEFINE_SEMAPHORE(init_mutex); ++ +struct cec_rx_list { + u8 buffer[CEC_RX_BUFF_SIZE]; + unsigned char size; @@ -226,7 +229,7 @@ index 0000000..bd31aaa + rx_msg_status = amlogic_cec_read_reg(CEC_RX_MSG_STATUS); + rx_num_msg = amlogic_cec_read_reg(CEC_RX_NUM_MSG); + -+ amlogic_cec_log_dbg("amlogic_cec_read_hw: enter: CEC_RX_MSG_STATUS %d, CEC_RX_NUM_MSG %d\n", rx_msg_status, rx_num_msg); ++ amlogic_cec_log_dbg("rx_msg_status: %d, rx_num_msg: %d\n", rx_msg_status, rx_num_msg); + + valid_msg = (RX_DONE == rx_msg_status) && (1 == rx_num_msg); + @@ -248,7 +251,7 @@ index 0000000..bd31aaa +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 + aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2)); +#endif -+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_ACK_NEXT); ++ amlogic_cec_write_reg(CEC_RX_MSG_CMD, valid_msg ? RX_ACK_NEXT : RX_ACK_CURRENT); + amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_NO_OP); + + return ret; @@ -290,45 +293,89 @@ index 0000000..bd31aaa + if (hdmitx_device->hdmi_info.vsdb_phy_addr.valid == 0) + { + amlogic_cec_log_dbg("no valid cec physical address\n"); -+ if (aml_read_reg32(P_AO_DEBUG_REG1)) ++ if (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff) + { + amlogic_cec_log_dbg("use last physical address\n"); + } + else + { -+ aml_write_reg32(P_AO_DEBUG_REG1, 0x1000); ++ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | 0x1000); + amlogic_cec_log_dbg("use default physical address\n"); + } + } + else + { -+ aml_write_reg32(P_AO_DEBUG_REG1, cec_phy_addr); -+ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1)); -+ -+ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0)) -+ { -+ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL) ++ if (cec_global_info.my_node_index) ++ { ++ // prevent write operations ++ if (down_interruptible(&init_mutex)) + { -+ amlogic_cec_log_dbg("can't alloc cec_rx_list\n"); ++ printk(KERN_ERR "[amlogic] ##### cec node init interrupted! #####\n"); ++ return; + } -+ else ++ hdmitx_device->cec_init_ready = 0; ++ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); ++ ++ amlogic_cec_log_dbg("start reset\n"); ++#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 ++ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<16)); ++ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0xc); //[3]cec_creg_sw_rst [2]cec_sys_sw_rst ++ ++#if 0 ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x1); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x1); ++ ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x0); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x0); ++#endif ++ ++ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0x0); ++ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)&(~(1<<16))); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 ); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 ); ++ ++#endif ++#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 ++ // regain rx interrupts ++ cec_enable_irq(); ++#endif ++ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); ++ ++ hdmitx_device->cec_init_ready = 1; ++ ++ up(&init_mutex); ++ amlogic_cec_log_dbg("stop reset\n"); ++ } ++ ++ if ((aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff) != cec_phy_addr) ++ { ++ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | cec_phy_addr); ++ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff); ++ ++ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0)) + { -+ // let the libCEC ask for new physical Address -+ entry->buffer[0] = 0xff; -+ entry->size = 1; -+ INIT_LIST_HEAD(&entry->list); ++ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL) ++ { ++ amlogic_cec_log_dbg("can't alloc cec_rx_list\n"); ++ } ++ else ++ { ++ // let the libCEC ask for new physical Address ++ entry->buffer[0] = 0xff; ++ entry->size = 1; ++ INIT_LIST_HEAD(&entry->list); + -+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); -+ list_add_tail(&entry->list, &cec_rx_struct.list); -+ amlogic_cec_set_rx_state(STATE_DONE); -+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); ++ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); ++ list_add_tail(&entry->list, &cec_rx_struct.list); ++ amlogic_cec_set_rx_state(STATE_DONE); ++ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); + -+ amlogic_cec_log_dbg("trigger libCEC\n"); -+ wake_up_interruptible(&cec_rx_struct.waitq); ++ amlogic_cec_log_dbg("trigger libCEC\n"); ++ wake_up_interruptible(&cec_rx_struct.waitq); ++ } + } -+ } ++ } + } -+ amlogic_cec_log_dbg("cec node init: cec features ok !\n"); +} + +static irqreturn_t amlogic_cec_irq_handler(int irq, void *dummy) @@ -338,7 +385,9 @@ index 0000000..bd31aaa + unsigned int tx_msg_state; + unsigned int rx_msg_state; + ++#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + udelay(100); //Delay execution a little. This fixes an issue when HDMI CEC stops working after a while. ++#endif + + tx_msg_state = amlogic_cec_read_reg(CEC_TX_MSG_STATUS); + rx_msg_state = amlogic_cec_read_reg(CEC_RX_MSG_STATUS); @@ -356,9 +405,6 @@ index 0000000..bd31aaa + case TX_DONE : + amlogic_cec_set_tx_state(STATE_DONE); + break; -+ default : -+ amlogic_cec_log_dbg("unexpected ts message state: 0x%x", tx_msg_state); -+ break; + } + wake_up_interruptible(&cec_tx_struct.waitq); + } @@ -372,16 +418,18 @@ index 0000000..bd31aaa + return IRQ_HANDLED; + } + ++ INIT_LIST_HEAD(&entry->list); ++ ++ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); ++ + if ((-1) == amlogic_cec_read_hw(entry->buffer, &entry->size)) + { + kfree(entry); + amlogic_cec_log_dbg("amlogic_cec_irq_handler: nothing to read\n"); ++ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); + return IRQ_HANDLED; + } + -+ INIT_LIST_HEAD(&entry->list); -+ -+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); + list_add_tail(&entry->list, &cec_rx_struct.list); + amlogic_cec_set_rx_state(STATE_DONE); + spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); @@ -432,21 +480,17 @@ index 0000000..bd31aaa + aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK, aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK) | (1 << 23)); // Enable the hdmi cec interrupt +#endif +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 -+#if 1 // Please match with H/W cec config +// GPIOAO_12 + aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 0, 14, 1); // bit[14]: AO_PWM_C pinmux //0xc8100014 + aml_set_reg32_bits(P_AO_RTI_PULL_UP_REG, 1, 12, 1); // bit[12]: enable AO_12 internal pull-up //0xc810002c + aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 1, 17, 1); // bit[17]: AO_CEC pinmux //0xc8100014 + ao_cec_init(); -+#else -+// GPIOH_3 -+ aml_set_reg32_bits(P_PAD_PULL_UP_EN_REG1, 0, 19, 1); // disable gpioh_3 internal pull-up -+ aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 1, 23, 1); // gpioh_3 cec pinmux -+#endif + cec_arbit_bit_time_set(3, 0x118, 0); + cec_arbit_bit_time_set(5, 0x000, 0); + cec_arbit_bit_time_set(7, 0x2aa, 0); +#endif ++ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf); ++ + hdmitx_device->cec_init_ready = 1; + + } @@ -463,6 +507,8 @@ index 0000000..bd31aaa + free_irq(INT_AO_CEC, (void *)hdmitx_device); +#endif + ++ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf); ++ + atomic_dec(&hdmi_on); + + return 0; @@ -520,6 +566,7 @@ index 0000000..bd31aaa +static ssize_t amlogic_cec_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ ++ int retval = count; + char data[CEC_TX_BUFF_SIZE]; + + /* check data size */ @@ -534,9 +581,8 @@ index 0000000..bd31aaa + + amlogic_cec_set_tx_state(STATE_TX); + -+ // just for the case that the first write starts -+ // before the end of amlogic_cec_delayed_init() -+ if (wait_event_interruptible(cec_tx_struct.waitq, hdmitx_device->cec_init_ready == 1)) ++ // don't write if cec_node_init() is in progress ++ if (down_interruptible(&init_mutex)) + { + amlogic_cec_log_dbg("error during wait on state change\n"); + printk(KERN_ERR "[amlogic] ##### cec write error! #####\n"); @@ -552,22 +598,27 @@ index 0000000..bd31aaa + printk(KERN_ERR "[amlogic] ##### cec write error! #####\n"); + amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_ABORT); // stop cec tx for hw retry. + amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_NO_OP); -+ return -ERESTARTSYS; ++ retval = -ERESTARTSYS; ++ goto error_exit; + } + + if (atomic_read(&cec_tx_struct.state) != STATE_DONE) + { + printk(KERN_ERR "[amlogic] ##### cec write error! #####\n"); -+ return -1; ++ retval = -1; + } + -+ return count; ++error_exit: ++ up(&init_mutex); ++ ++ return retval; +} + +static long amlogic_cec_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned char logical_addr; ++ unsigned int reg; + + switch(cmd) { + case CEC_IOC_SETLADDR: @@ -578,12 +629,21 @@ index 0000000..bd31aaa + } + + amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | logical_addr); ++ cec_global_info.my_node_index = logical_addr; ++ /* ++ * use DEBUG_REG1 bit 16 ~ 31 to save logic address. ++ * So uboot can use this logic address directly ++ */ ++ reg = (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff); ++ reg |= ((unsigned int)logical_addr) << 16; ++ aml_write_reg32(P_AO_DEBUG_REG1, reg); ++ + amlogic_cec_log_dbg("amlogic_cec_ioctl: Set logical address: %d\n", logical_addr); + return 0; + + case CEC_IOC_GETPADDR: -+ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1)); -+ return aml_read_reg32(P_AO_DEBUG_REG1); ++ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff); ++ return aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff; + } + + return -EINVAL; @@ -618,13 +678,23 @@ index 0000000..bd31aaa + +static int amlogic_cec_init(void) +{ ++ int retval = 0; + extern hdmitx_dev_t * get_hdmitx_device(void); ++ ++ if (down_interruptible(&init_mutex)) ++ { ++ return -ERESTARTSYS; ++ } ++ + INIT_LIST_HEAD(&cec_rx_struct.list); + + printk("%s, Version: %s\n", banner, VERSION); + + hdmitx_device = get_hdmitx_device(); + amlogic_cec_log_dbg("CEC init\n"); ++ ++ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf); ++ +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 ); + hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 ); @@ -641,10 +711,15 @@ index 0000000..bd31aaa + if (misc_register(&cec_misc_device)) + { + printk(KERN_WARNING " Couldn't register device 10, %d.\n", CEC_MINOR); -+ return -EBUSY; ++ retval = -EBUSY; + } + -+ return 0; ++ // release initial lock on init_mutex ++ up(&init_mutex); ++ ++ amlogic_cec_log_dbg("CEC init finished: %d\n", retval); ++ ++ return retval; +} + +static void amlogic_cec_exit(void) diff --git a/projects/WeTek_Play/patches/linux/080-amlogic-cec-driver.patch b/projects/WeTek_Play/patches/linux/080-amlogic-cec-driver.patch index 5d72bcde96..12dcacca90 100644 --- a/projects/WeTek_Play/patches/linux/080-amlogic-cec-driver.patch +++ b/projects/WeTek_Play/patches/linux/080-amlogic-cec-driver.patch @@ -55,10 +55,10 @@ index 7a944cd..f74ec1f 100755 #EXTRA_CFLAGS += -O2 diff --git a/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c new file mode 100644 -index 0000000..bd31aaa +index 0000000..a3556b3 --- /dev/null +++ b/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c -@@ -0,0 +1,596 @@ +@@ -0,0 +1,671 @@ +/* linux/drivers/amlogic/hdmi/hdmi_tx/amlogic_cec.c + * + * Copyright (c) 2016 Gerald Dachs @@ -84,6 +84,7 @@ index 0000000..bd31aaa +#include +#include +#include ++#include + +#include +#include @@ -127,6 +128,8 @@ index 0000000..bd31aaa +/* CEC Tx buffer size */ +#define CEC_TX_BUFF_SIZE 16 + ++static DEFINE_SEMAPHORE(init_mutex); ++ +struct cec_rx_list { + u8 buffer[CEC_RX_BUFF_SIZE]; + unsigned char size; @@ -226,7 +229,7 @@ index 0000000..bd31aaa + rx_msg_status = amlogic_cec_read_reg(CEC_RX_MSG_STATUS); + rx_num_msg = amlogic_cec_read_reg(CEC_RX_NUM_MSG); + -+ amlogic_cec_log_dbg("amlogic_cec_read_hw: enter: CEC_RX_MSG_STATUS %d, CEC_RX_NUM_MSG %d\n", rx_msg_status, rx_num_msg); ++ amlogic_cec_log_dbg("rx_msg_status: %d, rx_num_msg: %d\n", rx_msg_status, rx_num_msg); + + valid_msg = (RX_DONE == rx_msg_status) && (1 == rx_num_msg); + @@ -248,7 +251,7 @@ index 0000000..bd31aaa +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 + aml_write_reg32(P_AO_CEC_INTR_CLR, aml_read_reg32(P_AO_CEC_INTR_CLR) | (1 << 2)); +#endif -+ amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_ACK_NEXT); ++ amlogic_cec_write_reg(CEC_RX_MSG_CMD, valid_msg ? RX_ACK_NEXT : RX_ACK_CURRENT); + amlogic_cec_write_reg(CEC_RX_MSG_CMD, RX_NO_OP); + + return ret; @@ -290,45 +293,89 @@ index 0000000..bd31aaa + if (hdmitx_device->hdmi_info.vsdb_phy_addr.valid == 0) + { + amlogic_cec_log_dbg("no valid cec physical address\n"); -+ if (aml_read_reg32(P_AO_DEBUG_REG1)) ++ if (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff) + { + amlogic_cec_log_dbg("use last physical address\n"); + } + else + { -+ aml_write_reg32(P_AO_DEBUG_REG1, 0x1000); ++ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | 0x1000); + amlogic_cec_log_dbg("use default physical address\n"); + } + } + else + { -+ aml_write_reg32(P_AO_DEBUG_REG1, cec_phy_addr); -+ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1)); -+ -+ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0)) -+ { -+ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL) ++ if (cec_global_info.my_node_index) ++ { ++ // prevent write operations ++ if (down_interruptible(&init_mutex)) + { -+ amlogic_cec_log_dbg("can't alloc cec_rx_list\n"); ++ printk(KERN_ERR "[amlogic] ##### cec node init interrupted! #####\n"); ++ return; + } -+ else ++ hdmitx_device->cec_init_ready = 0; ++ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); ++ ++ amlogic_cec_log_dbg("start reset\n"); ++#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 ++ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)|(1<<16)); ++ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0xc); //[3]cec_creg_sw_rst [2]cec_sys_sw_rst ++ ++#if 0 ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x1); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x1); ++ ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_TX_CLEAR_BUF, 0x0); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_RX_CLEAR_BUF, 0x0); ++#endif ++ ++ hdmi_wr_reg(OTHER_BASE_ADDR+HDMI_OTHER_CTRL0, 0x0); ++ aml_write_reg32(P_HDMI_CTRL_PORT, aml_read_reg32(P_HDMI_CTRL_PORT)&(~(1<<16))); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 ); ++ hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 ); ++ ++#endif ++#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 ++ // regain rx interrupts ++ cec_enable_irq(); ++#endif ++ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); ++ ++ hdmitx_device->cec_init_ready = 1; ++ ++ up(&init_mutex); ++ amlogic_cec_log_dbg("stop reset\n"); ++ } ++ ++ if ((aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff) != cec_phy_addr) ++ { ++ aml_write_reg32(P_AO_DEBUG_REG1, (aml_read_reg32(P_AO_DEBUG_REG1) & (0xf << 16)) | cec_phy_addr); ++ amlogic_cec_log_dbg("physical address:0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff); ++ ++ if ((hdmitx_device->cec_init_ready != 0) && (hdmitx_device->hpd_state != 0)) + { -+ // let the libCEC ask for new physical Address -+ entry->buffer[0] = 0xff; -+ entry->size = 1; -+ INIT_LIST_HEAD(&entry->list); ++ if ((entry = kmalloc(sizeof(struct cec_rx_list), GFP_ATOMIC)) == NULL) ++ { ++ amlogic_cec_log_dbg("can't alloc cec_rx_list\n"); ++ } ++ else ++ { ++ // let the libCEC ask for new physical Address ++ entry->buffer[0] = 0xff; ++ entry->size = 1; ++ INIT_LIST_HEAD(&entry->list); + -+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); -+ list_add_tail(&entry->list, &cec_rx_struct.list); -+ amlogic_cec_set_rx_state(STATE_DONE); -+ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); ++ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); ++ list_add_tail(&entry->list, &cec_rx_struct.list); ++ amlogic_cec_set_rx_state(STATE_DONE); ++ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); + -+ amlogic_cec_log_dbg("trigger libCEC\n"); -+ wake_up_interruptible(&cec_rx_struct.waitq); ++ amlogic_cec_log_dbg("trigger libCEC\n"); ++ wake_up_interruptible(&cec_rx_struct.waitq); ++ } + } -+ } ++ } + } -+ amlogic_cec_log_dbg("cec node init: cec features ok !\n"); +} + +static irqreturn_t amlogic_cec_irq_handler(int irq, void *dummy) @@ -338,7 +385,9 @@ index 0000000..bd31aaa + unsigned int tx_msg_state; + unsigned int rx_msg_state; + ++#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + udelay(100); //Delay execution a little. This fixes an issue when HDMI CEC stops working after a while. ++#endif + + tx_msg_state = amlogic_cec_read_reg(CEC_TX_MSG_STATUS); + rx_msg_state = amlogic_cec_read_reg(CEC_RX_MSG_STATUS); @@ -356,9 +405,6 @@ index 0000000..bd31aaa + case TX_DONE : + amlogic_cec_set_tx_state(STATE_DONE); + break; -+ default : -+ amlogic_cec_log_dbg("unexpected ts message state: 0x%x", tx_msg_state); -+ break; + } + wake_up_interruptible(&cec_tx_struct.waitq); + } @@ -372,16 +418,18 @@ index 0000000..bd31aaa + return IRQ_HANDLED; + } + ++ INIT_LIST_HEAD(&entry->list); ++ ++ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); ++ + if ((-1) == amlogic_cec_read_hw(entry->buffer, &entry->size)) + { + kfree(entry); + amlogic_cec_log_dbg("amlogic_cec_irq_handler: nothing to read\n"); ++ spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); + return IRQ_HANDLED; + } + -+ INIT_LIST_HEAD(&entry->list); -+ -+ spin_lock_irqsave(&cec_rx_struct.lock, spin_flags); + list_add_tail(&entry->list, &cec_rx_struct.list); + amlogic_cec_set_rx_state(STATE_DONE); + spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags); @@ -432,21 +480,17 @@ index 0000000..bd31aaa + aml_write_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK, aml_read_reg32(P_SYS_CPU_0_IRQ_IN1_INTR_MASK) | (1 << 23)); // Enable the hdmi cec interrupt +#endif +#if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 -+#if 1 // Please match with H/W cec config +// GPIOAO_12 + aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 0, 14, 1); // bit[14]: AO_PWM_C pinmux //0xc8100014 + aml_set_reg32_bits(P_AO_RTI_PULL_UP_REG, 1, 12, 1); // bit[12]: enable AO_12 internal pull-up //0xc810002c + aml_set_reg32_bits(P_AO_RTI_PIN_MUX_REG, 1, 17, 1); // bit[17]: AO_CEC pinmux //0xc8100014 + ao_cec_init(); -+#else -+// GPIOH_3 -+ aml_set_reg32_bits(P_PAD_PULL_UP_EN_REG1, 0, 19, 1); // disable gpioh_3 internal pull-up -+ aml_set_reg32_bits(P_PERIPHS_PIN_MUX_1, 1, 23, 1); // gpioh_3 cec pinmux -+#endif + cec_arbit_bit_time_set(3, 0x118, 0); + cec_arbit_bit_time_set(5, 0x000, 0); + cec_arbit_bit_time_set(7, 0x2aa, 0); +#endif ++ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf); ++ + hdmitx_device->cec_init_ready = 1; + + } @@ -463,6 +507,8 @@ index 0000000..bd31aaa + free_irq(INT_AO_CEC, (void *)hdmitx_device); +#endif + ++ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf); ++ + atomic_dec(&hdmi_on); + + return 0; @@ -520,6 +566,7 @@ index 0000000..bd31aaa +static ssize_t amlogic_cec_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ ++ int retval = count; + char data[CEC_TX_BUFF_SIZE]; + + /* check data size */ @@ -534,9 +581,8 @@ index 0000000..bd31aaa + + amlogic_cec_set_tx_state(STATE_TX); + -+ // just for the case that the first write starts -+ // before the end of amlogic_cec_delayed_init() -+ if (wait_event_interruptible(cec_tx_struct.waitq, hdmitx_device->cec_init_ready == 1)) ++ // don't write if cec_node_init() is in progress ++ if (down_interruptible(&init_mutex)) + { + amlogic_cec_log_dbg("error during wait on state change\n"); + printk(KERN_ERR "[amlogic] ##### cec write error! #####\n"); @@ -552,22 +598,27 @@ index 0000000..bd31aaa + printk(KERN_ERR "[amlogic] ##### cec write error! #####\n"); + amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_ABORT); // stop cec tx for hw retry. + amlogic_cec_write_reg(CEC_TX_MSG_CMD, TX_NO_OP); -+ return -ERESTARTSYS; ++ retval = -ERESTARTSYS; ++ goto error_exit; + } + + if (atomic_read(&cec_tx_struct.state) != STATE_DONE) + { + printk(KERN_ERR "[amlogic] ##### cec write error! #####\n"); -+ return -1; ++ retval = -1; + } + -+ return count; ++error_exit: ++ up(&init_mutex); ++ ++ return retval; +} + +static long amlogic_cec_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + unsigned char logical_addr; ++ unsigned int reg; + + switch(cmd) { + case CEC_IOC_SETLADDR: @@ -578,12 +629,21 @@ index 0000000..bd31aaa + } + + amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | logical_addr); ++ cec_global_info.my_node_index = logical_addr; ++ /* ++ * use DEBUG_REG1 bit 16 ~ 31 to save logic address. ++ * So uboot can use this logic address directly ++ */ ++ reg = (aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff); ++ reg |= ((unsigned int)logical_addr) << 16; ++ aml_write_reg32(P_AO_DEBUG_REG1, reg); ++ + amlogic_cec_log_dbg("amlogic_cec_ioctl: Set logical address: %d\n", logical_addr); + return 0; + + case CEC_IOC_GETPADDR: -+ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1)); -+ return aml_read_reg32(P_AO_DEBUG_REG1); ++ amlogic_cec_log_dbg("amlogic_cec_ioctl: return physical address 0x%x\n", aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff); ++ return aml_read_reg32(P_AO_DEBUG_REG1) & 0xffff; + } + + return -EINVAL; @@ -618,13 +678,23 @@ index 0000000..bd31aaa + +static int amlogic_cec_init(void) +{ ++ int retval = 0; + extern hdmitx_dev_t * get_hdmitx_device(void); ++ ++ if (down_interruptible(&init_mutex)) ++ { ++ return -ERESTARTSYS; ++ } ++ + INIT_LIST_HEAD(&cec_rx_struct.list); + + printk("%s, Version: %s\n", banner, VERSION); + + hdmitx_device = get_hdmitx_device(); + amlogic_cec_log_dbg("CEC init\n"); ++ ++ amlogic_cec_write_reg(CEC_LOGICAL_ADDR0, (0x1 << 4) | 0xf); ++ +#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6 + hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_H, 0x00 ); + hdmi_wr_reg(CEC0_BASE_ADDR+CEC_CLOCK_DIV_L, 0xf0 ); @@ -641,10 +711,15 @@ index 0000000..bd31aaa + if (misc_register(&cec_misc_device)) + { + printk(KERN_WARNING " Couldn't register device 10, %d.\n", CEC_MINOR); -+ return -EBUSY; ++ retval = -EBUSY; + } + -+ return 0; ++ // release initial lock on init_mutex ++ up(&init_mutex); ++ ++ amlogic_cec_log_dbg("CEC init finished: %d\n", retval); ++ ++ return retval; +} + +static void amlogic_cec_exit(void)